Documentation: split devicetree driver hookup into separate page

Move the devicetree driver example into a separate page under the
drivers category, and link to it from both the devicetree page and
the drivers index page. This makes more sense from a grouping
perspective and makes the info easier to find.

Change-Id: Ic3ca80b93a0020737c7ccb5313a0877172022e1a
Signed-off-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/67762
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
Matt DeVillier 2022-09-21 10:06:15 -05:00 committed by Felix Held
parent 626abf0758
commit 8e013cd8c8
3 changed files with 216 additions and 205 deletions

View File

@ -0,0 +1,210 @@
# Driver Devicetree Entries
Let's take a look at an example entry from
``src/mainboard/google/hatch/variants/hatch/overridetree.cb``:
```
device pci 15.0 on
chip drivers/i2c/generic
register "hid" = ""ELAN0000""
register "desc" = ""ELAN Touchpad""
register "irq" = "ACPI_IRQ_WAKE_LEVEL_LOW(GPP_A21_IRQ)"
register "wake" = "GPE0_DW0_21"
device i2c 15 on end
end
end # I2C #0
```
When this entry is processed during ramstage, it will create a device in the
ACPI SSDT table (all devices in devicetrees end up in the SSDT table). The ACPI
generation routines in coreboot actually generate the raw bytecode that
represents the device's structure, but looking at ASL code is easier to
understand; see below for what the disassembled bytecode looks like:
```
Scope (\_SB.PCI0.I2C0)
{
Device (D015)
{
Name (_HID, "ELAN0000") // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_DDN, "ELAN Touchpad") // _DDN: DOS Device Name
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, , Exclusive, )
Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, )
{
0x0000002D,
}
})
Name (_S0W, ACPI_DEVICE_SLEEP_D3_HOT) // _S0W: S0 Device Wake State
Name (_PRW, Package (0x02) // _PRW: Power Resources for Wake
{
0x15, // GPE #21
0x03 // Sleep state S3
})
}
}
```
You can see it generates _HID, _UID, _DDN, _STA, _CRS, _S0W, and _PRW
names/methods in the Device's scope.
## Utilizing a device driver
The device driver must be enabled for your build. There will be a CONFIG option
in the Kconfig file in the directory that the driver is in (e.g.,
``src/drivers/i2c/generic`` contains a Kconfig file; the option here is named
CONFIG_DRIVERS_I2C_GENERIC). The config option will need to be added to your
mainboard's Kconfig file (e.g., ``src/mainboard/google/hatch/Kconfig``) in order
to be compiled into your build.
## Diving into the above example:
Let's take a look at how the devicetree language corresponds to the generated
ASL.
First, note this:
```
chip drivers/i2c/generic
```
This means that the device driver we're using has a corresponding structure,
located at ``src/drivers/i2c/generic/chip.h``, named **struct
drivers_i2c_generic_config** and it contains many properties you can specify to
be included in the ACPI table.
### hid
```
register "hid" = ""ELAN0000""
```
This corresponds to **const char *hid** in the struct. In the ACPI ASL, it
translates to:
```
Name (_HID, "ELAN0000") // _HID: Hardware ID
```
under the device. **This property is used to match the device to its driver
during enumeration in the OS.**
### desc
```
register "desc" = ""ELAN Touchpad""
```
corresponds to **const char *desc** and in ASL:
```
Name (_DDN, "ELAN Touchpad") // _DDN: DOS Device Name
```
### irq
It also adds the interrupt,
```
Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, )
{
0x0000002D,
}
```
which comes from:
```
register "irq" = "ACPI_IRQ_WAKE_LEVEL_LOW(GPP_A21_IRQ)"
```
The GPIO pin IRQ settings control the "Level", "ActiveLow", and
"ExclusiveAndWake" settings seen above (level means it is a level-triggered
interrupt as opposed to edge-triggered; active low means the interrupt is
triggered when the signal is low).
Note that the ACPI_IRQ_WAKE_LEVEL_LOW macro informs the platform that the GPIO
will be routed through SCI (ACPI's System Control Interrupt) for use as a wake
source. Also note that the IRQ names are SoC-specific, and you will need to
find the names in your SoC's header file. The ACPI_* macros are defined in
``src/arch/x86/include/acpi/acpi_device.h``.
Using a GPIO as an IRQ requires that it is configured in coreboot correctly.
This is often done in a mainboard-specific file named ``gpio.c``.
### wake
The last register is:
```
register "wake" = "GPE0_DW0_21"
```
which indicates that the method of waking the system using the touchpad will be
through a GPE, #21 associated with DW0, which is set up in devicetree.cb from
this example. The "21" indicates GPP_X21, where GPP_X is mapped onto DW0
elsewhere in the devicetree.
The last bit of the definition of that device includes:
```
device i2c 15 on end
```
which means it's an I2C device, with 7-bit address 0x15, and the device is "on",
meaning it will be exposed in the ACPI table. The PCI device that the
controller is located in determines which I2C bus the device is expected to be
found on. In this example, this is I2C bus 0. This also determines the ACPI
"Scope" that the device names and methods will live under, in this case
"\_SB.PCI0.I2C0".
## Other auto-generated names
(see [ACPI specification
6.3](https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf)
for more details on ACPI methods)
### _S0W (S0 Device Wake State)
_S0W indicates the deepest S0 sleep state this device can wake itself from,
which in this case is ACPI_DEVICE_SLEEP_D3_HOT, representing _D3hot_.
### _PRW (Power Resources for Wake)
_PRW indicates the power resources and events required for wake. There are no
dependent power resources, but the GPE (GPE0_DW0_21) is mentioned here (0x15),
as well as the deepest sleep state supporting waking the system (3), which is
S3.
### _STA (Status)
The _STA method is generated automatically, and its values, 0xF, indicates the
following:
Bit [0] Set if the device is present.
Bit [1] Set if the device is enabled and decoding its resources.
Bit [2] Set if the device should be shown in the UI.
Bit [3] Set if the device is functioning properly (cleared if device failed its diagnostics).
### _CRS (Current resource settings)
The _CRS method is generated automatically, as the driver knows it is an I2C
controller, and so specifies how to configure the controller for proper
operation with the touchpad.
```
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, , Exclusive, )
```
## Notes
- **All devices in devicetrees end up in the SSDT table, and are generated in
coreboot's ramstage**

View File

@ -4,6 +4,10 @@ The drivers can be found in `src/drivers`. They are intended for onboard
and plugin devices, significantly reducing integration complexity and
they allow to easily reuse existing code across platforms.
For details on how to connect device drivers to a mainboard, see [Driver Devicetree Entries](dt_entries.md).
Some of the drivers currently available include:
* [Intel DPTF](dptf.md)
* [IPMI KCS](ipmi_kcs.md)
* [SMMSTORE](smmstore.md)

View File

@ -78,213 +78,10 @@ with no properties as a direct child of the SoC.
## Device drivers
Let's take a look at an example entry from
``src/mainboard/google/hatch/variants/hatch/overridetree.cb``:
```
device pci 15.0 on
chip drivers/i2c/generic
register "hid" = ""ELAN0000""
register "desc" = ""ELAN Touchpad""
register "irq" = "ACPI_IRQ_WAKE_LEVEL_LOW(GPP_A21_IRQ)"
register "wake" = "GPE0_DW0_21"
device i2c 15 on end
end
end # I2C #0
```
When this entry is processed during ramstage, it will create a device in the
ACPI SSDT table (all devices in devicetrees end up in the SSDT table). The ACPI
generation routines in coreboot actually generate the raw bytecode that
represents the device's structure, but looking at ASL code is easier to
understand; see below for what the disassembled bytecode looks like:
```
Scope (\_SB.PCI0.I2C0)
{
Device (D015)
{
Name (_HID, "ELAN0000") // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_DDN, "ELAN Touchpad") // _DDN: DOS Device Name
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, , Exclusive, )
Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, )
{
0x0000002D,
}
})
Name (_S0W, ACPI_DEVICE_SLEEP_D3_HOT) // _S0W: S0 Device Wake State
Name (_PRW, Package (0x02) // _PRW: Power Resources for Wake
{
0x15, // GPE #21
0x03 // Sleep state S3
})
}
}
```
You can see it generates _HID, _UID, _DDN, _STA, _CRS, _S0W, and _PRW
names/methods in the Device's scope.
## Utilizing a device driver
The device driver must be enabled for your build. There will be a CONFIG option
in the Kconfig file in the directory that the driver is in (e.g.,
``src/drivers/i2c/generic`` contains a Kconfig file; the option here is named
CONFIG_DRIVERS_I2C_GENERIC). The config option will need to be added to your
mainboard's Kconfig file (e.g., ``src/mainboard/google/hatch/Kconfig``) in order
to be compiled into your build.
## Diving into the above example:
Let's take a look at how the devicetree language corresponds to the generated
ASL.
First, note this:
```
chip drivers/i2c/generic
```
This means that the device driver we're using has a corresponding structure,
located at ``src/drivers/i2c/generic/chip.h``, named **struct
drivers_i2c_generic_config** and it contains many properties you can specify to
be included in the ACPI table.
### hid
```
register "hid" = ""ELAN0000""
```
This corresponds to **const char *hid** in the struct. In the ACPI ASL, it
translates to:
```
Name (_HID, "ELAN0000") // _HID: Hardware ID
```
under the device. **This property is used to match the device to its driver
during enumeration in the OS.**
### desc
```
register "desc" = ""ELAN Touchpad""
```
corresponds to **const char *desc** and in ASL:
```
Name (_DDN, "ELAN Touchpad") // _DDN: DOS Device Name
```
### irq
It also adds the interrupt,
```
Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, )
{
0x0000002D,
}
```
which comes from:
```
register "irq" = "ACPI_IRQ_WAKE_LEVEL_LOW(GPP_A21_IRQ)"
```
The GPIO pin IRQ settings control the "Level", "ActiveLow", and
"ExclusiveAndWake" settings seen above (level means it is a level-triggered
interrupt as opposed to edge-triggered; active low means the interrupt is
triggered when the signal is low).
Note that the ACPI_IRQ_WAKE_LEVEL_LOW macro informs the platform that the GPIO
will be routed through SCI (ACPI's System Control Interrupt) for use as a wake
source. Also note that the IRQ names are SoC-specific, and you will need to
find the names in your SoC's header file. The ACPI_* macros are defined in
``src/arch/x86/include/acpi/acpi_device.h``.
Using a GPIO as an IRQ requires that it is configured in coreboot correctly.
This is often done in a mainboard-specific file named ``gpio.c``.
### wake
The last register is:
```
register "wake" = "GPE0_DW0_21"
```
which indicates that the method of waking the system using the touchpad will be
through a GPE, #21 associated with DW0, which is set up in devicetree.cb from
this example. The "21" indicates GPP_X21, where GPP_X is mapped onto DW0
elsewhere in the devicetree.
The last bit of the definition of that device includes:
```
device i2c 15 on end
```
which means it's an I2C device, with 7-bit address 0x15, and the device is "on",
meaning it will be exposed in the ACPI table. The PCI device that the
controller is located in determines which I2C bus the device is expected to be
found on. In this example, this is I2C bus 0. This also determines the ACPI
"Scope" that the device names and methods will live under, in this case
"\_SB.PCI0.I2C0".
## Other auto-generated names
(see [ACPI specification
6.3](https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf)
for more details on ACPI methods)
### _S0W (S0 Device Wake State)
_S0W indicates the deepest S0 sleep state this device can wake itself from,
which in this case is ACPI_DEVICE_SLEEP_D3_HOT, representing _D3hot_.
### _PRW (Power Resources for Wake)
_PRW indicates the power resources and events required for wake. There are no
dependent power resources, but the GPE (GPE0_DW0_21) is mentioned here (0x15),
as well as the deepest sleep state supporting waking the system (3), which is
S3.
### _STA (Status)
The _STA method is generated automatically, and its values, 0xF, indicates the
following:
Bit [0] Set if the device is present.
Bit [1] Set if the device is enabled and decoding its resources.
Bit [2] Set if the device should be shown in the UI.
Bit [3] Set if the device is functioning properly (cleared if device failed its diagnostics).
### _CRS (Current resource settings)
The _CRS method is generated automatically, as the driver knows it is an I2C
controller, and so specifies how to configure the controller for proper
operation with the touchpad.
```
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 400000,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, , Exclusive, )
```
Platform independent device drivers are hooked up via entries in a devicetree.
See [Driver Devicetree Entries](drivers/dt_entries.md) for more info.
## Notes
- **All fields that are left unspecified in the devicetree are initialized to
zero.**
- **All devices in devicetrees end up in the SSDT table, and are generated in
coreboot's ramstage**