Skip to content

Commit

Permalink
Merge branch 'acpi-docs'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Rafael J. Wysocki committed Mar 18, 2022
2 parents 8a9bd50 + 830751d commit 1bde8bd
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 91 deletions.
21 changes: 9 additions & 12 deletions Documentation/driver-api/gpio/board.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::

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

Name (_DSD, Package () {
Expand All @@ -92,10 +92,7 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
^FOO, 2, 0, 1,
}
},
Package () {
"power-gpios",
Package () {^FOO, 3, 0, 0},
},
Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } },
}
})
}
Expand Down
111 changes: 44 additions & 67 deletions Documentation/firmware-guide/acpi/enumeration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ possible we decided to do following:
platform devices.

- Devices behind real busses where there is a connector resource
are represented as struct spi_device or struct i2c_device
(standard UARTs are not busses so there is no struct uart_device).
are represented as struct spi_device or struct i2c_device. Note
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
resources) this implementation follows the Device Tree way as much as
possible.

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

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
Expand All @@ -46,18 +47,16 @@ some minor changes.
Adding ACPI support for an existing driver should be pretty
straightforward. Here is the simplest example::

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

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

Expand Down Expand Up @@ -155,7 +154,7 @@ Here is what the ACPI namespace for a SPI slave might look like::
Device (EEP0)
{
Name (_ADR, 1)
Name (_CID, Package() {
Name (_CID, Package () {
"ATML0025",
"AT25",
})
Expand All @@ -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
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[] = {
{ "AT25", 0 },
{ },
{ }
};
MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
#endif

static struct spi_driver at25_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
eeprom etc. but at the time writing this there is no standard way of
passing those. One idea is to return this in _DSM method like::
eeprom, etc. This information can be passed via _DSD method like::

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

// Check UUIDs etc.

Return (Local0)
}

Then the at25 SPI driver can get this configuration by calling _DSM on its
ACPI handle like::

struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_object_list input;
acpi_status status;
Package () { "size", 1024 },
Package () { "pagesize", 32 },
Package () { "address-width", 16 },
}
})
}

/* Fill in the input buffer */
Then the at25 SPI driver can get this configuration by calling device property
APIs during ->probe() phase like::

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

/* 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
======================
Expand All @@ -237,26 +228,24 @@ registered.
Below is an example of how to add ACPI support to the existing mpu3050
input driver::

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

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

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

})
...
}

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
Expand All @@ -306,26 +295,13 @@ For example::
{
Name (SBUF, ResourceTemplate()
{
...
// Used to power on/off the device
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
0x00, ResourceConsumer,,)
{
// Pin List
0x0055
}
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
"\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 85 }

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

...

GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone, 0,
"\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 88 }
}

Return (SBUF)
Expand All @@ -337,11 +313,12 @@ For example::
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"power-gpios", Package() {^DEV, 0, 0, 0 }},
Package () {"irq-gpios", Package() {^DEV, 1, 0, 0 }},
Package () { "power-gpios", Package () { ^DEV, 0, 0, 0 } },
Package () { "irq-gpios", Package () { ^DEV, 1, 0, 0 } },
}
})
...
}

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
Expand Down Expand Up @@ -460,10 +437,10 @@ namespace link::
Device (TMP0)
{
Name (_HID, "PRP0001")
Name (_DSD, Package() {
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package (2) { "compatible", "ti,tmp75" },
Package () { "compatible", "ti,tmp75" },
}
})
Method (_CRS, 0, Serialized)
Expand Down
26 changes: 14 additions & 12 deletions Documentation/firmware-guide/acpi/gpio-properties.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ index, like the ASL example below shows::
Name (_CRS, ResourceTemplate ()
{
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {15}
"\\_SB.GPO0", 0, ResourceConsumer) { 15 }
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
"\\_SB.GPO0", 0, ResourceConsumer) { 27, 31 }
})

Name (_DSD, Package ()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"reset-gpios", Package() {^BTH, 1, 1, 0 }},
Package () {"shutdown-gpios", Package() {^BTH, 0, 0, 0 }},
{
Package () { "reset-gpios", Package () { ^BTH, 1, 1, 0 } },
Package () { "shutdown-gpios", Package () { ^BTH, 0, 0, 0 } },
}
})
}
Expand Down Expand Up @@ -123,17 +123,17 @@ Example::
// _DSD Hierarchical Properties Extension UUID
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () {
Package () {"hog-gpio8", "G8PU"}
Package () { "hog-gpio8", "G8PU" }
}
})

Name (G8PU, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"gpio-hog", 1},
Package () {"gpios", Package () {8, 0}},
Package () {"output-high", 1},
Package () {"line-name", "gpio8-pullup"},
Package () { "gpio-hog", 1 },
Package () { "gpios", Package () { 8, 0 } },
Package () { "output-high", 1 },
Package () { "line-name", "gpio8-pullup" },
}
})

Expand Down Expand Up @@ -266,15 +266,17 @@ have a device like below::

Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
"\\_SB.GPO0", 0, ResourceConsumer) {15}
"\\_SB.GPO0", 0, ResourceConsumer) { 15 }
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
"\\_SB.GPO0", 0, ResourceConsumer) {27}
"\\_SB.GPO0", 0, ResourceConsumer) { 27 }
})
}

The driver might expect to get the right GPIO when it does::

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
the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT).
Expand Down

0 comments on commit 1bde8bd

Please sign in to comment.