diff options
| author | GuEe-GUI <[email protected]> | 2025-06-24 10:38:18 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2025-06-30 09:42:39 +0800 |
| commit | ad2de6e477cad1da7f5c930f4b0f0945fd67a0cd (patch) | |
| tree | 179d90369758396503bb8b96b23ab3f8c5aede7e /documentation | |
| parent | 3e4f0ec015d6ad8e8c1f43b01b33efe2f6e12b68 (diff) | |
[TOOLS] Add DTC (Devicetree Compiler) tools
Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'documentation')
| -rw-r--r-- | documentation/6.components/device-driver/INDEX.md | 1 | ||||
| -rw-r--r-- | documentation/6.components/device-driver/ofw/dtc.md | 274 |
2 files changed, 275 insertions, 0 deletions
diff --git a/documentation/6.components/device-driver/INDEX.md b/documentation/6.components/device-driver/INDEX.md index 010d0fc910..b8600c9e79 100644 --- a/documentation/6.components/device-driver/INDEX.md +++ b/documentation/6.components/device-driver/INDEX.md @@ -13,3 +13,4 @@ - @subpage page_device_wlan - @subpage page_device_sensor - @subpage page_device_audio +- @subpage page_device_dtc diff --git a/documentation/6.components/device-driver/ofw/dtc.md b/documentation/6.components/device-driver/ofw/dtc.md new file mode 100644 index 0000000000..2cc3c1b34c --- /dev/null +++ b/documentation/6.components/device-driver/ofw/dtc.md @@ -0,0 +1,274 @@ +@page page_device_dtc Devicetree Compiler + +# Introduction to the DTC + +Device 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. +Typically, 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. + +> If the dtc tool is not installed on your host system, the dtc module will guide you through the installation. + +## Generate DTS + +When 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. +You can do this in Python or your SConscript file. For example, assuming you have `dummpy.dtb`: + +```python +import os, sys + +RTT_ROOT = os.getenv('RTT_ROOT') +sys.path.append(RTT_ROOT + '/tools') + +from building import * +import dtc + +dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb") +``` + +This will generate a dummpy.dts in the current directory. If a file with the same name already exists, it will be replaced. +To avoid overwriting, you can specify a different output name: + +```python +[...] + +dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", "dummpy-tmp.dts") +# or +dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", dts_name = "dummpy-tmp.dts") +``` + +## Generate DTB + +Before 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) + +### Include and Macros + +By default, dtc does not support C-style preprocessing (like cpp), but you can use the C preprocessor with your DTS files. +Don't worry — our dtc module already includes this step. + +If your DTS file uses dt-bindings headers or macros, you can write something like: + +```c +/* + * Used "#include" if header file need preprocessor, + * `components/drivers/include` and current directory path is default. + */ +#include <dt-bindings/size.h> +#include "dummy.dtsi" +/* Well, if dtsi is simple, you can use "/include/", it is supported by dtc */ +/include/ "chosen.dtsi" + +#define MMIO_BASE 0x10000 +#define MMIO_SIZE SIZE_GB +#define MEM_BASE (MMIO_BASE + MMIO_SIZE) + +#ifndef CPU_HARDID +#define CPU_HARDID 0 +#endif + +#ifndef SOC_INTC +#define SOC_INTC intc_a +#endif + +/ { + #address-cells = <2>; + #size-cells = <2>; + /* + * Macros after "&" will be replaced, + * there will affect the interrupt controller in this SoC. + */ + interrupt-parent = <&SOC_INTC>; + + [...] + + memory { + /* When there is a calculation, please use "()" to include them */ + reg = <0x0 MEM_BASE 0x0 (3 * SIZE_GB)>; + device_type = "memory"; + }; + + cpus { + #size-cells = <0>; + #address-cells = <1>; + + /* Macros after "@" will be replaced */ + cpu0: cpu@CPU_HARDID { + reg = <CPU_HARDID>; + device_type = "cpu"; + }; + }; + + /* Macros replace support phandle name, too */ + intc_a: intc-a { + interrupt-controller; + }; + + intc_b: intc-b { + interrupt-controller; + }; + + [...] +}; +``` + +To generate the DTB: + +```python +import os, sys + +RTT_ROOT = os.getenv('RTT_ROOT') +sys.path.append(RTT_ROOT + '/tools') + +from building import * +import dtc + +dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"] +``` + +To append more include paths, for example, SoC DM headers: + +```python +[...] + +dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], include_paths = ['dm/include', 'firmware']) +``` + +### Multiple DTB + +A single SoC may have different board variants. +Example `dummy.dtsi` (common base): + +```c +/* SoC dummy */ +/ { + #address-cells = <2>; + #size-cells = <2>; + model = "Dummy SoC Board"; + + [...] + + chosen { + bootargs = "cma=8M coherent_pool=2M"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + + isp_shm@100000 { + reg = <0x0 0x100000 0x0 0x100000>; + }; + + dsp_shm@200000 { + reg = <0x0 0x200000 0x0 0x100000>; + }; + }; + + dsp { + status = "okay"; + }; + + buddy { + isp = <&{/reserved-memory/isp_shm@100000}>; + dsp = <&{/reserved-memory/dsp_shm@200000}>; + }; + + uart0: uart { + status = "disabled"; + }; + + i2c0: i2c { + status = "okay"; + }; + + [...] +}; +``` + +For a vendor-specific variant (Vendor A): + +```c +/* vendorA dummy */ +#include "dummy.dtsi" + +/ { + /* No phandle name can modify in place */ + chosen { + bootargs = "console=uart0 cma=8M coherent_pool=2M"; + }; +}; + +/* Reference and modify direct if has phandle name */ +&uart0 { + status = "okay"; + pinctrl-0 = <&uart0_m1>; +}; + +&i2c0 { + status = "disabled"; +}; +``` + +To remove nodes or properties (Vendor B): + +```c +/* vendorB dummy */ +#include "dummy.dtsi" + +/delete-node/ &dsp_shm; + +/ { + /* Delete in place if no phandle name */ + /delete-node/ dsp; + + /* Delete property */ + buddy { + /delete-property/ dsp; + }; +}; +``` + +To add new devices (Vendor C): + +```c +/* vendorC dummy */ +#include "dummy.dtsi" + +&i2c0 { + rtc@0 { + clock-frequency = <32768>; + }; +}; +``` + +Build all DTBs together: + +```python +[...] + +dtc.dts_to_dtb(RTT_ROOT, ["dummpy-vendorA.dts", "dummpy-vendorB.dts", "dummpy-vendorC.dts"]) +``` + +This will produce `dummpy-vendorA.dtb`, `dummpy-vendorB.dtb`, and `dummpy-vendorC.dtb` + +## Warnings + +DTC may produce warnings that are irrelevant or noisy. +To suppress specific warnings: + +```python +[...] + +dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"]) +``` + +Make sure your DTS is valid! + +## Raw options + +DTC provides additional command-line options (see dtc --help). You can pass raw options like this: + +```python +[...] + +dtc.dtb_to_dts(RTT_ROOT, "dummpy.dtb", options = "--quiet") +dtc.dts_to_dtb(RTT_ROOT, ["dummpy.dts"], options = "--quiet") +``` |
