1@page page_device_dtc Devicetree Compiler
2
3# Introduction to the DTC
4
5Device Tree Compiler, dtc, takes as input a device-tree in a given format and outputs a device-tree in another format for booting kernels on embedded systems.
6Typically, the input format is "dts" (device-tree source), a human readable source format, and creates a "dtb" (device-tree binary), or binary format as output.
7
8> If the dtc tool is not installed on your host system, the dtc module will guide you through the installation.
9
10## Generate DTS
11
12When you have a DTB or FDT file from firmware or another runtime system, you might want to convert it into a DTS file for easier reading.
13You can do this in Python or your SConscript file. For example, assuming you have `dummpy.dtb`:
14
15```python
16import os, sys
17
18RTT_ROOT = os.getenv('RTT_ROOT')
19sys.path.append(RTT_ROOT + '/tools')
20
21from building import *
22import dtc
23
24dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb")
25```
26
27This will generate a dummpy.dts in the current directory. If a file with the same name already exists, it will be replaced.
28To avoid overwriting, you can specify a different output name:
29
30```python
31[...]
32
33dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", "dummpy-tmp.dts")
34# or
35dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", dts_name = "dummpy-tmp.dts")
36```
37
38## Generate DTB
39
40Before generating a DTB, you may want to review the basics of DTS syntax and structure: [DeviceTree Specification](https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html)
41
42### Include and Macros
43
44By default, dtc does not support C-style preprocessing (like cpp), but you can use the C preprocessor with your DTS files.
45Don't worry — our dtc module already includes this step.
46
47If your DTS file uses dt-bindings headers or macros, you can write something like:
48
49```c
50/*
51 * Used "#include" if header file need preprocessor,
52 * `components/drivers/include` and current directory path is default.
53 */
54#include <dt-bindings/size.h>
55#include "dummy.dtsi"
56/* Well, if dtsi is simple, you can use "/include/", it is supported by dtc */
57/include/ "chosen.dtsi"
58
59#define MMIO_BASE   0x10000
60#define MMIO_SIZE   SIZE_GB
61#define MEM_BASE    (MMIO_BASE + MMIO_SIZE)
62
63#ifndef CPU_HARDID
64#define CPU_HARDID  0
65#endif
66
67#ifndef SOC_INTC
68#define SOC_INTC    intc_a
69#endif
70
71/ {
72    #address-cells = <2>;
73    #size-cells = <2>;
74    /*
75     * Macros after "&" will be replaced,
76     * there will affect the interrupt controller in this SoC.
77     */
78    interrupt-parent = <&SOC_INTC>;
79
80    [...]
81
82    memory {
83        /* When there is a calculation, please use "()" to include them */
84        reg = <0x0 MEM_BASE 0x0 (3 * SIZE_GB)>;
85        device_type = "memory";
86    };
87
88    cpus {
89        #size-cells = <0>;
90        #address-cells = <1>;
91
92        /* Macros after "@" will be replaced */
93        cpu0: cpu@CPU_HARDID {
94            reg = <CPU_HARDID>;
95            device_type = "cpu";
96        };
97    };
98
99    /* Macros replace support phandle name, too */
100    intc_a: intc-a {
101        interrupt-controller;
102    };
103
104    intc_b: intc-b {
105        interrupt-controller;
106    };
107
108    [...]
109};
110```
111
112To generate the DTB:
113
114```python
115import os, sys
116
117RTT_ROOT = os.getenv('RTT_ROOT')
118sys.path.append(RTT_ROOT + '/tools')
119
120from building import *
121import dtc
122
123dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"]
124```
125
126To append more include paths, for example, SoC DM headers:
127
128```python
129[...]
130
131dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], include_paths = ['dm/include', 'firmware'])
132```
133
134### Multiple DTB
135
136A single SoC may have different board variants.
137Example `dummy.dtsi` (common base):
138
139```c
140/* SoC dummy */
141/ {
142    #address-cells = <2>;
143    #size-cells = <2>;
144    model = "Dummy SoC Board";
145
146    [...]
147
148    chosen {
149        bootargs = "cma=8M coherent_pool=2M";
150    };
151
152    reserved-memory {
153        #address-cells = <2>;
154        #size-cells = <2>;
155
156        isp_shm@100000 {
157            reg = <0x0 0x100000 0x0 0x100000>;
158        };
159
160        dsp_shm@200000 {
161            reg = <0x0 0x200000 0x0 0x100000>;
162        };
163    };
164
165    dsp {
166        status = "okay";
167    };
168
169    buddy {
170        isp = <&{/reserved-memory/isp_shm@100000}>;
171        dsp = <&{/reserved-memory/dsp_shm@200000}>;
172    };
173
174    uart0: uart {
175        status = "disabled";
176    };
177
178    i2c0: i2c {
179        status = "okay";
180    };
181
182    [...]
183};
184```
185
186For a vendor-specific variant (Vendor A):
187
188```c
189/* vendorA dummy */
190#include "dummy.dtsi"
191
192/ {
193    /* No phandle name can modify in place */
194    chosen {
195        bootargs = "console=uart0 cma=8M coherent_pool=2M";
196    };
197};
198
199/* Reference and modify direct if has phandle name */
200&uart0 {
201    status = "okay";
202    pinctrl-0 = <&uart0_m1>;
203};
204
205&i2c0 {
206    status = "disabled";
207};
208```
209
210To remove nodes or properties (Vendor B):
211
212```c
213/* vendorB dummy */
214#include "dummy.dtsi"
215
216/delete-node/ &dsp_shm;
217
218/ {
219    /* Delete in place if no phandle name */
220    /delete-node/ dsp;
221
222    /* Delete property */
223    buddy {
224        /delete-property/ dsp;
225    };
226};
227```
228
229To add new devices (Vendor C):
230
231```c
232/* vendorC dummy */
233#include "dummy.dtsi"
234
235&i2c0 {
236    rtc@0 {
237        clock-frequency = <32768>;
238    };
239};
240```
241
242Build all DTBs together:
243
244```python
245[...]
246
247dtc.dts_to_dtb(RTT_ROOT, ["dummpy-vendorA.dts", "dummpy-vendorB.dts", "dummpy-vendorC.dts"])
248```
249
250This will produce `dummpy-vendorA.dtb`, `dummpy-vendorB.dtb`, and `dummpy-vendorC.dtb`
251
252## Warnings
253
254DTC may produce warnings that are irrelevant or noisy.
255To suppress specific warnings:
256
257```python
258[...]
259
260dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"])
261```
262
263Make sure your DTS is valid!
264
265## Raw options
266
267DTC provides additional command-line options (see dtc --help). You can pass raw options like this:
268
269```python
270[...]
271
272dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", options = "--quiet")
273dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], options = "--quiet")
274```
275