Linux设备树
设备树
组成
DTS有一系列node(节点)和property(属性),节点可以包含更多子节点,DTS主要描述设备信息
- CPU的数量及类别
- 内存基地址和size
- 总线和桥
- 外设连接
- 中断
- GPIO
- CLOCK
其有以下几种特性:
- 每个设备树文件都有一个根节点,每个设备都是一个节点。
- 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
- 每个设备的属性都用一组key-value对(键值对)来描述。
- 每个属性的描述用
;
结束
/{ //根节点
node1{ //node1是节点名,是/的子节点
key=value; //node1的属性
...
node2{ //node2是node1的子节点
key=value; //node2的属性
...
}
} //node1的描述到此为止
node3{
key=value;
...
}
}
节点名
每个节点必须有节点名,格式< name>[@< unit-address>]
- < name>:为最长31个字符的ascii字符串,一般用其代表的设备类型命名,
- unit-address: 描述设备的地址,一般情况下,其提供访问设备的基地址,节点的reg property也用此参数,见下文。
引用
和c语言一样支持引用,如果按照树结构书写嵌套比较深,会十分不方便,可以&节点名
来省去路径,相同节点不同属性信息会被合并,相同节点相同的属性会被重写
&cpu{
cpu0-supply = <&buck2_reg>;
};
KEY
键值对是描述设备属性的方式,eg:Linux驱动中可以通过设备节点中的“compatible”这个属性查找设备节点。
其包括包括:compatible, address, interrupt等,这些信息能够在内核初始化找到节点的时候,自动解析生成相应的设备信息。此外,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这些属性一般不能被内核自动解析生成相应的设备信息,但是内核已经编写的相应的解析提取函数(of_类函数),常见的有 “mac_addr”,“gpio”,“clock”,“power”。“regulator” 等等。
- compatible
设备树中每个节点都需要有compatible属性,compatible属性决定每一个设备驱动绑定哪一个设备,设备驱动可以利用这个相应函数读取compatible信息,利用该属性来查找节点,此外也可以通过节点名、节点路径查找指定节点。compatible是一个字符串序列,第一个字符串指定精确设备,第二字符串指定兼容设备。eg:compatible = “fsl,mpc8349-uart”, “ns16550”
第一个字符串指定精确设备,第二个指定国家半导体16550 uart兼容设备。
需要注意:驱动中用于匹配的结构使用的compatible和设备树中一模一样,否则就可能无法匹配,这里另外的一点是struct of_device_id数组的最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个空。
static const struct of_device_id fls[] = {
{ .compatible = "fsl,mpc8349-uart", "ns16550"}
{ /*为空*/}
};
- address
(几乎)所有的设备都需要与CPU的IO口相连,所以其IO端口信息就需要在设备节点节点中说明。常用的属性有
- #address-cells,用来描述子节点“reg”属性的地址表中用来描述首地址的cell的数量,
- #size-cells,用来描述子节点“reg”属性的地址表中用来描述地址长度的cell的数量。
这两个属性,子节点中的“reg”就可以描述一块连续的地址区域。eg:父节点中指定了
#address-cells = <2>;
#size-cells = <1>;
reg = <0 0x1046C 0x4> //reg中的前两个数表示一个地址,即0和0x1045C,最后一个数的表示地址跨度,即是0x4
- interrupts
在设备中经常用到中断,设备树中中断常用属性有
- interrupt-controller 一个空属性用来声明这个node接收中断信号,即这个node是一个中断控制器
- #interrupt-cells,是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符,用来描述子节点中“interrupts”属性使用了父节点中的interrupts属性的具体的哪个值。一般,如果父节点的该属性的值是3,则子节点的interrupts一个cell的三个32bits整数值分别为:<中断域 中断 触发方式>,如果父节点的该属性是2,则是<中断 触发方式>
- interrupt-parent,标识此设备节点属于哪一个中断控制器,如果没有设置这个属性,会自动依附父节点的
- interrupts,一个中断标识符列表,表示每一个中断输出信号
在内核中中断分层概念趋于流行,使内核中原本的中断源直接到中断号的方式已经很难继续发展了,所以引入了irq domain (中断域),其他的power domain,clock domain等等也是类似。系统中所有的interrupt controller会形成树状结构,对于每个interrupt controller都可以连接若干个外设的中断请求(interrupt source,中断源),interrupt controller会对连接其上的interrupt source(根据其在Interrupt controller中物理特性)进行编号(HW interrupt ID)。引入中断域后,其编号就只限定在本域内,有利于编程
中断源--interrupt parent-->GPIO--interrupt parent-->GIC1--interrupt parent-->GIC2--...-->CPU
[email protected]101f3000 {
compatible = "arm,pl061";
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
interrupts = < 3 0 >;
};
intc: [email protected]10140000 { // 中断控制器
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>; // 中断说明符有2 cells,此例中cell 1表示中断号,cell 2 表示触发方式
};
The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
- ==补充== 中断划分
中断按来源分类:
- 外部中断
- 内部中断
按可屏蔽:
- 可屏蔽中断
- 不可屏蔽中断
按入口地址:
- 向量中断(硬件提供入口地址)
- 非向量中断(软件提供入口地址)
ARM平台支持GIC中断控制器:
-
GIC所支持的中断类型:
- 1.PPI:私有中断,中断必须绑定一个固定CPU核,当处理该中断时,必须由绑定的CPU核处理
- 2.SPI:共享中断,中断的处理可被任意的CPU核处理
- 3.SWI:软中断,用于处理核间通信和调度。
内核 –|- cpu —– GIC———中断控制器 ……..—|—外设
————————————————-
soc内部
- gpio
gpio也是最常见的IO口,常用的属性有
- “gpio-controller”,用来说明该节点描述的是一个gpio控制器
- “#gpio-cells”,用来描述gpio使用节点的属性一个cell的内容,即 `属性 = <&引用GPIO节点别名 GPIO标号 工作模式>
[email protected]4{
compatible = "xj4421, key";
gpx2_7 = <&gpx2 7 0>;
}
下一篇: 设备树 phy节点 使用说明