设备树学习笔记
设备树——dtb格式到struct device node结构体的转换
U-BOOT之寻找dtb位置:
设备树详解2:
驱动中device_node详解(将设备树属性存到变量中):
device_node转化为platform_device:
设备树框架
设备树用树状结构描述设备信息,它有以下几种特性
- 每个设备树文件都有一个根节点,每个设备都是一个节点。
- 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
- 每个设备的属性都用一组key-value对(键值对)来描述。
- 每个属性的描述用;结束
设备树语法
设备树是一颗树,树上的每个节点由节点和属性组成,属性是键值对
绑定
在设备树中添加新的compatible字符串,必须添加相应的BT Binding文档进行解释,
*位于Documentation\devicetree\bindings*
设备绑定文档主要内容包括:
1.关于模块最基本的描述;
2.必须属性的描述(required properties);
3.可选属性的描述(optional properites);
4.一个实例
例如:Documentation\devicetree\bindings\i2c\i2c-xiic.txt
设备树中添加的compatible字符串和添加的BT Binding文档怎么发生关联关系,是通过文件名和字符串的匹配吗?
根节点兼容性:
根节点的兼容属性,定义了整个系统(设备级别)的名称,
它的组织形式是<manufacture><model>,
Linux内核通过根节点“/”的兼容性即可判断启动的是什么设备,一般根节点兼容性包括两个或以上兼容性字符串。
例如:arch/arm/boot/dts$ vim exynos4210-origen.dts
compatible = “insignal,origen”, “samsung,exynos4210”, “samsung,exynos4”;
第一个兼容性字符串是板子名字(很特定)
第二个兼容性字符串是芯片名字(比较特定)
第二个兼容性字符串是芯片系列名字(比较通用)
设备节点兼容性
设备节点兼容性用于驱动和设备的绑定(匹配)。兼容属性是一个字符串列表。
它的组织形式是<manufacture><model>,
例如:
第一个兼容性字符串是节点代表的确切设备
第二个兼容性字符串是可兼容的其他设备
根节点和设备节点兼容性字符串列表都是从具体到抽象
节点名
理论个节点名只要是长度不超过31个字符的ASCII字符串即可,Linux内核还约定设备名应写成形如[@]的形式,其中name就是设备名,最长可以是31个字符长度。unit_address一般是设备地址,用来唯一标识一个节点
Linux中的设备树还包括几个特殊的节点,比如chosen,chosen节点不描述一个真实设备,而是用于firmware传递一些数据给OS,比如bootloader传递内核启动参数给内核
chosen{
bootargs = “console=ttySAC2,115200”;
stdout-path=&serial_2;
};
引用
当我们找一个节点的时候,我们必须书写完整的节点路径,这样当一个节点嵌套比较深的时候就不是很方便,所以,设备树允许我们用下面的形式为节点标注引用(起别名),借以省去冗长的路径。这样就可以实现类似函数调用的效果
KEY
在设备树中,键值对是描述属性的方式,比如,Linux驱动中可以通过设备节点中的”compatible”这个属性查找设备节点
inux设备树语法中定义了一些具有规范意义的属性,包括:compatible, address, interrupt等,这些信息能够在内核初始化找到节点的时候,自动解析生成相应的设备信息。此外,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这些属性一般不能被内核自动解析生成相应的设备信息,但是内核已经编写的相应的解析提取函数,常见的有 “mac_addr”,”gpio”,”clock”,”power”。”regulator” 等等。
compatible
设备节点中对应的节点信息已经被内核构造成struct platform_device。驱动可以通过相应的函数从中提取信息。主要有三种方法提取信息
1、compatible属性是用来查找节点
2、通过节点名查找指定节点
3、节点路径查找指定节点
看一个使用compatible提取属性的例子
#dts
gpio_demo: gpio_demo {
status = “okay”;
compatible = “firefly,rk3399-gpio”;
};
#驱动代码
static struct of_device_id firefly_match_table[] = {//该数组就是OF匹配表
{ .compatible = “firefly,rk3399-gpio”,}, //完全相同
{}, //最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个空。
};
address
#address-cells,用来描述子节点”reg”属性的地址表中用来描述首地址的cell的数量
#size-cells,用来描述子节点”reg”属性的地址表中用来描述地址长度的cell的数量。
pinctrl: pinctrl {
compatible = “rockchip,rk3399-pinctrl”;
#address-cells = <0x2>;
#size-cells = <0x2>;
gpio0: gpio0@ff720000 {
compatible = “rockchip,gpio-bank”;
reg = <0x0 0xff720000 0x0 0x100>;
//前两个数字表示一个地址0x0 0xff720000
//后两个数字表示一个地址跨度 0x100
};
…
}
interrupts