This shows you the differences between two versions of the page.
ass:cursuri:02:theory:02 [2023/07/19 11:08] radu.mantu |
ass:cursuri:02:theory:02 [2023/07/19 12:11] (current) radu.mantu |
||
---|---|---|---|
Line 1: | Line 1: | ||
==== Flattened Device Trees ==== | ==== Flattened Device Trees ==== | ||
+ | |||
+ | A [[https://www.kernel.org/doc/html/latest/devicetree/usage-model.html|Device Tree]] (DT) is a data structure that (normally) contains a hierarchical representation of the available hardware, but also runtime configuration information. The DT is always written in the [[https://devicetree-specification.readthedocs.io/en/latest/chapter6-source-language.html|Device Tree Source]] (DTS) format and looks something like this: | ||
+ | |||
+ | <spoiler Heavily truncated DTS> | ||
+ | <code> | ||
+ | /dts-v1/; | ||
+ | |||
+ | / { | ||
+ | interrupt-parent = <0x01>; | ||
+ | #address-cells = <0x02>; | ||
+ | #size-cells = <0x02>; | ||
+ | model = "TechNexion PICO-PI-8M"; | ||
+ | compatible = "technexion,pico-pi-imx8m", "fsl,imx8mq"; | ||
+ | |||
+ | cpus { | ||
+ | #address-cells = <0x01>; | ||
+ | #size-cells = <0x00>; | ||
+ | |||
+ | cpu@0 { | ||
+ | device_type = "cpu"; | ||
+ | compatible = "arm,cortex-a53"; | ||
+ | reg = <0x00>; | ||
+ | clock-latency = <0xee6c>; | ||
+ | clocks = <0x02 0x102>; | ||
+ | enable-method = "psci"; | ||
+ | }; | ||
+ | }; | ||
+ | | ||
+ | soc@0 { | ||
+ | compatible = "fsl,imx8mq-soc", "simple-bus"; | ||
+ | #address-cells = <0x01>; | ||
+ | #size-cells = <0x01>; | ||
+ | ranges = <0x00 0x00 0x00 0x3e000000>; | ||
+ | dma-ranges = <0x40000000 0x00 0x40000000 0xc0000000>; | ||
+ | |||
+ | bus@30800000 { | ||
+ | compatible = "fsl,aips-bus", "simple-bus"; | ||
+ | reg = <0x30800000 0x400000>; | ||
+ | #address-cells = <0x01>; | ||
+ | #size-cells = <0x01>; | ||
+ | ranges = <0x30800000 0x30800000 0x400000 0x8000000 0x8000000 0x10000000>; | ||
+ | |||
+ | serial@30890000 { | ||
+ | compatible = "fsl,imx8mq-uart", "fsl,imx6q-uart"; | ||
+ | reg = <0x30890000 0x10000>; | ||
+ | interrupts = <0x00 0x1b 0x04>; | ||
+ | clocks = <0x02 0xcb 0x02 0xcb>; | ||
+ | clock-names = "ipg\0per"; | ||
+ | dmas = <0x11 0x18 0x04 0x00 0x11 0x19 0x04 0x00>; | ||
+ | dma-names = "rx\0tx"; | ||
+ | status = "okay"; | ||
+ | }; | ||
+ | }; | ||
+ | }; | ||
+ | }; | ||
+ | </code> | ||
+ | </spoiler> | ||
+ | \\ | ||
+ | |||
+ | We notice that the DT is structured as multiple nested nodes. Each node can be referenced by a path comprised of the names of all of its ancestors. In fact, nodes that represent hardware devices are usually assigned an alias based on this path: | ||
+ | |||
+ | <spoiler Node aliases> | ||
+ | <code> | ||
+ | aliases { | ||
+ | ethernet0 = "/soc@0/bus@30800000/ethernet@30be0000"; | ||
+ | gpio0 = "/soc@0/bus@30000000/gpio@30200000"; | ||
+ | mmc0 = "/soc@0/bus@30800000/mmc@30b40000"; | ||
+ | mmc1 = "/soc@0/bus@30800000/mmc@30b50000"; | ||
+ | serial0 = "/soc@0/bus@30800000/serial@30860000"; | ||
+ | }; | ||
+ | </code> | ||
+ | </spoiler> | ||
+ | |||
+ | Each node is comprised of //properties// and other node. A property can be a: | ||
+ | * **String:** ''device_type = "cpu";'' | ||
+ | * **Boolean:** ''regulator-boot-on;'' | ||
+ | * Its presence means true. | ||
+ | * **Packed array of integers**: ''reg = <0x30860000 0x10000>;'' | ||
+ | |||
+ | Additionally, there are special properties that start with a ''#'' symbol. These properties are used by the FDT parser as hints on how to interpret the packed array of integers. Normally, each element in the array is a //uint32_t//. However, certain properties (''reg'' especially) usually contain one or more ''(address, size)'' tuples. In the example above, the ''reg'' property located in the ''serial@30890000'' node informs the kernel that the serial (UART) device is mapped in memory starting at ''0x30890000'' has a size of ''0x10000''. Note that in this case we have one tuple where each element consists of precisely one //uint32_t// element. This may not always be the case! Hence, the following properties: | ||
+ | * ''#address-cells'': Number of //uint32_t// cells that comprise the //address// element in each tuple. | ||
+ | * ''#size-cells'': Number of //uint32_t// cells that comprise the //size// element in each tuple. | ||
+ | |||
+ | Knowing these values is the only way to determine the number of tuples in a packed array property. Note, however, that the ''#*-cells'' properties do not apply to the node where they are encountered, but only to its children. For example, if ''bus@30800000'' overrides these properties (whose default value was inherited from ''soc@0''), only the ''reg'' of ''serial@30890000'' would adhere to these changes. The ''ranges'' property of ''bus@30800000'' would still use the values inherited from ''soc@0''. |