diff --git a/Documentation/index.md b/Documentation/index.md index 7ba88f30ef..b564c5c71d 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -219,6 +219,7 @@ Community Payloads Distributions Technotes +Internal APIs & Configuration ACPI Native Graphics Initialization with libgfxinit Display panel diff --git a/Documentation/internals/devicetree.md b/Documentation/internals/devicetree.md new file mode 100644 index 0000000000..c6f5c4cc68 --- /dev/null +++ b/Documentation/internals/devicetree.md @@ -0,0 +1,684 @@ +# Devicetree + +## Introduction to the coreboot devicetree + +The first thing that may come to mind when one hears "DeviceTree" is a +different sort of description file that is generally passed to the Linux +kernel to describe a system's components. Both that devicetree and +coreboot's devicetree serve fundamentally the same purpose, but are +otherwise unrelated and have completely different syntax. The term +devicetree was used long before either version was created, and was +initially used in coreboot as a generic term. + +coreboot's devicetree's main use is to define and describe the runtime +configuration and settings of the hardware on a board, chip or device +level. It defines which of the functions of the chips on the board are +enabled, and how they're configured. + +The devicetree file is parsed during the build process by a utility +named `sconfig`, which translates the devicetree into a tree of C +structures containing the included devices. This code is placed in the +file `static.c` and a couple of header files, all under the `build` +directory. This file is then built into the binaries for the various +coreboot stages and is referred to during the coreboot boot process. + +For the early stages of the coreboot boot process, the data that is +generated by `sconfig` is a useful resource, but this structure is the +critical architectural glue of ramstage. This structure gets filled in +with pointers to every chip's initialization code, allowing ramstage to +find and initialize those devices through the `chip_operations` +structures. + + +### History of coreboot's devicetree + +The initial devicetree in coreboot was introduced in 2003 by Ron Minnich +as a part of the linuxbios config file, 'config.lb'. At this point both +the devicetree and config options were in the same file. In 2009, +when Kconfig was added into the coreboot build, devicetree was split +out into its own file for each mainboard in a commit with this message: + +```text +devicetree.cb + +The devicetree that formerly resided in src/mainboard/*/*/Config.lb. + +Just without the build system crap +``` + +The devicetree structure was initially mainly used only in ramstage for +PCI device enumeration, configuration and resource allocation. It has +since expanded for use in the pre-ram stages as a read-only structure. + +The language used in the devicetree has been expanded greatly since it +was first introduced as well, adding new features every year or so. + + +### Devicetree Registers + +In coreboot, the devicetree register setting is one of the two main +methods used to configure a board's properties. In this way, devicetree +is similar in function to Kconfig. It's more flexible in many ways as +it can specify not only single values, but also arrays or structures. +It's also even more static than Kconfig because there's no update +mechanism for it other than editing the devicetree files. + +Chip-specific configuration values are often set using `register` +definitions within a `chip` block, corresponding to a `struct` defined +in the chip's `chip.h` file. + +For example, in a `chip drivers/gpio/acpi` block, you might set a GPE: + +```text +register "gpe0_sts" = "0x42" +``` + + +### Adding new static configuration options: Devicetree or Kconfig + +When adding options for a new board or chip, there is frequently a +decision that needs to be made about how the option should be added. +Using the devicetree or Kconfig are the two typical methods of +build-time configuration. Below are some general guidelines on when to +use each. + +Kconfig should be used if the option configures the build in a Makefile, +or if the option is something that should be user selectable. Kconfig +is also preferred if the configuration is a global option and not limited +to a single chip. Another thing Kconfig excels at is handling decisions +based on other configuration options, which devicetree cannot do. + +Devicetree should obviously be used to define the hardware hierarchy. +It's also preferred if the option is only used in C code and is static +for a mainboard, or if the option is chip-specific. As mentioned +earlier, devicetree registers can also define structures or arrays, +which Kconfig cannot. + +Both Kconfig and devicetree can be used in C code for runtime +configuration, but there's a significant difference in how they are +handled. Because Kconfig generates a `#define` for the choice, the +compiler can eliminate code paths not used by the option. Devicetree +options, however, are actual runtime selections, and the code for all +choices remains in the final build. + + +## Basic Devicetree Syntax + +The coreboot devicetree uses a custom language parsed by the `sconfig` +utility. Here's a brief overview of the main keywords and concepts: + +* **`chip `**: Defines a collection of devices associated + with the code in the specified directory. `sconfig` may also parse a + `chip.h` file within this directory for register definitions. +* **`device [on|off] [alias ] ... end`**: Defines a + specific hardware device. + * ``: Specifies the device type (e.g., `pci`, `cpu_cluster`, + `i2c`). + * ``: A unique identifier for the device within its type/bus + (e.g., PCI BDF `17.0`, I2C address `0x50`). + * `on`/`off`: Enables or disables the device definition. + * `alias `: Assigns a human-readable alias for referencing + this device elsewhere (often used in `chipset.cb`). + * `end`: Marks the end of the device definition block. Registers + and other properties are defined between `device` and `end`. +* **`register "" = `**: Sets the value of a configuration + register defined in the corresponding `chip.h` structure. The value + can be a number, string, or complex structure initialization. +* **`probe