Commit 1bde8bdd authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-docs'

Make ACPI documentation updates for 5.18-rc1:

 - Update the ACPI device enumeration documentation and unify the ASL
   style in GPIO-related examples (Andy Shevchenko).

* acpi-docs:
  ACPI: docs: gpio-properties: Unify ASL style for GPIO examples
  ACPI: docs: enumeration: Unify Package () for properties
  ACPI: docs: enumeration: Drop comma for terminator entry
  ACPI: docs: enumeration: Drop ugly ifdeffery from the examples
  ACPI: docs: enumeration: Amend PWM enumeration ASL example
  ACPI: docs: enumeration: Remove redundant .owner assignment
  ACPI: docs: enumeration: Update UART serial bus resource documentation
  ACPI: docs: enumeration: Discourage to use custom _DSM methods
parents 8a9bd50a 830751d5
Loading
Loading
Loading
Loading
+9 −12
Original line number Original line Diff line number Diff line
@@ -71,14 +71,14 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::


	Device (FOO) {
	Device (FOO) {
		Name (_CRS, ResourceTemplate () {
		Name (_CRS, ResourceTemplate () {
			GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
				"\\_SB.GPI0") {15} // red
				"\\_SB.GPI0", 0, ResourceConsumer) { 15 } // red
			GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
				"\\_SB.GPI0") {16} // green
				"\\_SB.GPI0", 0, ResourceConsumer) { 16 } // green
			GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
				"\\_SB.GPI0") {17} // blue
				"\\_SB.GPI0", 0, ResourceConsumer) { 17 } // blue
			GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
			GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
				"\\_SB.GPI0") {1} // power
				"\\_SB.GPI0", 0, ResourceConsumer) { 1 } // power
		})
		})


		Name (_DSD, Package () {
		Name (_DSD, Package () {
@@ -92,10 +92,7 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
						^FOO, 2, 0, 1,
						^FOO, 2, 0, 1,
					}
					}
				},
				},
				Package () {
				Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } },
					"power-gpios",
					Package () {^FOO, 3, 0, 0},
				},
			}
			}
		})
		})
	}
	}
+44 −67
Original line number Original line Diff line number Diff line
@@ -19,16 +19,17 @@ possible we decided to do following:
    platform devices.
    platform devices.


  - Devices behind real busses where there is a connector resource
  - Devices behind real busses where there is a connector resource
    are represented as struct spi_device or struct i2c_device
    are represented as struct spi_device or struct i2c_device. Note
    (standard UARTs are not busses so there is no struct uart_device).
    that standard UARTs are not busses so there is no struct uart_device,
    although some of them may be represented by sturct serdev_device.


As both ACPI and Device Tree represent a tree of devices (and their
As both ACPI and Device Tree represent a tree of devices (and their
resources) this implementation follows the Device Tree way as much as
resources) this implementation follows the Device Tree way as much as
possible.
possible.


The ACPI implementation enumerates devices behind busses (platform, SPI and
The ACPI implementation enumerates devices behind busses (platform, SPI,
I2C), creates the physical devices and binds them to their ACPI handle in
I2C, and in some cases UART), creates the physical devices and binds them
the ACPI namespace.
to their ACPI handle in the ACPI namespace.


This means that when ACPI_HANDLE(dev) returns non-NULL the device was
This means that when ACPI_HANDLE(dev) returns non-NULL the device was
enumerated from ACPI namespace. This handle can be used to extract other
enumerated from ACPI namespace. This handle can be used to extract other
@@ -46,18 +47,16 @@ some minor changes.
Adding ACPI support for an existing driver should be pretty
Adding ACPI support for an existing driver should be pretty
straightforward. Here is the simplest example::
straightforward. Here is the simplest example::


	#ifdef CONFIG_ACPI
	static const struct acpi_device_id mydrv_acpi_match[] = {
	static const struct acpi_device_id mydrv_acpi_match[] = {
		/* ACPI IDs here */
		/* ACPI IDs here */
		{ }
		{ }
	};
	};
	MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match);
	MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match);
	#endif


	static struct platform_driver my_driver = {
	static struct platform_driver my_driver = {
		...
		...
		.driver = {
		.driver = {
			.acpi_match_table = ACPI_PTR(mydrv_acpi_match),
			.acpi_match_table = mydrv_acpi_match,
		},
		},
	};
	};


@@ -172,59 +171,51 @@ The SPI device drivers only need to add ACPI IDs in a similar way than with
the platform device drivers. Below is an example where we add ACPI support
the platform device drivers. Below is an example where we add ACPI support
to at25 SPI eeprom driver (this is meant for the above ACPI snippet)::
to at25 SPI eeprom driver (this is meant for the above ACPI snippet)::


	#ifdef CONFIG_ACPI
	static const struct acpi_device_id at25_acpi_match[] = {
	static const struct acpi_device_id at25_acpi_match[] = {
		{ "AT25", 0 },
		{ "AT25", 0 },
		{ },
		{ }
	};
	};
	MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
	MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
	#endif


	static struct spi_driver at25_driver = {
	static struct spi_driver at25_driver = {
		.driver = {
		.driver = {
			...
			...
			.acpi_match_table = ACPI_PTR(at25_acpi_match),
			.acpi_match_table = at25_acpi_match,
		},
		},
	};
	};


Note that this driver actually needs more information like page size of the
Note that this driver actually needs more information like page size of the
eeprom etc. but at the time writing this there is no standard way of
eeprom, etc. This information can be passed via _DSD method like::
passing those. One idea is to return this in _DSM method like::


	Device (EEP0)
	Device (EEP0)
	{
	{
		...
		...
		Method (_DSM, 4, NotSerialized)
		Name (_DSD, Package ()
		{
		{
			Store (Package (6)
			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
			Package ()
			{
			{
				"byte-len", 1024,
				Package () { "size", 1024 },
				"addr-mode", 2,
				Package () { "pagesize", 32 },
				"page-size, 32
				Package () { "address-width", 16 },
			}, Local0)
			}

		})
			// Check UUIDs etc.

			Return (Local0)
	}
	}


Then the at25 SPI driver can get this configuration by calling _DSM on its
Then the at25 SPI driver can get this configuration by calling device property
ACPI handle like::
APIs during ->probe() phase like::

	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_object_list input;
	acpi_status status;

	/* Fill in the input buffer */


	status = acpi_evaluate_object(ACPI_HANDLE(&spi->dev), "_DSM",
	err = device_property_read_u32(dev, "size", &size);
				      &input, &output);
	if (err)
	if (ACPI_FAILURE(status))
		...error handling...
		/* Handle the error */


	/* Extract the data here */
	err = device_property_read_u32(dev, "pagesize", &page_size);
	if (err)
		...error handling...


	kfree(output.pointer);
	err = device_property_read_u32(dev, "address-width", &addr_width);
	if (err)
		...error handling...


I2C serial bus support
I2C serial bus support
======================
======================
@@ -237,26 +228,24 @@ registered.
Below is an example of how to add ACPI support to the existing mpu3050
Below is an example of how to add ACPI support to the existing mpu3050
input driver::
input driver::


	#ifdef CONFIG_ACPI
	static const struct acpi_device_id mpu3050_acpi_match[] = {
	static const struct acpi_device_id mpu3050_acpi_match[] = {
		{ "MPU3050", 0 },
		{ "MPU3050", 0 },
		{ },
		{ }
	};
	};
	MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match);
	MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match);
	#endif


	static struct i2c_driver mpu3050_i2c_driver = {
	static struct i2c_driver mpu3050_i2c_driver = {
		.driver	= {
		.driver	= {
			.name	= "mpu3050",
			.name	= "mpu3050",
			.owner	= THIS_MODULE,
			.pm	= &mpu3050_pm,
			.pm	= &mpu3050_pm,
			.of_match_table = mpu3050_of_match,
			.of_match_table = mpu3050_of_match,
			.acpi_match_table = ACPI_PTR(mpu3050_acpi_match),
			.acpi_match_table = mpu3050_acpi_match,
		},
		},
		.probe		= mpu3050_probe,
		.probe		= mpu3050_probe,
		.remove		= mpu3050_remove,
		.remove		= mpu3050_remove,
		.id_table	= mpu3050_ids,
		.id_table	= mpu3050_ids,
	};
	};
	module_i2c_driver(mpu3050_i2c_driver);


Reference to PWM device
Reference to PWM device
=======================
=======================
@@ -282,9 +271,9 @@ introduced, i.e.::
                    }
                    }
                }
                }
            }
            }

        })
        })
        ...
        ...
    }


In the above example the PWM-based LED driver references to the PWM channel 0
In the above example the PWM-based LED driver references to the PWM channel 0
of \_SB.PCI0.PWM device with initial period setting equal to 600 ms (note that
of \_SB.PCI0.PWM device with initial period setting equal to 600 ms (note that
@@ -306,26 +295,13 @@ For example::
		{
		{
			Name (SBUF, ResourceTemplate()
			Name (SBUF, ResourceTemplate()
			{
			{
				...
				// Used to power on/off the device
				// Used to power on/off the device
				GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
				GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
					IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
					"\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 85 }
					0x00, ResourceConsumer,,)
				{
					// Pin List
					0x0055
				}


				// Interrupt for the device
				// Interrupt for the device
				GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone,
				GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone, 0,
					0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer,,)
					 "\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 88 }
				{
					// Pin list
					0x0058
				}

				...

			}
			}


			Return (SBUF)
			Return (SBUF)
@@ -342,6 +318,7 @@ For example::
			}
			}
		})
		})
		...
		...
	}


These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
specifies the path to the controller. In order to use these GPIOs in Linux
specifies the path to the controller. In order to use these GPIOs in Linux
@@ -463,7 +440,7 @@ namespace link::
		Name (_DSD, Package () {
		Name (_DSD, Package () {
			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
			Package () {
			Package () {
				Package (2) { "compatible", "ti,tmp75" },
				Package () { "compatible", "ti,tmp75" },
			}
			}
		})
		})
		Method (_CRS, 0, Serialized)
		Method (_CRS, 0, Serialized)
+14 −12
Original line number Original line Diff line number Diff line
@@ -275,6 +275,8 @@ have a device like below::
The driver might expect to get the right GPIO when it does::
The driver might expect to get the right GPIO when it does::


  desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW);
  desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW);
  if (IS_ERR(desc))
	...error handling...


but since there is no way to know the mapping between "reset" and
but since there is no way to know the mapping between "reset" and
the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT).
the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT).