Mika Westerberg | 0d9a693 | 2014-10-29 15:41:01 +0100 | [diff] [blame] | 1 | _DSD Device Properties Related to GPIO |
| 2 | -------------------------------------- |
| 3 | |
Rafael J. Wysocki | a00212e | 2015-05-04 01:58:27 +0200 | [diff] [blame] | 4 | With the release of ACPI 5.1, the _DSD configuration object finally |
| 5 | allows names to be given to GPIOs (and other things as well) returned |
| 6 | by _CRS. Previously, we were only able to use an integer index to find |
Mika Westerberg | 0d9a693 | 2014-10-29 15:41:01 +0100 | [diff] [blame] | 7 | the corresponding GPIO, which is pretty error prone (it depends on |
| 8 | the _CRS output ordering, for example). |
| 9 | |
| 10 | With _DSD we can now query GPIOs using a name instead of an integer |
| 11 | index, like the ASL example below shows: |
| 12 | |
| 13 | // Bluetooth device with reset and shutdown GPIOs |
| 14 | Device (BTH) |
| 15 | { |
| 16 | Name (_HID, ...) |
| 17 | |
| 18 | Name (_CRS, ResourceTemplate () |
| 19 | { |
| 20 | GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, |
| 21 | "\\_SB.GPO0", 0, ResourceConsumer) {15} |
| 22 | GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, |
| 23 | "\\_SB.GPO0", 0, ResourceConsumer) {27, 31} |
| 24 | }) |
| 25 | |
| 26 | Name (_DSD, Package () |
| 27 | { |
| 28 | ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), |
| 29 | Package () |
| 30 | { |
Mika Westerberg | 060d791 | 2016-09-23 17:57:06 +0300 | [diff] [blame] | 31 | Package () {"reset-gpios", Package() {^BTH, 1, 1, 0 }}, |
| 32 | Package () {"shutdown-gpios", Package() {^BTH, 0, 0, 0 }}, |
Mika Westerberg | 0d9a693 | 2014-10-29 15:41:01 +0100 | [diff] [blame] | 33 | } |
| 34 | }) |
| 35 | } |
| 36 | |
| 37 | The format of the supported GPIO property is: |
| 38 | |
| 39 | Package () { "name", Package () { ref, index, pin, active_low }} |
| 40 | |
| 41 | ref - The device that has _CRS containing GpioIo()/GpioInt() resources, |
| 42 | typically this is the device itself (BTH in our case). |
| 43 | index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero. |
| 44 | pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero. |
| 45 | active_low - If 1 the GPIO is marked as active_low. |
| 46 | |
| 47 | Since ACPI GpioIo() resource does not have a field saying whether it is |
| 48 | active low or high, the "active_low" argument can be used here. Setting |
| 49 | it to 1 marks the GPIO as active low. |
| 50 | |
Mika Westerberg | 060d791 | 2016-09-23 17:57:06 +0300 | [diff] [blame] | 51 | In our Bluetooth example the "reset-gpios" refers to the second GpioIo() |
Mika Westerberg | 0d9a693 | 2014-10-29 15:41:01 +0100 | [diff] [blame] | 52 | resource, second pin in that resource with the GPIO number of 31. |
Rafael J. Wysocki | e36d453 | 2014-11-03 23:39:57 +0100 | [diff] [blame] | 53 | |
| 54 | ACPI GPIO Mappings Provided by Drivers |
| 55 | -------------------------------------- |
| 56 | |
| 57 | There are systems in which the ACPI tables do not contain _DSD but provide _CRS |
| 58 | with GpioIo()/GpioInt() resources and device drivers still need to work with |
| 59 | them. |
| 60 | |
| 61 | In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV, |
| 62 | available to the driver can be used to identify the device and that is supposed |
| 63 | to be sufficient to determine the meaning and purpose of all of the GPIO lines |
| 64 | listed by the GpioIo()/GpioInt() resources returned by _CRS. In other words, |
| 65 | the driver is supposed to know what to use the GpioIo()/GpioInt() resources for |
| 66 | once it has identified the device. Having done that, it can simply assign names |
| 67 | to the GPIO lines it is going to use and provide the GPIO subsystem with a |
| 68 | mapping between those names and the ACPI GPIO resources corresponding to them. |
| 69 | |
| 70 | To do that, the driver needs to define a mapping table as a NULL-terminated |
| 71 | array of struct acpi_gpio_mapping objects that each contain a name, a pointer |
| 72 | to an array of line data (struct acpi_gpio_params) objects and the size of that |
| 73 | array. Each struct acpi_gpio_params object consists of three fields, |
| 74 | crs_entry_index, line_index, active_low, representing the index of the target |
| 75 | GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target |
| 76 | line in that resource starting from zero, and the active-low flag for that line, |
| 77 | respectively, in analogy with the _DSD GPIO property format specified above. |
| 78 | |
| 79 | For the example Bluetooth device discussed previously the data structures in |
| 80 | question would look like this: |
| 81 | |
| 82 | static const struct acpi_gpio_params reset_gpio = { 1, 1, false }; |
| 83 | static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false }; |
| 84 | |
| 85 | static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = { |
Mika Westerberg | 060d791 | 2016-09-23 17:57:06 +0300 | [diff] [blame] | 86 | { "reset-gpios", &reset_gpio, 1 }, |
| 87 | { "shutdown-gpios", &shutdown_gpio, 1 }, |
Rafael J. Wysocki | e36d453 | 2014-11-03 23:39:57 +0100 | [diff] [blame] | 88 | { }, |
| 89 | }; |
| 90 | |
| 91 | Next, the mapping table needs to be passed as the second argument to |
| 92 | acpi_dev_add_driver_gpios() that will register it with the ACPI device object |
| 93 | pointed to by its first argument. That should be done in the driver's .probe() |
| 94 | routine. On removal, the driver should unregister its GPIO mapping table by |
| 95 | calling acpi_dev_remove_driver_gpios() on the ACPI device object where that |
| 96 | table was previously registered. |