Linux device driver model devicetree

Linux device driver model devicetree

Current Linux driver development is inseparable from the configuration of devicetree. What does it do? To simply understand the number of devices, it is a board configuration information description file. At the beginning, the kernel does not have a device tree, and the device information about the board is described in the code, resulting in a lot of board-level related source files in the arch directory of the kernel, all of which are defined in the format of .c or .h. Compared with the rest of the kernel, these configurations are many duplicates. In order to solve such problems, the kernel introduces devicetree, which is specially used to describe board-level configuration information, and the kernel driver parses the device tree to obtain board-level information for configuration. Doing driver work completes the decoupling of driver and board-level configuration. So what exactly does the device tree look like? Follow up below.

devicetree

The device tree is a data structure text describing board-level hardware devices. Device tree files are generally saved with .dts or .dtsi suffixes, and describe board-level resources through nodes and attributes. The following is an introduction using a dts file:

#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/gpio.h>	/* dts中可以通过include引用其他的头文件,使用它们的定义 */
#include "sun8iw18p1-clk.dtsi"		/* 可以引用其它的dts文件 */
#include "sun8iw18p1-pinctrl.dtsi"

/ {
    
    			/* device tree,树总会有根,而/则是设备树的根,其他的都是节点,节点可以包含子节点 */
        cpus {
    
    	/* cpus作为根节点下的一个子节点,它也包含了cpu0、1两个子节点以及enable-method等属性信息 */
                enable-method = "allwinner,sun8iw18p1";
                #address-cells = <1>;
                #size-cells = <0>;

                cpu@0 {
    
    
                        device_type = "cpu";
                        compatible = "arm,cortex-a7","arm,armv7";
                        reg = <0x0>;
                        enable-method = "psci";
                    	/* 描述设备的时钟依赖信息,后续驱动可获取该信息 */
                        clocks = <&clk_pll_cpu>,<&clk_cpu>,<&clk_pll_periph0>;
                        clock-names = "pll","cpu","periph0";
                        operating-points-v2 = <&cpu_opp_l_table0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 &SYS_SLEEP_0>;
                };
        }
}

You can simply understand that when the device tree is turned on, the system will parse the dts one by one and register the device for it, and then we will write the driver. When the driver matches the device, the device can be used normally. Regarding the device tree, remember one thing: as long as it conforms to the syntax rules, everything else needs to be parsed by the driver. Therefore, in addition to the devicetree information, the driver also needs to parse the device tree. The parsing interface is introduced below.

Commonly used devicetree APIs

Get the integer variable from the device tree :

int of_property_read_u32(const struct device_node *np,
                         		const char *propname,
                         		u32 *out_value);
int of_property_read_u16(const struct device_node *np,
                         		const char *propname,
                         		u16 *out_value);

The above interface can be obtained from the device tree or shaped variables, such as:

// dts
        dao: dao-test {
    
    
                compatible = "dao-test";
                num = <12>;
        };

u32 value;
np指向dao节点,此时通过 of_property_read_u32(np, "num", &value)获取“num”指向的内容,此时value=12

Get a string variable from the device tree :

 int of_property_read_string(const struct device_node *np,
                                   const char *propname,
                                   const char **out_string);

The usage is as follows:

// dts
        dao: dao-test {
    
    
                compatible = "dao-test";
                num = <12>;
            	str_info = "test_info";
        };

const char *info;
np指向dao节点,此时通过 of_property_read_string(np, "str_info", &info)获取“str_info”指向的内容,此时info指向的内容是“test_info”。

More APIs can include/linux/of.hbe used by referring to the interfaces in the kernel.

devicetree conversion

The device tree is used in the kernel stage. In the editing stage, it is the text state of dts. When the kernel is used, it is converted into a dtb binary file. During the system startup process, uboot loads it and passes it to the kernel for use . The conversion of this device tree is performed through the dtc tool. The dtc tool is generally included in the kernel source code. dtc supports the following commands:

root@root#./scripts/dtc/dtc --help
Usage: dtc [options] <input file>

Options: -[qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv]
  -q, --quiet
        Quiet: -q suppress warnings, -qq errors, -qqq all
  -I, --in-format <arg>
        Input formats are:
                dts - device tree source text
                dtb - device tree blob
                fs  - /proc/device-tree style directory
  -o, --out <arg>
        Output file
  -O, --out-format <arg>
        Output formats are:
                dts - device tree source text
                dtb - device tree blob
                asm - assembler source
  -V, --out-version <arg>
        Blob version to produce, defaults to 17 (for dtb and asm output)
  -d, --out-dependency <arg>
        Output dependency file
  -R, --reserve <arg>
        Make space for <number> reserve map entries (for dtb and asm output)
  -S, --space <arg>
        Make the blob at least <bytes> long (extra space)
  -p, --pad <arg>
        Add padding to the blob of <bytes> long (extra space)
  -a, --align <arg>
        Make the blob align to the <bytes> (extra space)
  -b, --boot-cpu <arg>
        Set the physical boot cpu
  -f, --force
        Try to produce output even if the input tree has errors
  -i, --include <arg>
        Add a path to search for include files
  -s, --sort
        Sort nodes and properties before outputting (useful for comparing trees)
  -H, --phandle <arg>
        Valid phandle formats are:
                legacy - "linux,phandle" properties only
                epapr  - "phandle" properties only
                both   - Both "linux,phandle" and "phandle" properties
  -W, --warning <arg>
        Enable/disable warnings (prefix with "no-")
  -E, --error <arg>
        Enable/disable errors (prefix with "no-")
  -@, --symbols
        Enable generation of symbols
  -A, --auto-alias
        Enable auto-alias of labels
  -T, --annotate
        Annotate output .dts with input source file and line (-T -T for more details)
  -h, --help
        Print this help and exit
  -v, --version
        Print version and exit

There are many parameters supported by dtc, but -I -i -O -othese parameters are commonly used by us. Through them, the input and output files and formats are specified, and the dtb file is obtained and then attached to the kernel image.

Guess you like

Origin blog.csdn.net/weixin_41944449/article/details/132799957