Menu Close

设备树中的标准属性

此文章介绍了设备树中的标准属性。

相关参考文章:SOC 教学教案

 

节点由许多不同属性构成,不同的设备需要不同的属性;用户也可以创建自定义的属性。自定义属性除外,许多其他属性是标准属性,并且被无数Linux外设驱动使用。其中最常用的标准属性如下:

 

compatible

compatible兼容性属性的值可以是字符串也可以是字符串列表,其中格式通常为 <制造商>,<型号>。 您可以选择使用其他格式,但这是绝大多数人为了统一和兼容而使用的格式。例子如下:

compatible = “manufacturer1,model1”,“manufacturer2,model2”;

compatible 属性用于在设备和驱动程序之间创建关联:设备将先在 Linux 内核中搜寻第一个兼容的值(例如manufacturer1,model1)查看是否有相匹配的驱动;如果没有找到任何匹配的值,它将继续去查询下一个兼容值(例如manufacturer2,model2),直到它找到匹配值或搜索了整个内核。

驱动文件通常都拥有一个 0F 匹配表,其中存储着一些 compatible 的值。如果任何一个匹配表值跟设备树节点中的 compatible 值一样,那将表示设备可以使用驱动。一个例子就是 /drivers/tty/serial/ 目录下的 xilinx_uartps.c。

%title插图%num

%title插图%num

以上代码设置了 platform_driver 的 0F 匹配表。主要部分位于第1709行,其中 .of_match_table 被设为了 cdns_uart_of_match。

 

model

model属性是一个指定设备型号的字符串,并且通常定义在根节点中。其主要目的是帮助描述设备,并且在内核解析设备树时会印出字符串。

作为例子,如果我们把model值设为如下图system-top.dts文件中一样,它将显示指定的字符串为设备型号。注意chosen,aliases,以及memory都为简单起见在例子中省略了。

/dts-v1/;
#include “zynq-7000.dtsi”
#include “pl.dtsi”
#include “pew.dtsi”
/{
    model = “xlnx,zynq-7000”;

    chosen{
        ...
    };
    aliases{
        ...
    };
    memory{
        ...
    };
};

%title插图%num

 

status

status 属性用于标注设备的状态,并且可以禁用或启用设备。设置status值时有四个选项:

okay                         表示设备可操作,并且启用设备。

disabled                  表示设备当前不可操作,但是可被启用。

fail                            表示设备因为检测到了错误而不可操作,且启用可能性很小。

fail-[错误内容]        跟fail 一样,但是显示检测到的错误。

例如:

status = "okay";

 

#address-cells 和 #size-cells

这两个属性都是32位无符号整形,并且可以用在任何有子节点的设备节点中,因为它用于描述子节点的地址信息。

#address-cells 用于描述子节点 reg 属性地址表中描述首地址的cell的数量。

#size-cells 用于描述子节点 reg 属性地址表中描述地址长度的 cell 的数量。

两个属性都表明了子节点怎样编写 reg 属性值。reg 属性通常都跟地址有关,主要是首地址和地址长度。reg 属性能够使用这两个参数描述一块连续的地址区域。格式如下:

reg = <地址1 长度1 地址2 长度2 地址3 长度3>

注意每个地址和长度都表示一个地址部分,#address-cells 定义了 address 的长度并且 #size-cells 定义了 length 的长度。请见以下例子。

&qspi{
    #address-cells = <1>;
    #size-cells = <0>;
    #flash0:flash@0{
        compatible = "n25q512a","micron,m25p80";
        reg = <0x0>;
        #address-cells = <1>;
        #size-cells = <1>;
        #spi-max-frequency = <50000000>;
        partition@0x00000000{
            label = "boot";
            reg = <0x00000000 0x00500000>;
        };
        partition@0x00500000{
            label = "bootenv";
            reg = <0x00520000 0x00a80000>;
        };
        partition@0x00520000{
            label = "kernel";
            reg = <0x00520000 0x00a80000>;
        };
        partition@0x00fa0000{
            label = "spare";
            reg = <0x00fa0000 0x00000000>;
        };
    };
};

注意刚开始 qspi 节点的 #address-cells 是 <1>,并且 #size-cells 是 <0>。这意味子节点 reg 的首地址是使用 32 位数据表示的。在第 6 行我们可以看到子节点 flash0:flash@0 的 reg 值为 <0>。因为父节点把 #address-cells 设为了 <1> 且把 #size-cells 设为了 <0>,所以地址是 0 并且没有一个 length 长度值。相当设了首地址但是没有设地址长度。

在第 7 行和第 8 行 flash0:flash@0 节点把 #address-cells 和 #size-cells 都设为了 <1>,表示 flash0:flash@0 的子节点将拥有首地址且地址长度为 1。

 

reg

如上一小部分所示,reg 的参数通常是成对的 address 和 length。reg 通常用于描述设备地址和资源,其主要关于外设寄存器和 flash 设备分区信息。一个例子就是 /arch/arm/boot/dts/ 目录下 zynq-7000.dts 中的 174 至 181 行:

uart0:serial@e00000000{
    compatible = “xlnx,xuartps”,“cdns,uart-r1p8”;
    status = “disabled”;
    clocks = <&clkc 23>,<&clkc 40>;
    clock-names = “uart_clk”,“pclk”;
    reg = <0xE0000000 0x1000>;
    interrupts = <0 27 4>;
};

以上代码是 uart0 节点,其中描述了 ZYNQ PS 端口 UART0 的相关信息。此代码的核心部分是倒数第三行的 reg 配置,把 address 地址属性设为了 0xE0000000 并把 length 属性设为了 0x1000。起始地址 0xE0000000 是 ZYNQ 的 UART0 寄存器的起始地址。

 

device_type

device_type 一般使用一个字符串指定节点类型。 虽然此属性整体不常用,它通常用在与 cpu 或内存相关的节点中。一个例子就是 zynq-7000.dtsi 中的 cpu0 和 cpu1 节点:

cpu0:cpu@0{
    compatible = “arm,cortex-a9”;
    device_type = “cpu”;
    reg = <0>;
    clocks = <&clkc 3>;
    clock-latency = <1000>;
    cpu0-supply = <&regulator_vccpint>;
    operating-points = <
                            /* kHz  uV */
                            666667 1000000
                            333334 1000000
                            >;
};

cpu1:cpu@1{
    compatible = “arm,cortex-a9”;
    device_type = “cpu”;
    reg = <1>;
    clocks = <&clkc 3>;
};

注意device_type被设为了cpu。

 

ranges

ranges 是一个地址转换表,其中每一个项目都是一个子节点,父节点,以及在子地址空间的大小的映射。ranges 的属性值可以选择留空,也可以根据(子总线地址,父总线地址,长度)格式设为一个数字矩阵。映射表中的父子地址的长度由 ranges 属性在的节点和父节点里的 #address-cells 决定。子地址空间长度占用的字长由 ranges 属性所在的节点中的 #address-cells 决定。

子总线地址(child-bus-address)   是子总线地址空间的物理地址,其占用的字长由 ranges 属性所在

的节点中的 #address-cells决定。

 

父总线地址(parent-bus-address)是父总线地址空间的物理地址,其占用的字长由ranges属性所在

的父节点中的 #address-cells决定。

 

长度(length)                                     是子地址空间的长度,其占用的字长由ranges属性所在的节点中

的 #address-cells决定。

 

注意如果ranges值被留空,那将表明子节点跟父节点一样,并且没有必要进行地址转换。如果没有被留空,将如以下例子差不多:

soc{
    compatible = “simple-bus”;
    #address-cells = <1>;
    #size-cells = <1>;
    ranges = <0x0 0xe0000000 0x00100000>;

    serial{
        device_type = “serial”;
        compatible = “ns16550”;
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
    };
};

注意 SoC 中定义的 ranges 把地址范围设为了 0x00100000(1024KB),其中子地址空间的物理起始地址为 0x0,并且父地址空间的物理起始地址为 0xe0000000。

serial 是串口设备节点,其中 reg 把串口设备的起始地址设为了 0x4600,且长度为 0x100。地址转换后,串口设备可以从 0xe0000000(0xe0004600 = 0x4600 + 0xe0000000)进行读写。

Posted in 教材与教案

发表评论

相关链接