我是靠谱客的博主 自由香烟,最近开发中收集的这篇文章主要介绍ARM Linux设备树(3),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在.dts文件中对设备及其属性的描述通常如以下这样:

/ {
    compatible = "acme, coyotes-revenge";
    #address-cells = <1>;
    #size-cells = <1>;
    ...

    cpus {
        #address-cells = <1>;
        #size-cells = <0>;
        cpu@0 {
            compatible = "arm, cortex-a9";
            reg = <0>;
        };
        cpu@1 {
            compatible = "arm, cortex-a9";
            reg = <1>;
        };
    };

    serial1@101f0000 {
        compatible = "arm,pl1011";
        reg = <0x101f0000 0x1000>;
        interrupts = < 1 0 >;
    };
    
    ...

    external-bus {
        #address-cells = <2>;
        #size-cells = <1>;
        ranges = <0 0 0x10100000 0x1000     // ChipSelect 1, Ethernet
                  1 0 0x10160000 0x1000     // ChipSelect 2, i2c controller
                  2 0 0x30000000 0x100000>; // ChipSelect 3, NOR Flash

        ethernet@0,0 {
            compatible = "smc,smc91c111";
            reg = <0 0 0x1000>
            interrupts = < 5 2 >;
        }; 

        ...   
    }; 
};

其中compatible代表设备节点的兼容属性(略);

reg代表地址编码,reg组织形式为:

reg = <address1 length1 [address2 length2] [address3 length3] ... >

以上的每组 “address length” 表征了设备使用的一个地址范围。

address为1个或者多个32-bit的整型(即cell);

length的含义是从 address 到 address + length - 1 的地址范围都属于该设备节点;

(一)地址编码

前述 address 和 length 字段是可变长度的,父节点的 #address-cells 和 #size-cells 分别决定了子节点reg属性的 address 字段的个数和 length 字段的个数。

若#size-cells = <0>,则表示length字段为空。

在上述.dts文件描述中,root节点的:#address-cells = <1>; #size-cells = <1>; 意味着root节点下面的各个子节点的 address字段和 length字段的个数分别为1。例如,serial1这个子节点:

reg = <0x101f0000 0x1000>

它就是符合:address字段的个数为1,length字段的个数为1。

而 cpus 这个子节点它又包含了子节点,并且 cpus 的 reg 属性是:#address-cells = <1>; #size-cells = <0>; 所以 cpus 的子节点 cpu 的reg属性为:

reg = <0> 

或者 reg = <1>

即 length 字段为空。

接着,再看 root 节点的 external-bus 子节点:

external-bus {
    #address-cells = <2>;
    #size-cells = <1>;
    ranges = <0 0 0x10100000 0x1000        // ChipSelect 1, Ethernet
                     1 0 0x10160000 0x1000        // ChipSelect 2, i2c controller
                     2 0 0x30000000 0x100000>; // ChipSelect 3, NOR Flash

    ethernet@0,0 {
        compatible = "smc,smc91c111";
        reg = <0 0 0x1000>
        interrupts = < 5 2 >;
    };
    ...
   
};

它代表 address 字段的个数为2,而 length 字段的个数为1。意味着其下的 ethernet 子节点的 reg 属性形如:

reg = <0 0 0x1000>;

值得说明的是,通常 root 节点的直接子节点的 address 区域就直接位于 CPU 的内存区域,而经过总线桥以后的 address 往往需要经过转换才能对应到 CPU 的内存映射区域。

在以上 external-bus 节点的描述中,ranges 表示地址转换表。

ranges 中的每个项目是:子 address + 父 address (子 address 的地址映射)及映射的大小。

具体而言,external-bus 这个子节点的 #address-cells 值为2,而其父节点(root 节点)的 #address-cells 值为1,所以 ranges 中:

0 0 0x10100000 0x1000

前面两个cell (即 0 0 )代表总线桥上面片选 0 和 偏移地址 0;

第3个cell (即 0x10100000 )代表总线桥上面片选 0 和 偏移地址 0 的地址空间被映射到了 CPU 本地总线的 0x10100000 位置,也就是所谓的 “父 address” ;

第4个cell(即 0x1000 )代表地址空间映射的大小为 0x1000 。

(二)中断控制器节点

intc: interrupt-controller@10140000 {
    compatible = "arm,pl190";
    reg = <0x10140000 0x1000>;
    interrupt-controller;
    #interrupt-cells = <2>;
};

上述 #interrupt-cells 与 #address-cells 和 #size-cells 相似,它表示连接到此中断控制器的设备的中断属性的 cell 个数。

在整个设备树中,与中断相关的属性还有:

1)interrput-parent属性

设备节点通过它来指定它所依附的中断控制器的phandle,当设备节点没有指定 interrupt-parent 属性之时,则从父级节点继承。

2)interrupts属性

设备节点通过它指定中断号、触发方法等,这个属性具体包含多少个 cell,由它依附的中断控制器节点的 #interrupt-cells 属性决定。而每个 cell 具体又是什么含义,一般由驱动的实现决定,而且也会在设备树的绑定文档中进行说明。

(三)GPIO控制器节点

对于GPIO控制器而言,其对应的设备需声明 gpio-controller 属性,并设置 #gpio-cell 的个数。例如:

pinctrl@80018000 {
    compatible = "fsl,imx28-pinctrl","simple-bus";
    reg = <0x80018000 2000>;
    
    gpio0: gpio@0 {
        compatible = "fsl,imx28-gpio";
        interrupts = <127>;
        gpio-controller;
        #gpio-cells = <2>;
        interrupt-controller;
        #interrupt-cells = <2>;
    };

    gpio1: gpio@0 {
        compatible = "fsl,imx28-gpio";
        interrupts = <126>;
        gpio-controller;
        #gpio-cells = <2>;
        interrupt-controller;
        #interrupt-cells = <2>;
    };
};

其中,#gpio-cells 为2,第一个 cell 为 GPIO 号,第二个 cell 为 GPIO 的极性:为0的时候是高电平有效,为1的时候是低电平有效。

使用GPIO的其他设备可以通过定义 xxx-gpios 属性来引用 GPIO 控制器设备节点,例如:

sdhci@c8000400 {
    status = "okay";
    cd-gpios = <&gpio01 0>;
    wp-gpios = <&gpio02 0>;
    power-gpios = <&gpio03 0>;
    bus-width = <4>;
};

而具体的设备驱动则通过以下方法来获取GPIO:

cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
power_gpio = of_get_named_gpio(np, "power-gpios", 0);

of_get_named_gpio这个API的原型如下:

static inline int of_get_named_gpio(
                      struct device_node *np,
                      const char *propname, int index );

最后

以上就是自由香烟为你收集整理的ARM Linux设备树(3)的全部内容,希望文章能够帮你解决ARM Linux设备树(3)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部