Device Tree is defined as

In computing, a device tree (also written devicetree) is a data structure describing the hardware components of a particular computer so that the operating system’s kernel can use and manage those components, including the CPU or CPUs, the memory, the buses and the peripherals.

Basically, device tree defines SOC architecture for operating system or boot-loader. This is widely used in embedded systems where the system is not configurable and not going to change.

This is not a problem on PCs because of things like BIOS enumeration through ACPI and you can add whatever behind PCI and it can be probed.

Anyway, i read the first two chapters of specification and i thought it was enough to play around with dtc which part of device-tree-compiler.

apt install device-tree-compiler

Device tree crash course Link to heading

I am not going to repeat the spec. but to sum up,

  • It’s a tree of nodes (DAG)
  • each node have pairs of property/values.
  • The devicetree has a single root node of which all other device nodes are descendants. The full path to the root node is /.
  • All devicetrees shall have a root node and the following nodes shall be present at the root of all devicetrees: one /cpus/ and at least one /memory

That’s it.

/dts-v1/;

/ {
    compatible = "vendor,model";
	cpus {
		cpu1: cpu@1 {
			compatible = "vendor,model";
			clock-frequency = <650000000>;
			device_type = "cpu";
			reg = <1>;
		};
	};

    memory: memory@80000000 {
		device_type = "memory";
		reg = <0x00000000 0x80000000 0x00000000 0x40000000>;
	};

};

Properties can take one the following values

  • empty
  • u32
  • u64
  • phandle
  • string
  • prop-encoded-array
  • stringlist

more details and examples at sections 2.2 of specs

Compile and de-compile device tree Link to heading

Using dtc, we can compile dts into dtb(device tree blob).

dtc -I dts  -O dtb -o 1.dtb  1.dts 

we can de-compile the blob back to dts.

dtc -I dtb  -O dts -o 1.dtsd  1.dtb

Note, the specs define the format for the binary blob. with the following, i guess it would be fun to write a parser for it.

struct fdt_header {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
};

we can see this realy quick with hexdump as specs says the magicvalue is 0xd00dfeed. Note, we get 0dd0 edfe because of endiance.

$ hexdump 1.dtb 
0000000 0dd0 edfe 0000 3f01 0000 3800 0000 1401

Interrupts Link to heading

I think that interrupts is most complicated part of specs.Here is quick overview

the spec defines interrupt-generating devices

The physical wiring of an interrupt source to an interrupt controller is represented in the devicetree with the interrupt-parent property. Nodes that represent interrupt-generating devices contain an interrupt-parent property which has a phandle value that points to the device to which the device’s interrupts are routed, typically an interrupt controller. If an interrupt-generating device does not have an interrupt-parent property, its interrupt parent is assumed to be its devicetree parent.

and interrupt domain is defined as:

An interrupt domain is the context in which an interrupt specifier is interpreted. The root of the domain is either (1) an interrupt controller or (2) an interrupt nexus.

  • An interrupt controller
  • An interrupt nexus

Looking at any dts in linux kernel say this one. The interrupt controller has the properties

  • interrupt-controller
  • interrupt-cells which defines the interrupt specifier in the interrupt-generating device
			gic: interrupt-controller@d000 {
				compatible = "arm,cortex-a9-gic";
				#interrupt-cells = <3>;
				#size-cells = <0>;
				interrupt-controller;
				reg = <0xd000 0x1000>,
				      <0xc100 0x100>;
			};

somewhere in the same dts, there are interrupt devices with interrupts property

			rtc: rtc@10300 {
				compatible = "marvell,orion-rtc";
				reg = <0x10300 0x20>;
				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
			};