0% found this document useful (0 votes)
79 views

Device Tree Learning (DTS) by SSM

The document discusses device trees, which describe hardware configurations in a tree structure format. It covers what a device tree is, the benefits of using one over traditional models, the file types (DTS, DTSI, DTB), syntax including nodes and attributes, and how the DTC tool compiles device tree source files into binary files. Key points include that a device tree describes hardware resources like memory and interrupts to allow drivers to be hardware-agnostic, DTS files are compiled into DTB files passed to the kernel, and the DTC tool relies on files like dtc.c to perform the compilation.

Uploaded by

Siba Ssm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
0% found this document useful (0 votes)
79 views

Device Tree Learning (DTS) by SSM

The document discusses device trees, which describe hardware configurations in a tree structure format. It covers what a device tree is, the benefits of using one over traditional models, the file types (DTS, DTSI, DTB), syntax including nodes and attributes, and how the DTC tool compiles device tree source files into binary files. Key points include that a device tree describes hardware resources like memory and interrupts to allow drivers to be hardware-agnostic, DTS files are compiled into DTB files passed to the kernel, and the DTC tool relies on files like dtc.c to perform the compilation.

Uploaded by

Siba Ssm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
You are on page 1/ 7

Linux:Device Tree Learning (1)

1. What is a device tree


2. Why use a device tree instead of a traditional bus device-driven model
3. DTS、DTB 和 DTC
4. DTS syntax
4.1 .dtsi header file
4.2 Device Nodes
4.3 Standard Attributes
5. DTS compilation
5.1 Kernel compilation device tree
5.2 The DTC tool compiles the device tree

1. What is a device tree


A device tree is a data structure that describes on-chip and off-chip device information in a unique syntactic format. The BootLoader is passed to
the kernel, and the kernel parses it to form a dev structure associated with the driver for use by the driver code.
The DTS file describes the device-level device in a tree-like structure, that is, the device information on the development board, such as the number
of CPUs, memory base addresses, which devices are connected to the IIC interface, which devices are connected to the SPI interface, and so on.
The backbone of the tree is the system bus, and the IIC controller, GPIO controller, SPI controller, etc. are all branches connected to the main line
of the system. There are two types of IIC controllers: IIC1 and IIC2, where IIC1 is connected to the FT5206 and AT24C02, and IIC2 is connected to
only MPU6050 device. The main function of the DTS file is to describe the device information on the board according to the structure shown in the
figure.

2. Why use a device tree instead of a traditional bus device-driven model


The traditional bus device driver describes the device information in C code, and when it is necessary to modify the hardware information related to
the driver, the specific code file must be modified, and then the kernel is fully compiled. The whole operation is cumbersome and not conducive to
the maintenance and porting of the code.
The device tree completely separates the driver from the device. Drivers are designed to be hardware-agnostic, and all device resources (e.g.,
memory, interrupt, clk, pinctrl) are defined in the device tree file. kernel to adapt driver and device information. Pass the valid device information to
the probe function of the driver through the parameters, and then initialize the specific hardware. In this way, when the hardware is changed (each
company designs the PCB separately based on the public version of the chip), you only need to modify the corresponding device tree file, and you
don't need to change the driver code at all. The versatility of the drive will also be greatly provided. In this way, multiple series chips only need to
share the same set of driver code, differential device tree files.

3. DTS、DTB 和 DTC
The code files for the device tree are DTS files and DTSI files.

1. dts is the device tree source code file;


2. The dtsi file is similar to the include header file, which can be included by the dts file;
3. dtb is a binary file obtained by compiling dts.

The DTS file is compiled by the DTC (Device Tree Compiler) into a DTB (Device Tree Block) binary. The file will be flashed to a specific address in
memory (specified by the BootLoader, in principle, as long as it does not overwrite the contents of the boot and kernel). The BootLoader then
passes the address to the kernel as a parameter. The kernel parses valid device information according to the specific format of the DTB file and
passes it to the driver code.
The source code of the dtc tool is located in the scripts/dtc directory of the Linux kernel:
Insert a description of the picture here

kernel/msm-5.4/scripts/dtc$ cat Makefile

# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile

hostprogs-$(CONFIG_DTC) := dtc
ifeq ($(DTC_EXT),)
always := $(hostprogs-y)
endif

dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \


srcpos.o checks.o util.o
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o

# Source files need to get at the userspace version of libfdt_env.h to compile


HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt

ifeq ($(shell pkg-config --exists yaml-0.1 2>/dev/null && echo yes),)


ifneq ($(CHECK_DTBS),)
$(error dtc needs libyaml for DT schema validation support. \
Install the necessary libyaml development package.)
endif
HOST_EXTRACFLAGS += -DNO_YAML
else
dtc-objs += yamltree.o
HOSTLDLIBS_dtc := $(shell pkg-config yaml-0.1 --libs)
endif

# Generated files need one more search path to include headers in source tree
HOSTCFLAGS_dtc-lexer.lex.o := -I $(srctree)/$(src)
HOSTCFLAGS_dtc-parser.tab.o := -I $(srctree)/$(src)

# dependencies on generated files need to be listed explicitly


$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h

The DTC tool relies on files such as dtc.c, flattree.c, fstree.c, etc., and finally compiles the DTC as a host file. If you want to compile a DTS file, you
just need to go to the root directory of the Linux source code and run the following command: make all or make dtbs.

4. DTS syntax
4.1 .dtsi header file
Like C, headers are supported in the device tree, which has a .dtsi extension. At the same time, .dts files can also reference .h files in C, and even
.dts files.
Generally, the .dtsi file is used to describe the internal peripheral information of the SOC, such as the CPU architecture, the main frequency, and the
address range of the peripheral registers, such as UART, IIC, etc.

4.2 Device Nodes


The device tree is a file that uses a tree structure to describe the device information on the board, each device is a node, called the equipment
node, and each node describes the node information through some attribute information, and the attribute is the key-value pair.
kernel4.14\arch\arm\boot\dts\spear300.dtsi

/include/ "spear3xx.dtsi"

/ {
ahb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0x60000000 0x60000000 0x50000000
0xd0000000 0xd0000000 0x30000000>;

pinmux@99000000 {
compatible = "st,spear300-pinmux";
reg = <0x99000000 0x1000>;
};

clcd@60000000 {
compatible = "arm,pl110", "arm,primecell";
reg = <0x60000000 0x1000>;
interrupts = <30>;
status = "disabled";
};
fsmc: flash@94000000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x94000000 0x1000 /* FSMC Register */
0x80000000 0x0010 /* NAND Base DATA */
0x80020000 0x0010 /* NAND Base ADDR */
0x80010000 0x0010>; /* NAND Base CMD */
reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
status = "disabled";
};

sdhci@70000000 {
compatible = "st,sdhci-spear";
reg = <0x70000000 0x100>;
interrupts = <1>;
status = "disabled";
};

shirq: interrupt-controller@0x50000000 {
compatible = "st,spear300-shirq";
reg = <0x50000000 0x1000>;
interrupts = <28>;
#interrupt-cells = <1>;
interrupt-controller;
};

apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xa0000000 0xa0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;

gpio1: gpio@a9000000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xa9000000 0x1000>;
interrupts = <8>;
interrupt-parent = <&shirq>;
status = "disabled";
};

kbd@a0000000 {
compatible = "st,spear300-kbd";
reg = <0xa0000000 0x1000>;
interrupts = <7>;
interrupt-parent = <&shirq>;
status = "disabled";
};
};
};
};

The basic unit of the device tree is the node, which consists of the root node (/) and its child nodes (name@addr), and the child nodes can also
have child nodes, forming a tree-like structure.
In the example above:
1. "/" is the root node, and each device tree file has only one root node.
2. AHB is a child node, and the node name format in the device tree is as follows:

node-name@unit-address

"node-name" is the name of the node, which is an ASCII string, and the node name should be able to clearly describe the function of the node, for
example, "uart1" means that the node is a UART1 peripheral. "unit-address" generally indicates the address of the device or the first address of the
register, if a node does not have an address or register, "unit-address" can be dispensed with, such as "cpu@0" or "interrupt-
controller@00a01000".
Another format:

label: node-name@unit-address

The purpose of introducing label is to facilitate access to the node, which can be accessed directly through &label, for example, through &cpu0, you
can access the node "cpu@0" without entering the full node name.

4.3 Standard Attributes


Nodes are composed of a bunch of attributes, nodes are specific devices, different devices need different attributes, users can customize attributes.
In addition to user-defined attributes, there are many standard attributes, which are used by many peripheral drivers under Linux, and several
commonly used standard attributes:
1. compatible property
The compatible property, also known as the "compatibility" property, can be understood as the compatibility ID of the node, and its value is a list of
strings through which the kernel matches the driver. The composite of the root node is more indicative of the types of platforms supported by the
device tree. The string list is used to select the driver to be used by the device, and the value format of the compatible attribute is as follows:

"manufacturer,model"

manufacturer indicates the manufacturer, and model is generally the driver name corresponding to the module.

1. model property
The value of the model property is also a string, and the model attribute generally describes the device module information, such as the name.

例如:kernel4.14\arch\arm\boot\dts\sun8i-a33-et-q8-v1.6.dts

/ {
model = "Q8 A33 Tablet";
compatible = "allwinner,q8-a33", "allwinner,sun8i-a33";
};

compatible = “allwinner,q8-a33”, “allwinner,sun8i-a33”; This means that the current device tree supports Allwinner's Q8-A33 platform and Sun8i-A33
platform. When the kernel runs the mach platform file in the corresponding arch directory, it will match the device tree and then load it.
1. status property
The status attribute is related to the state of the device, and the value of the status attribute is also a string, and the string is the state information
of the device.

Insert a description of the picture here

1. #address-cells and #size-cells properties


The values of both properties are unsigned 32-bit integers, and the #address-cells and #size-cells properties can be used on any device that has
a child node to describe the address information of the child node. The value of the #address-cells attribute determines the word length (32 bits)
occupied by the address information in the reg attribute of the child node, and the value of the #size-cells attribute determines the word length (32
bits) occupied by the length information in the reg attribute of the child node. #address-cells and #size-cells indicate how the child node should
write the reg attribute value, generally the reg attribute is related to the address, and there are two kinds of address-related information: the start
address and the address length, the format of the reg attribute is:

reg = <address1 length1 address2 length2 address3 length3……>

Each "address length" combination represents an address range, where address is the starting address, length is the address length, #address-
cells indicates the length of the word used by the address data, and #size-cells indicates the length of the word used by the data.

fsmc: flash@94000000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x94000000 0x1000 /* FSMC Register */
0x80000000 0x0010 /* NAND Base DATA */
0x80020000 0x0010 /* NAND Base ADDR */
0x80010000 0x0010>; /* NAND Base CMD */
reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
status = "disabled";
};

The first address of the reg in FSMC is 0x94000000, and its size is 0x1000; The second address is 0x80000000, and its size is 0x0010; The third
address is 0x80020000, which is 0x0010 in size; The fourth address is 0x80010000, which is 0x0010 in size. This means that this device occupies
four blocks of register address space, and the start address and offset of each block are listed in the reg.
1. reg attribute
The value of the reg attribute is usually (address, length) pairs. Generally, it is used to describe the resource information of the device address
space, which is the register address range information of a peripheral.
2. ranges property
The ranges attribute can be empty or a matrix of numbers written in the format (child-bus-address, parent-bus-address, length), ranges is an
address mapping/conversion table, and the ranges attribute consists of three parts: child address, parent address, and address space length:

apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xa0000000 0xa0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;

gpio1: gpio@a9000000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xa9000000 0x1000>;
interrupts = <8>;
interrupt-parent = <&shirq>;
status = "disabled";
};

kbd@a0000000 {
compatible = "st,spear300-kbd";
reg = <0xa0000000 0x1000>;
interrupts = <7>;
interrupt-parent = <&shirq>;
status = "disabled";
};
};

child-bus-address: The physical address of the subbus address space, the word length occupied by the #address-cells of the parent node
determines the number of words occupied by this physical address.
parent-bus-address: the physical address of the parent bus address space, which is also determined by the #address-cells of the parent node.

length: the length of the child address space, which is determined by the #size-cells of the parent node.

If the value of the ranges property is null, the child address space and the parent address space are identical, and address translation is not
required.
1. aliases property
aliases means "aliases", so the main function of aliases nodes is to define aliases, and the purpose of defining aliases is to facilitate access to the
node. Nodes that don't use aliases to reference nodes use an absolute path, like /soc/serial0. It is mainly used outside the device tree, and the
internal reference node of the device can use the label. When naming nodes, label will be added, and then the node will be accessed through
&label, which is more convenient, and a lot of the device tree will be used in the form of &label to access nodes.
2. chosen attribute
The chosen node is not a real device, and the chosen node is mainly used to pass data to the Linux kernel for uboot, such as bootargs, which
does not represent the actual device. Its parent node must be the root node. In general, the chosen node in a .dts file is usually empty or has very
little content.

如kernel4.14\arch\arm\boot\dts\sun8i-r16-bananapi-m2m.dts

/dts-v1/;
#include "sun8i-a33.dtsi"

#include <dt-bindings/gpio/gpio.h>
/ {
model = "BananaPi M2 Magic";
compatible = "sinovoip,bananapi-m2m", "allwinner,sun8i-a33";

aliases {
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
serial0 = &uart0;
serial1 = &uart1;
};

chosen {
stdout-path = "serial0:115200n8";
};
...

1. memory node
The memory node is a required node of the device tree file, and the device_type attribute indicates that the type of the node is memory, which
defines the layout of the system's physical memory, that is, the start address and length. There can be multiple memory nodes, which represent
multiple segments of memory.

/ {
memory {
reg = <0x00000000 0x20000000>;
};
...

1. Binding information documents


The device tree is used to describe the device information on the board, and the information of different devices is different, and the attributes
reflected in the device tree are different. So where can we find the relevant instructions when we add a node corresponding to the hardware in the
device tree? There are detailed .txt documentation in the Linux kernel source code that describes how to add nodes, these .txt documents are
called binding documents, and the path is: kernel/Documentation/devicetree/bindings.
2. The OF operation function is commonly used in the device tree
The device tree describes the details of the device, including number, string, and array, which we need to get when writing the driver. The Linux
kernel provides us with a series of functions to obtain node or attribute information in the device tree, and this series of functions has a unified
prefix "of_", so it is also called OF function in many materials. These OF function prototypes are defined in the kernel/include/linux/of.h file.

5. DTS compilation
5.1 Kernel compilation device tree
Add the compilation option of the dts file to the Makefile in the kernel/arch/arm/boot/dts/ directory, and make dtbs in the kernel directory to get the
corresponding dtb binary.

5.2 The DTC tool compiles the device tree


Compile the device tree using the DTC tool in Ubuntu:

1. DTC Tool Installation:

sudo apt-get install device-tree-compiler

1. Compile the device tree:

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

1. Device tree disassembly

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

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy