[1] 什么是设备树?
用于描述设备和总线层次关系的脚本。
[2] 设备树如何组成?
/ { // 根, 描述CPU总线和主板, 名字一定为'/'
name = <value ...> // 属性, name为名字,<value ...>为属性值
name = "string", ... // 属性, name为名字, "string", ...为属性值
node { // 节点, 描述设备或总线, 名字可以使用全名
name = <value ...> // 属性
name = "string", ... // 属性
...
node {
...
};
};
...
};
1. 名字
描述设备类型或属性名,语法如下:
基本名@扩展名
(1) 基本名
由'a'-'z'、'0'-'9'、','、'.'、'+'、'_'、'#'、'?'和'-'字符组成
最大字符数为31
是设备类型
(2) 扩展名
如果某类设备存在多个设备,可以增加扩展名,以避免名字重复,
扩展名只能用于设备结点名, 一般为设备在总线上的地址
内核在匹配驱动时,不会使用扩展名
2. 属性值
<value ...> 一个或多个32bit整数
"string", ... 一个或多个字符串
[3] 如何实现设备树?(详细语法)
1. 根和内存
/ {
model = "主板名";
compatible = "SOC名"; // 必选,用于匹配BSP中的支持的SOC列表,以判断内核是否支持该主板
// platform总线
#address-cells = <A>; // 必选, 地址位数,单位(cell)为32bit, A = 地址位数 / 32
#size-cells = <S>; // 必选, 大小位数,单位(cell)为32bit, S = 大小位数 / 32
// 内存
memory {
device_type = "memory"; // device_type值一定为"memory"
reg = <address size ... ...> // 必选, 描述地址范围
};
};
<address size>
(1) 地址和大小成对出现, 描述内存范围, 地址的位数决定于A,大小位数决定于S
(2) 地址或大小的位数超过32位时,需要用多个32bit数表示,采用大端模式
例: A = 2 S = 2 时
reg = <0x00000000 0x400000000 0x00000000 0x400000000>
表示内存范围为0x400000000 - 0x800000000
2. chosen
/ {
...
chosen {
bootargs = "内核启动参数"; // 必选
linux,stdout-path= "console" // 可选
};
...
};
3. 设备
标号: 设备类型@地址 { // 设备名字, 基本名通常为设备类型, 扩展名通常为设备在总线上的地址
name = "设备(总线)类型"; // 可选,name属性值必须和基本名一致
device_type = "芯片名"; // 可选,设备采用芯片名
compatible = "兼容芯片1", "兼容产品2"; // 必选, 用于匹配驱动
// io内存(寄存器)地址
#address-cells = <A>; // 可选, 同"根和内存"相同名称属性
#size-cells = <S>; // 可选, 同"根和内存"相同名称属性
reg = <地址(端口号) 大小 ... ...>; // 可选, 同"根和内存"相同名称属性
// 中断(详细参考Documentation/devicetree/bindings/interrupt-controller/interrupts.txt内核文档)
// 只有一个中断父设备(必选)
interrupt-parent = <&父设备标号>;
interrupts = <irqno trigger>, <... ...>;
// 有多个中断父设备(必选)
interrupts-extended = <&父设备标号 irqno trigger>, <... ... ...>;
};
(1) 设备和驱动匹配
1. 匹配设备树上的设备
驱动 设备树 条件
compatible compatible 必须
type device_type 驱动存在type属性
name name 驱动存在name
2. 匹配代码添加的设备
驱动 设备 条件
name name 必须
(2) 设备(非中断控制器)中断
interrupt-parent
interrupts
和
interrupts-extended
只允许出现一次
1. irqno
父设备(中断控制器)中的中断编号
2. trigger
促发条件,目前只用到32bit中的[0:3]bit
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
4. 中断控制器
标号: 设备类型@地址 {
...
interrupt-controller; // 必选
interrupt-parent = <&父设备标号>; // 必选
#interrupt-cells = <1>; // 必选
interrupts = <irqno>, <...>; // 必选
或
#interrupt-cells = <2>; // 必选
interrupts = <irqno trigger>, <... ...>; // 必选
...
};