下面从节点,属性,reg,ranges,中断控制器等几个方面叙述devicetree的书写规范。
1,dts的基本元素:节点
.dts(或者其include的.dtsi)基本元素为结点和属性。举例说明节点的概念:
/ { node1 { a-string-property = "A string"; a-string-list-property = "first string", "second string"; a-byte-data-property = [0x01 0x23 0x34 0x56]; child-node1 { first-child-property; second-child-property = <1>; a-string-property = "Hello, world"; }; child-node2 { }; }; node2 { an-empty-property; a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */ child-node1 { }; }; };
1个root结点"/";root结点下面含一系列子结点,本例中为"node1"和"node2";
结点"node1"下又含有一系列子结点,本例中为"child-node1"和"child-node2";
各结点都有一系列属性。这些属性可能为空,如"an-empty-property";可能为字符串,如"a-string-property";可能为字符串数组,如"a-string-list-property";可能为Cells(由u32整数组成),如"second-child-property",可能为二进制数,如"a-byte-data-property"。
子结点的命名遵循的组织形式为:<name>[@<unit-address>],<>中的内容是必选项,[]中的则为可选项。name是一个ASCII字符串,用于描述结点对应的设备类型,如3comEthernet适配器对应的结点name宜为ethernet,而不是3com509。如果一个结点描述的设备有地址,则应该给出@unit-address。多个相同类型设备结点的name可以一样,只要unit-address不同即可。设备的unit-address地址也经常在其对应结点的reg属性中给出。
2,dts的基本元素:compatible属性
在.dts文件的每个设备,都有一个compatible属性,compatible属性用户驱动和设备的绑定。compatible属性是一个字符串的列表,列表中的第一个字符串表征了结点代表的确切设备,形式为"<manufacturer>,<model>",其后的字符串表征可兼容的其他设备。可以说前面的是特指,后面的则涵盖更广的范围。
举例说明:FreescaleMPC8349 SoC含一个串口设备,它实现了国家半导体(NationalSemiconductor)的ns16550寄存器接口。则MPC8349串口设备的compatible属性为compatible= "fsl,mpc8349-uart","ns16550"。其中,fsl,mpc8349-uart指代了确切的设备,ns16550代表该设备与NationalSemiconductor的16550UART保持了寄存器兼容。
3,dts的其它部分:reg
可寻址的设备使用如下信息来在DeviceTree中编码地址信息:
-
reg
-
#address-cells
-
#size-cells
其中reg的组织形式为reg= <address1 length1 [address2 length2] [address3 length3] ...>,其中的每一组addresslength表明了设备使用的一个地址范围。address为1个或多个32位的整型(即cell),而length则为cell的列表或者为空(若#size-cells= 0)。address和length字段是可变长的,父结点的#address-cells和#size-cells分别决定了子结点的reg属性的address和length字段的长度。
4,dts的其它部分:ranges
ranges是地址转换表,其中的每个项目是一个子地址、父地址以及在子地址空间的大小的映射。映射表中的子地址、父地址分别采用子地址空间的#address-cells和父地址空间的#address-cells大小。举例如下:
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
对于本例而言,子地址空间的#address-cells为2,父地址空间的#address-cells值为1,因此00 0x101000000x10000的前2个cell为external-bus后片选0上偏移0,第3个cell表示external-bus后片选0上偏移0的地址空间被映射到CPU的0x10100000位置,第4个cell表示映射的大小为0x10000。ranges的后面2个项目的含义可以类推。
5,Dts的其它部分:中断控制器
DeviceTree中还可以中断连接信息,对于中断控制器而言,它提供如下属性:interrupt-controller–这个属性为空,中断控制器应该加上此属性表明自己的身份;#interrupt-cells–与#address-cells和#size-cells相似,它表明连接此中断控制器的设备的interrupts属性的cell大小。
在整个DeviceTree中,与中断相关的属性还包括:interrupt-parent–设备结点透过它来指定它所依附的中断控制器的phandle,当结点没有指定interrupt-parent时,则从父级结点继承。
interrupts–用到了中断的设备结点透过它指定中断号、触发方法等,具体这个属性含有多少个cell,由它依附的中断控制器结点的#interrupt-cells属性决定。而具体每个cell又是什么含义,一般由驱动的实现决定,而且也会在DeviceTree的binding文档中说明。值得注意的是,一个设备还可能用到多个中断号。除了中断以外,在ARMLinux中clock、GPIO、pinmux都可以透过.dts中的结点和属性进行描述。
6,Dts的其它部分:需注意的地方
dts除了以上规则外,也可以自己加一些自定义的属性和子节点,但是一定要符合以下的几个规则:
(1)新的设备属性一定要以厂家名字做前缀,这样就可以避免他们会和当前的标准属性存在命名冲突问题;
(2)新加的属性具体含义以及子节点必须加以文档描述,这样设备驱动开发者就知道怎么解释这些数据了。描述文档中必须特别说明compatible的value的意义,应该有什么属性,可以有哪个(些)子节点,以及这代表了什么设备。每个独立的compatible都应该由单独的解释。
(3)新添加的这些要发送到devicetree-discuss@lists.ozlabs.org邮件列表中进行review,并且检查是否会在将来引发其他的问题。
在一个树状结构的devicetree中,如何引用一个node呢?要想唯一指定一个node必须使用fullpath,例如/node-name-1/node-name-2/node-name-N。
属性(property)值标识了设备的特性,它的值(value)是多种多样的:
1、可能是空,也就是没有值的定义。例如上图中的64-bit,这个属性没有赋值。
2、可能是一个u32、u64的数值(值得一提的是cell这个术语,在DeviceTree表示32bit的信息单位)。例如#address-cells= <1> 。当然,可能是一个数组。例如<0x000000000x00000000 0x00000000 0x20000000>
3、可能是一个字符串。例如device_type= "memory" ,当然也可能是一个stringlist。例如"PowerPC,970"
在描述DeviceTree的结构时,那些可以动态探测到的设备是不需要描述的,例如USBdevice。不过对于SOC上的usbhost controller,它是无法动态识别的,需要在devicetree中描述。同样的道理,在computersystem中,PCIdevice可以被动态探测到,不需要在devicetree中描述,但是PCIbridge如果不能被探测,那么就需要描述之。