xref: /aosp_15_r20/external/coreboot/Documentation/drivers/dt_entries.md (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1# Driver Devicetree Entries
2
3Let's take a look at an example entry from
4``src/mainboard/google/hatch/variants/hatch/overridetree.cb``:
5
6```
7device pci 15.0 on
8	chip drivers/i2c/generic
9		register "hid" = ""ELAN0000""
10		register "desc" = ""ELAN Touchpad""
11		register "irq" = "ACPI_IRQ_LEVEL_LOW(GPP_A21_IRQ)"
12		register "detect" = "1"
13		register "wake" = "GPE0_DW0_21"
14		device i2c 15 on end
15	end
16end # I2C #0
17```
18
19When this entry is processed during ramstage, it will create a device in the
20ACPI SSDT table (all devices in devicetrees end up in the SSDT table).  The ACPI
21generation routines in coreboot actually generate the raw bytecode that
22represents the device's structure, but looking at ASL code is easier to
23understand; see below for what the disassembled bytecode looks like:
24
25```
26Scope (\_SB.PCI0.I2C0)
27{
28    Device (D015)
29    {
30        Name (_HID, "ELAN0000")  // _HID: Hardware ID
31        Name (_UID, Zero)  // _UID: Unique ID
32        Name (_DDN, "ELAN Touchpad")  // _DDN: DOS Device Name
33        Method (_STA, 0, NotSerialized)  // _STA: Status
34        {
35            Return (0x0F)
36        }
37        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
38        {
39            I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
40                AddressingMode7Bit, "\\_SB.PCI0.I2C0",
41                0x00, ResourceConsumer, , Exclusive, )
42            Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
43            {
44                0x0000002D,
45            }
46        })
47        Name (_S0W, ACPI_DEVICE_SLEEP_D3_HOT)  // _S0W: S0 Device Wake State
48        Name (_PRW, Package (0x02)  // _PRW: Power Resources for Wake
49        {
50            0x15, // GPE #21
51            0x03  // Sleep state S3
52        })
53    }
54}
55```
56
57You can see it generates \_HID, \_UID, \_DDN, \_STA, \_CRS, \_S0W, and \_PRW
58names/methods in the Device's scope.
59
60## Utilizing a device driver
61
62The device driver must be enabled for your build.  There will be a CONFIG option
63in the Kconfig file in the directory that the driver is in (e.g.,
64``src/drivers/i2c/generic`` contains a Kconfig file; the option here is named
65CONFIG_DRIVERS_I2C_GENERIC).  The config option will need to be added to your
66mainboard's Kconfig file (e.g., ``src/mainboard/google/hatch/Kconfig``) in order
67to be compiled into your build.
68
69## Diving into the above example:
70
71Let's take a look at how the devicetree language corresponds to the generated
72ASL.
73
74First, note this:
75
76```
77    chip drivers/i2c/generic
78```
79
80This means that the device driver we're using has a corresponding structure,
81located at ``src/drivers/i2c/generic/chip.h``, named **struct
82drivers_i2c_generic_config** and it contains many properties you can specify to
83be included in the ACPI table.
84
85### hid
86
87```
88    register "hid" = ""ELAN0000""
89```
90
91This corresponds to **const char \*hid** in the struct.  In the ACPI ASL, it
92translates to:
93
94```
95    Name (_HID, "ELAN0000") // _HID: Hardware ID
96```
97
98under the device.  **This property is used to match the device to its driver
99during enumeration in the OS.**
100
101### desc
102
103```
104    register "desc" = ""ELAN Touchpad""
105```
106
107corresponds to **const char \*desc** and in ASL:
108
109```
110    Name (_DDN, "ELAN Touchpad") // _DDN: DOS Device Name
111```
112
113### irq
114
115It also adds the interrupt,
116
117```
118    Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
119    {
120        0x0000002D,
121    }
122```
123
124which comes from:
125
126```
127    register "irq" = "ACPI_IRQ_LEVEL_LOW(GPP_A21_IRQ)"
128```
129
130The IRQ settings control the "Trigger" and "Polarity" settings seen above (level
131means it is a level-triggered interrupt as opposed to
132edge-triggered; active low means the interrupt is triggered when the signal is
133low).
134
135Also note that the IRQ names are SoC-specific, and you will need to
136find the names in your SoC's header file.  The ACPI_* macros are defined in
137``src/arch/x86/include/acpi/acpi_device.h``.
138
139Using a GPIO as an IRQ requires that it is configured in coreboot correctly.
140This is often done in a mainboard-specific file named ``gpio.c``.
141
142AMD platforms don't have the ability to route GPIOs to the IO-APIC. Instead the
143GPIO controller needs to be used directly. You can do this by setting the
144`irq_gpio` register and using the `ACPI_GPIO_IRQ_X_X` macros.
145
146i.e.,
147```
148register "irq_gpio" = "ACPI_GPIO_IRQ_EDGE_LOW(GPIO_40)"
149```
150
151### detect
152
153The next register is:
154
155```
156    register "detect" = "1"
157```
158
159This flag tells the I2C driver that it should attempt to detect the presence of
160the device (using an I2C zero-byte write), and only generate a SSDT entry if the
161device is actually present. This alleviates the OS from having to determine if
162a device is present or not (ChromeOS/Linux) and prevents resource conflict/
163driver issues (Windows).
164
165Currently, the detect feature works and is hooked up for all I2C touchpads,
166and should be used any time a board has multiple touchpad options.
167I2C audio devices should also work without issue.
168
169Touchscreens can use this feature as well, but special care is needed to
170implement the proper power sequencing for the device to be detected. Generally,
171this means driving the enable GPIO high and holding the reset GPIO low in early
172GPIO init (bootblock/romstage), then releasing reset in ramstage. The first
173mainboards in the tree to implement this are google/skyrim and google/guybrush.
174This feature has also been used in downstream forks without issue for some time
175now on several other boards.
176
177### wake
178
179The last register is:
180
181```
182    register "wake" = "GPE0_DW0_21"
183```
184
185which indicates that the method of waking the system using the touchpad will be
186through a GPE, #21 associated with DW0, which is set up in devicetree.cb from
187this example.  The "21" indicates GPP_X21, where GPP_X is mapped onto DW0
188elsewhere in the devicetree.
189
190### device
191
192The last bit of the definition of that device includes:
193
194```
195    device i2c 15 on end
196```
197
198which means it's an I2C device, with 7-bit address 0x15, and the device is "on",
199meaning it will be exposed in the ACPI table.  The PCI device that the
200controller is located in determines which I2C bus the device is expected to be
201found on.  In this example, this is I2C bus 0.  This also determines the ACPI
202"Scope" that the device names and methods will live under, in this case
203"\_SB.PCI0.I2C0".
204
205## Wake sources
206
207The ACPI spec defines two methods to describe how a device can wake the system.
208Only one of these methods should be used, otherwise duplicate wake events will
209be generated.
210
211### Using GPEs as a wake source
212
213The `wake` property specified above is used to tell the ACPI subsystem that the
214device can use a GPE to wake the system. The OS can control whether to enable
215or disable the wake source by unmasking/masking off the GPE.
216
217The `GPIO` -> `GPE` mapping must be configured in firmware. On AMD platforms this is
218generally done by a mainboard specific `gpio.c` file that defines the GPIO
219using `PAD_SCI`. The `GPIO` -> `GPE` mapping is returned by the
220`soc_get_gpio_event_table` method that is defined in the SoC specific `gpio.c`
221file. On Intel platforms, you fill in the `pmc_gpe0_dw0`, `pmc_gpe0_dw1`, and
222`pmc_gpe0_dw2` fields in the devicetree to map 3 GPIO communities to `tier-1`
223GPEs (the rest are available as `tier-2` GPEs).
224
225Windows has a large caveat when using this method. If you use the `gpio_irq`
226property to define a `GpioInt` in the `_CRS`, and then use the `wake` property
227to define a `GPE`, Windows will
228[BSOD](https://github.com/MicrosoftDocs/windows-driver-docs/blob/staging/windows-driver-docs-pr/debugger/bug-check-0xa5--acpi-bios-error.md)
229complaining about an invalid ACPI configuration.
230> 0x1000D - A device used both GPE and GPIO interrupts, which is not supported.
231
232In order to avoid this error, you should use the `irq` property instead. AMD
233platforms don't support routing GPIOs to the IO-APIC, so this workaround isn't
234feasible. The other option is to use a wake capable GPIO as described below.
235
236### Using GPIO interrupts as a wake source
237
238The `ACPI_IRQ_WAKE_{EDGE,LEVEL}_{LOW,HIGH}` macros can be used when setting the
239`irq` or `gpio_irq` properties. This ends up setting `ExclusiveAndWake` or
240`SharedAndWake` on the `Interrupt` or `GpioInt` ACPI resource.
241
242This method has a few caveats:
243* On Intel and AMD platforms the IO-APIC can't wake the system. This means using
244  the `ACPI_IRQ_WAKE_*` macros with the `irq` property won't actually wake the
245  system. Instead you need to use the `gpio_irq` property, or a `GPE` as
246  described above.
247* The OS needs to know how to enable the `wake` bit on the GPIO. For linux this
248  means the platform specific GPIO controller driver must implement the
249  `irq_set_wake` callback. For AMD systems this wasn't
250  [implemented](https://github.com/torvalds/linux/commit/d62bd5ce12d79bcd6a6c3e4381daa7375dc21158)
251  until linux v5.15. If the controller doesn't define this callback, it's
252  possible for the firmware to manually set the `wake` bit on the GPIO. This is
253  often done in a mainboard-specific file named `gpio.c`. This is not
254  recommended because then it's not possible for the OS to disable the wake
255  source.
256* As of
257  [linux v6.0-rc5](https://github.com/torvalds/linux/releases/tag/v6.0-rc5),
258  the ACPI subsystem doesn't take the interrupt `wake` bit into account when
259  deciding on which power state to put the device in before suspending the
260  system. This means that if you define a power resource for a device via
261  `has_power_resource`, `enable_gpio`, etc, then the linux kernel will place the
262  device into D3Cold. i.e., power off the device.
263
264## Other auto-generated names
265
266(see [ACPI specification
2676.3](https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf)
268for more details on ACPI methods)
269
270### _S0W (S0 Device Wake State)
271\_S0W indicates the deepest S0 sleep state this device can wake itself from,
272which in this case is `ACPI_DEVICE_SLEEP_D3_HOT`, representing _D3hot_.
273D3Hot means the `PR3` power resources are still on and the device is still
274responsive on the bus. For i2c devices this is generally the same state as `D0`.
275
276### \_PRW (Power Resources for Wake)
277\_PRW indicates the power resources and events required for wake.  There are no
278dependent power resources, but the GPE (GPE0_DW0_21) is mentioned here (0x15),
279as well as the deepest sleep state supporting waking the system (3), which is
280S3.
281
282### \_STA (Status)
283The \_STA method is generated automatically, and its values, 0xF, indicates the
284following:
285
286    Bit [0] – Set if the device is present.
287    Bit [1] – Set if the device is enabled and decoding its resources.
288    Bit [2] – Set if the device should be shown in the UI.
289    Bit [3] – Set if the device is functioning properly (cleared if device failed its diagnostics).
290
291### \_CRS (Current resource settings)
292The \_CRS method is generated automatically, as the driver knows it is an I2C
293controller, and so specifies how to configure the controller for proper
294operation with the touchpad.
295
296```
297Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
298{
299    I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
300                    AddressingMode7Bit, "\\_SB.PCI0.I2C0",
301                    0x00, ResourceConsumer, , Exclusive, )
302```
303
304## Notes
305
306 - **All device driver entries in devicetrees end up in the SSDT table, and are
307   generated in coreboot's ramstage**
308   (The lone exception to this rule is i2c touchpads with the 'detect' flag set;
309    in this case, devices not present will not be added to the SSDT)
310