Reading – Device Tree

What is Device Tree and how are they used?

Device Tree is a specification used to perform boot-time configuration of a kernel whereby information about the running system is provided by the firmware to the kernel instead of being hard-coded with the kernel module loading or blacklisting process (i.e. load this kernel module for this device).

This Raspberry Pi document describes the format in introductory form. This blog post describes how it gets used.

Before Device Tree, there existed a format called ATAG (tagged list). It is essentially a variable-length array of variable-length structs with identifying tag types. It is terminated by an ATAG_NONE tag. This document describes this format in detail.

This Linux ARM booting document describes the both methods, as well as the overall booting process as expected by the Linux kernel.

Device Tree is passed to the kernel upon boot as an in-memory structure. With Linux booting on ARM, the r2 register is used for Device Tree with a magic value stored at that address to indicate its usage.

Device Tree overlays exist for further configuration of device tree files. This document describes the methods on Raspberry Pi.

Device Tree is mainly used on systems where device enumeration isn’t possible, so this information must be provided otherwise.

This document lays out how to write a Device Tree source file.

What is an example of information provided by Device Tree?

This is the Flattened Device Tree (DTB, FDT) file for Raspberry Pi 4 B. This is the Device Tree source (DTS) provided by Linux. I think the idea is that the kernel provides the source for the boards it supports (i.e. ensure that it contains the informations it expects like register locations), which is then compiled to a blob as part of the kernel build process, then a version of that is distributed by the Raspberry Pi firmware repository. This has some references to it.

This is a template inclusion file (DTSI). In particular, it contains the ARM memory-mapped register address for interfacing with the system timer.

system_timer: timer@7e003000 {
compatible = "brcm,bcm2835-system-timer";
reg = <0x7e003000 0x1000>;
interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
/* This could be a reference to BCM2835_CLOCK_TIMER,
* but we don't have the driver using the common clock
* support yet.
*/
clock-frequency = <1000000>;
};

The kernel can use this register address and interrupt configuration instead of a hard-coded address. For Linux, it knows to load the timer driver for the bcm2835 platform because of the compatible property, which will then make use of the rest of the information.

Commands used to interact with Device Tree files

Most of the interaction can be done with the dtc command line tool.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s