Linux设备驱动模型之devicetree

Linux设备驱动模型之devicetree

当前Linux驱动开发,离不开devicetree的配置,它是干什么的呢?简单理解设备数,它就是一个板子配置信息描述文件。一开始内核并没有没有设备树,关于板端的设备信息都是在代码中描述,从而导致内核的arch目录下非常多板级相关的源文件,都是以.c或.h的格式定义。相对内核的其他而言,这些配置很多重复的,为了解决这样的问题,内核引进了devicetree,专门用来描述板级的配置信息,而内核的驱动则解析设备树获取板级信息进行配置,驱动干驱动的事情,完成了驱动和板级配置的解耦。那么设备树具体是怎样的呢?下面继续跟进。

devicetree

设备树是描述板级硬件设备的数据结构文本,设备树文件一般以.dts或.dtsi为后缀的文件进行保存,通过节点和属性来描述板级资源。下面以一个dts文件进行介绍:

#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>;
                };
        }
}

大家可以简单理解,设备树在开机的时候,系统会逐个解析dts并为之注册设备,而我们再编写驱动,当驱动与设备匹配时,则可以正常使用该设备。关于设备树,记住一点:只要符合语法规则即可,其他的都需要由驱动进行解析。所以,除了devicetree的信息外,驱动还需要对设备树进行解析,解析的接口下面介绍。

常用devicetree api

从设备树获取整形变量

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);

上述的接口可以从设备树中或者整形变量,比如:

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

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

从设备树获取字符串变量

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

而使用方式如下:

// 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”。

更多的api可参考内核include/linux/of.h中的接口进行使用。

devicetree转换

设备树是在内核阶段使用的,编辑阶段,是dts的文本状态,而在内核使用时,则是将其转换为dtb二进制文件,系统在启动过程中,uboot再将其加载传递给内核进行使用。而这个设备树的转换则是通过dtc工具进行转换的,dtc工具一般在内核源码中有包含,dtc支持以下命令:

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

dtc支持的参数较多,但我们常用的就是-I -i -O -o这几个参数,通过他们指定输入输出文件和格式,得到dtb文件后再附加到内核镜像。

猜你喜欢

转载自blog.csdn.net/weixin_41944449/article/details/132799957