DTS and DTB files

The conversion from DTS to DTB and back to DTS.

Introduction

In the Linux kernel source tree, there are .dts (i.e., device tree source) and .dtsi (i.e., device tree source include).

.dtb is the binary form of the .dts in a similar sense what a binary exectuable is to an assembly source: it is possible to convert binary back to assembly, but some aliases and comment information will be lost.

From kernel sources

Because kernel .dts depend on .dtsi inclusion, they have to be preprocessed first with the C preprocessor (cpp). The dtc tool can convert between .dts and .dtb:

cd linux/arch/arm/boot/dts
cpp -nostdinc -I include -undef -x assembler-with-cpp sun8i-h3-nanopi-neo.dts > /tmp/sun8i-h3-nanopi-neo.dts
dtc -I dts /tmp/sun8i-h3-nanopi-neo.dts -O dtb -o /boot/sun8i-h3-nanopi-neo.dtb

Example

Let us compare the initial source (as generated by cpp) and the sources converted back from binary.

usb_otg: usb@01c19000 {
    compatible = "allwinner,sun8i-h3-musb";
    reg = <0x01c19000 0x400>;
    clocks = <&ccu 32>;
    resets = <&ccu 17>;
    interrupts = <0 71 4>;
    interrupt-names = "mc";
    phys = <&usbphy 0>;
    phy-names = "usb";
    extcon = <&usbphy 0>;
    status = "disabled";
};

usbphy: phy@01c19400 {
    [...]
};
usb@01c19000 {
    compatible = "allwinner,sun8i-h3-musb";
    reg = <0x1c19000 0x400>;
    clocks = <0x6 0x20>;
    resets = <0x6 0x11>;
    interrupts = <0x0 0x47 0x4>;
    interrupt-names = "mc";
    phys = <0xf 0x0>;
    phy-names = "usb";
    extcon = <0xf 0x0>;
    status = "disabled";
};

phy@01c19400 {
    [...]
    linux,phandle = <0xf>;
    phandle = <0xf>;
};

The alias usbphy is lost. It was used in the original source for the link from extcon to phy. In the source from binary, an handler is used (i.e., 0xf).

Modify sources

Now the question is: how to change the source .dts which comes from a binary .dtb?

For example, add this line as presented in kernel source:

&usbphy {
    usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
};

pio: pinctrl@01c20800 {
    [...]
};

&pio points to pinctrl@01c20800. As seen previously, the alias pio will be lost in the conversion to binary, but a phandle will be available:

pinctrl@01c20800 {
    [...]
    linux,phandle = <0xb>;
    phandle = <0xb>;
};

The phandle of pio is 0xb and the other parameters are simply converted to hexadecimal:

phy@01c19400 {
    [...]
    usb0_id_det-gpios = <0xb 0x6 0xc 0x0>;
};