linux-4.8.5\arch\arm\boot\dts ARM设备树文件所在位置
include/linux目录下的of_xxx.h为设备树函数头文件所在位置
设备树是一种描述硬件的数据结构,采用设备树后,许多硬件的细节可以直接通过它传给Linux。
它是由命令的节点(Node)和属性(Property)组成,而节点本身可以包含子节点。
DTS文件
(Device Tree Source,dts)是以ASCII文本形式描述设备树内容。
DTB文件
dtb文件是二进制格式,编译工具为:Device Tree Compiler(DTC)。
DTSI文件
dtsi文件则类似C语言的头文件,其他设备包含了这个文件。
/{ /*根节点*/
node{ /*子节点*/
key=value;
child_node{ /*node的子节点*/
key=value;
...
}
....
}
.....
}
语法:<name>[@]
eg:serial@1111000
一般名字我们以设备类型命名,unit-address一般是设备地址
/{
ethernet@800000000{
...
}
}
节点路径:/ethernet@800000000
头文件:include/of.h
struct device_node {
const char *name; //节点名
const char *type; //设备类型
const char *full_name; //全路径节点名
struct device_node *parent; //父节点指针
struct device_node *child; //子节点指针
...
}
为了解决节点路径过长的问题,引入了节点别名的概念。
demo:demo@80000000{
....
}
在这里demo就是节点demo@80000000的别名
也可以这样: demo = &demo0
那么如何引用呢?
&demo{
...
}
或者
{
property=<&demo>;
}
在第二个例子中,property应用了demo节点的内容,一般情况,引用其他节点的目的是使用其节点的部分属性内容。
先编写好节点,仅仅描述部分属性值;使用者后加一部分属性值。在同级路径下,节点名相同的“两个”节点实际是一个节点。
前提:节点名相同
合并:取一个和原属性不同的名字;
替换:取一个和原属性一样的名字;
chosen{
bootargs = "root=/dev/nfs........."
}
chosen节点描述的不是一个真实的设备,而是通过firmware传递一些参数给内核,例如传递bootargs给内核启动参数。
/{
#address-cells = <1>;
#size-cells = <0>;
son-node {
compatible = "arm,cortex-a9";
reg = <addr1 len1[addr2 len2]>;
};
};
#address-cells:描述子节点reg属性值的地址表中的首地址cell数量
#size-cells:描述子节点reg属性值的地址表中地址长度cell数量
在上面的示例中,子节点cpu0中有属性,地址表这些成员,下面一个个详细分析。
驱动自定义属性
有些属性很难通用,需要驱动自己定义好,可以通过内核的属性提取解析函数得到属性。
compatible属性
/{
node{
compatible="厂商名,名称";
};
.....
};
在描述一个设备内存地址的时候,经常一个cell(32bits)描述地址,紧接着一个cell(32bits)描述地址长度。
reg = <0x101f3000 0x1000
0x101f4000 0x2000>
#address-cells:描述子节点reg属性值的地址表中首地址cell数量
#size-cells:描述子节点reg属性值的地址表中地址长度cell数量
有时reg中会把size省略掉。
另外,譬如i2c设备,有一个寻址地址,没有内存地址那样的地址长度和范围,一般使用1个cell(32bits)描述该地址,而没有描述地址长度的cell。
地址转换范围Ranges
有些设备是有片选的,就需要描述片选及片选的偏移量,在说明地址时,还需要说明地址映射范围。
ranges = <0 0 0x10100000 0x10000 //片选 片选偏移量 地址 地址长度
1 0 0x10160000 0x10000
2 0 0x30000000 0x100000
>
reg = <0 0 0x1000>;片选0 偏移0 被映射到CPU地址空间的0x1010000~0x10110000中,地址长度为0x10000