Commit | Line | Data |
---|---|---|
0d9a693c MW |
1 | _DSD Device Properties Related to GPIO |
2 | -------------------------------------- | |
3 | ||
4 | With the release of ACPI 5.1 and the _DSD configuration objecte names | |
5 | can finally be given to GPIOs (and other things as well) returned by | |
6 | _CRS. Previously, we were only able to use an integer index to find | |
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 | { | |
31 | Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }}, | |
32 | Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }}, | |
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 | ||
51 | In our Bluetooth example the "reset-gpio" refers to the second GpioIo() | |
52 | resource, second pin in that resource with the GPIO number of 31. | |
e36d453e RW |
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[] = { | |
86 | { "reset-gpio", &reset_gpio, 1 }, | |
87 | { "shutdown-gpio", &shutdown_gpio, 1 }, | |
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. |