device-tree · git:20260905.fd53e99 · 2026-09-05 · sha256 8f0482604bb73408
device-tree git:20260905.fd53e99A
Immutable. This exact content is served forever at /api/v1/blob/8f0482604bb73408.
---
name: device-tree
description: 'Use when writing DTS/DTSI, bindings, overlays, phandles, or debugging OF platform probe failures. Not for probe and remove code: use platform-device-model.'
---
# Device tree
## Contract
| Field | Bound contract |
|---|---|
| Trigger | Writing or debugging Linux devicetree source: DTS/DTSI structure, bindings, phandles, overlays, `compatible` and property layout, or a driver whose OF probe never fires. |
| Authority | Read-only. Writes nothing. Chat output only. No remote mutation. |
| Side effect | Returns DTS fragments, property tables, and debug commands. No source files are modified. |
| Done | The node or fragment, the property set with cells explained, and a probe-failure diagnosis are delivered. |
## Inputs
1. Hardware fact to describe (required): the block or device, its MMIO base, IRQ, clocks, and the bus it sits on.
2. Board context (optional): the SoC `.dtsi` to include and the board `.dts` to extend.
3. Failure report (optional): the symptom, such as a driver that never probes or an IRQ that never fires.
## Procedure
1. Lay out the node under its bus parent. A board file includes the SoC `.dtsi` and extends or references its nodes by label.
```dts
/dts-v1/;
#include "soc.dtsi"
/ {
model = "My Board";
compatible = "vendor,my-board", "vendor,soc-family";
&uart0 {
status = "okay";
};
};
```
```dts
uart0: serial@40011000 {
compatible = "vendor,uart";
reg = <0x40011000 0x400>;
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_uart0>;
status = "disabled"; /* the board file sets "okay" */
};
```
Done when: the node sits under the right bus parent and every cell count matches the parent's `#address-cells` and `#size-cells`.
2. Set the load-bearing properties correctly.
| Property | Meaning |
|---|---|
| `compatible` | Driver match strings, most specific first |
| `reg` | MMIO address and length, cells per `#address-cells`/`#size-cells` |
| `interrupts` | IRQ specifier, cells defined by the interrupt parent |
| `clocks` / `clock-names` | Phandles to clock providers |
| `status` | `"disabled"` keeps the device unprobed |
Done when: each property value traces to the datasheet or the binding document.
3. Wire phandles for cross-node references. A phandle is the label reference the compiler resolves to a number.
```dts
clk_uart0: clock-uart0 {
compatible = "fixed-clock";
#clock-cells = <0>;
};
&uart0 {
clocks = <&clk_uart0>;
clock-names = "apb_pclk";
};
```
Done when: every `&label` reference resolves to a node defined in the compiled tree.
4. Match the driver to the node. The OF core parses the DTB at boot; `of_platform_populate()` creates `platform_device` instances for bus nodes, and a driver binds when its `of_match_table` matches `compatible`.
```c
static const struct of_device_id my_of_match[] = {
{ .compatible = "vendor,uart" },
{ }
};
MODULE_DEVICE_TABLE(of, my_of_match);
```
Done when: the driver's match table names the exact `compatible` string of the node.
5. Compile and inspect the tree. `dtc` ships with the kernel in `scripts/dtc`; `make dtbs` builds the in-tree boards.
```bash
dtc -I dts -O dtb -o board.dtb board.dts
dtc -I fs -O dts /proc/device-tree | less # what the running kernel sees
ls /sys/firmware/devicetree/base/
```
Name the binding document (`Documentation/devicetree/bindings/`, YAML under dt-schema) in the commit that adds or changes a binding. Done when: the compiled DTB matches the running tree, or the delta explains the failure.
6. Apply overlays where the platform supports them. `CONFIG_OF_OVERLAY` gives the kernel core overlay support. Mainline applies overlays through the bootloader: U-Boot's `fdt apply`, or `fdtoverlay` to merge a `.dtbo` into the kernel FDT at build time. A runtime configfs interface (`/sys/kernel/config/device-tree/overlays/`) exists only on kernels carrying a vendor patch (`CONFIG_OF_CONFIGFS`); do not assume it on a mainline kernel. Overlay resolution failures name unresolved symbols in `__fixups__`; export the target labels as `__symbols__` in the base DTB. Done when: the apply path is named for the actual kernel and boot chain.
7. Diagnose a probe failure bottom-up: confirm the node is present in the running tree (`/proc/device-tree`), confirm `status` is `"okay"`, confirm the `compatible` string matches the driver table character for character, then confirm suppliers (clocks, regulators, phys) are available or the driver handles `-EPROBE_DEFER`. Route deeper work: `platform-device-model` for probe and driver-model behavior, `bus-drivers-i2c-spi` for I2C/SPI child nodes, `datasheet-and-refmanual-reading` for mapping hardware facts to DT properties. Done when: the first broken link in the chain is named.
## Failure and recovery
| Symptom | Cause | Recovery |
|---|---|---|
| Driver never binds | `compatible` mismatch | Diff the string against the driver's `of_match_table`. |
| Wrong MMIO decoded | `#address-cells`/`#size-cells` mismatch | Follow the SoC `.dtsi` parent conventions. |
| IRQ never fires | Wrong interrupt parent or cells | Copy the specifier shape from a working node on the same interrupt controller. |
| Probe deferred forever | Missing supplier node or driver | Add the supplier to DT, or enable its driver. |
| Overlay fails to apply | Unresolved symbols | Export labels as `__symbols__` in the base DTB. |
## Output
The node or board fragment; the property table with cell arithmetic; the phandle wiring; the driver match snippet; the compile and inspect transcript; the overlay apply path for the actual kernel; the named first broken link in the probe chain.