设备树学习总结:
1、https://blog.csdn.net/qq_41782149/article/details/101149210
2、https://blog.csdn.net/Klaus_Wei/article/details/42915545
3、https://blog.csdn.net/stoic163/article/details/56489195
4、https://www.cnblogs.com/liuwanpeng/p/7421661.html
5、设备树:中断
https://www.cnblogs.com/god-of-death/p/10270667.html
6、设备树:中断
https://blog.csdn.net/qq_17270067/article/details/105056348
一、标签 :节点(名称@设备地址)
标签(label)
可以为节点创建标签,别的地方引用时可以用标签。标签为可选项。
节点(node)
每个节点必须有一个 “<名称>[@<设备地址>]” /"<name>[@<unit-address>]"形式的名字, [ ]为可选项,unit-address一般是内存地址。
名称(name):一个字节大小
就是一个不超过31位的简单 ascii 字符串,节点的命名应该根据它所体现的是什么样的设备。比如一个 3 com 以太网适配器的节点应该命名为 ethernet,而不应该是 3com509。
设备地址(unit-address)
挂到内存空间的设备,unit-address一般是内存地址。
用来访问该设备的主地址,并且该地址也在节点的reg属性中列出,同级节点命名必须是唯一的,但只要地址不同,多个节点也可以使用一样的通用名称,当然设备地址也是可选的,可以有也可以没有
二、自定义属性的设置与获取?
参考:https://blog.csdn.net/stoic163/article/details/56489195
三、常见属性——compatible(兼容性)属性:<制造商>,<型号>
指定了系统的名称,是一个字符串的列表,实际在代码中可以用于进行匹配,当前你选择的是哪个机器,它包含了一个"<制造商>,<型号>"形式的字符串。重要的是要指定一个确切的设备 ,并且包括制造商的名字,以避免命名空间冲突。不要使用带通配符的compatible值,比如"fsl,mpc83xx-uart" 或类似情况
如果一个节点是设备节点,那么它一定要有compatible(兼容性),因为这将作为驱动和设备(设备节点)的匹配依据。
compatible(兼容性)的值可以有不止一个字符串以满足不同的需求,详见下一节。
而根节点的compatible也是非常重要的,因为系统启动后,将根据根节点的compatible来判断cpu信息,并由此进行初始化
属性设置的套路:
- 一般来说,每一种设备的节点属性设置都会有一些套路,比如可以设置哪些属性?属性值怎么设置?那怎么知道这些套路呢,有两种思路 :
- 第一种是抄类似的dts,比如我们自己项目的平台是4412,那么就可以抄exynos4412-tiny4412.dts、exynos4412-smdk4412.dts这类相近的dts
- 第二种是查询内核中的文档,比如
Documentation/devicetree/bindings/i2c/i2c-imx.txt
就描述了imx平台的i2c属性设置方法;Documentation/devicetree/bindings/fb
就描述了lcd、lvds这类属性设置方法
四、 常见属性——地址编码 属性:#address-cells和#size-cells
父节点的address-cells和size-cells决定子节点的reg的address和lenth字段的长度,cell的单位为32bit
#address-cells=<1> // 子节点reg的address为几个32bit的整型数据
#size-cells=<1> // 长度为几个32bit整型数据,如果为0,则没有lenth字段
举例:
node{
reg = <address1 lenth1 [address2 lenth2] [address3 lenth3]...>;
}
ps7_axi_interconnect_0: amba@0 {
#address-cells = <1>; // 下一级节点reg的address字段长度为1个32bit,下一级节点为ps7-i2c@e0005000
#size-cells = <1>; // 下一级节点reg的len字段长度为1个32bit
...
ps7_i2c_1: ps7-i2c@e0005000 {
clock-frequency = <400000>;
clocks = <&clkc 39>;
compatible = "cdns,i2c-r1p10";
interrupt-parent = <&ps7_scugic_0>;
interrupts = <0 48 4>;
reg = <0xe0005000 0x1000>; // 地址为0xe0005000,长度为0x1000
xlnx,has-interrupt = <0x0>;
#address-cells = <1>; // 下一级eeprom的reg属性
#size-cells = <0>; // 没有len字段
eeprom@52 {
compatible = "at,24c512";
reg = <0x52>; // 地址为0x52,没有长度字段
};
} ;
...
}
五、常见属性——reg属性,实例见以上
reg的组织形式为 reg = <address1 lenth1 [address2 lenth2] [address3 lenth3]...>;
其中的每一组address1 lenth1表明了设备使用的一个地址范围
六、常见属性——GPIO、时钟、pinmux连接
1. GPIO属性的设置与获取
- dts的GPIO描述
gpio-controller表示“我是GPIO控制器”;
#gpio-cells,设置GPIO属性的大小
举例1:
ps7_gpio_0: ps7-gpio@e000a000 {
#gpio-cells = <2>; // 2个cell,一般第一个表示用哪个GPIO,第二个数0表示高电平有效、1表示低电平有效
clocks = <&clkc 42>;
compatible = "xlnx,zynq-gpio-1.0";
emio-gpio-width = <64>;
gpio-controller ;
gpio-mask-high = <0x0>;
gpio-mask-low = <0x5600>;
interrupt-parent = <&ps7_scugic_0>;
interrupts = <0 20 4>;
reg = <0xe000a000 0x1000>;
} ;
ps7_ethernet_0: ps7-ethernet@e000b000 { ... enet-reset = <&ps7_gpio_0 11 0>;
...
} ;
举例2:
/*imx6dl.dtsi中gpio1控制器的定义节点*/
gpio1: gpio@0209c000 {
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
reg = <0x0209c000 0x4000>;
interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
<0 67 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
/*imx6qdl-sabreauto.dtsi中某个设备节点*/
max7310_reset: max7310-reset {
compatible = "gpio-reset";
reset-gpios = <&gpio1 15 1>;
reset-delay-us = <1>;
#reset-cells = <0>;
};
1、一般来说,我们把gpio属性的名字起为 xxx-gpios
(xxx我们可以随便起),这样驱动才能通过特定API从识别该属性,并转换成具体的gpio号
2、该设备节点中设置了reset-gpios = <&gpio1 15 1>;
这格式是什么意思呢?&gpio1 15
引用了gpio1节点,故此处含义为gpio1_15这个引脚;最后一个参数1则代表低电平有效,0则为高电平有效。至于gpio1_15具体对应哪个引脚,在imx6的手册上都有详细描述
3、其实最后一个参数(高低电平有效)不是必须的,因为gpio1节点中设置了#gpio-cells = <2>;
,所以才有两个参数;某些soc的gpio节点中会设置为#gpio-cells = <1>;
,那么可以不写最后一个参数
参考:
https://www.cnblogs.com/liuwanpeng/p/7421661.html
https://blog.csdn.net/stoic163/article/details/56489195
七、常见属性——中断属性:interrupts 和 interrupts
描述中断连接需要四个属性:
中断控制器节点属性:这类节点可能是中断父节点
interrupt-controller -一个空的属性定义该节点作为一个接收中断信号的设备
#interrupt-cells -这是一个中断控制器节点的属性。它声明了该中断控制器的中断指示符中cell的个数(类似于#address-cells 和#size-cells )
中断产生设备节点属性:
interrupt-parent -这是一个设备节点的属性,包含一个指向该设备连接的中断控制器的phandle(指向或者可以引用&)那些没有interrupt-parent 的节点则从它们的父节点中继承该属性。
interrupts - 一个设备节点属性,包含-一个中断指示符的列表,对应于该设备上的每个中断输出信号
1、某个设备要使用中断, 需要在设备树中如何描述中断?
想使用中断,节点中至少有有2个属性:
interrupt-parent // 中断产生设备节点属性:这个中断要接到哪一个设备去? 即父中断控制器是谁
interrupts // 中断产生设备节点属性:表示要使用哪一个中断, 中断的触发类型等等。
父中断控制器有两种指定方法:
1)只有一个中断父设备
interrupt-parent = <&父设备标号>;
interrupts = <... ...>, <... ...>;
ethernet@20000000 {
compatible = "davicom,dm9000";
reg = <0x20000000 0x2 0x20000004 0x2>;
interrupt-parent = <&gpf>; //父中断控制器为gpf
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
local-mac-address = [00 00 de ad be ef];
davicom,no-eeprom;
};
2)有多个中断父设备
interrupts-extended = <&父设备标号 .....>, <... ... ...>;
buttons {
compatible = "jz2440_button";
eint-pins = <&gpf 0 0>, <&gpf 2 0>, <&gpg 3 0>, <&gpg 11 0>;
interrupts-extended = <&intc 0 0 0 3>,
<&intc 0 0 2 3>,
<&gpg 3 3>,
<&gpg 11 3>;
};
假设某设备节点需要一个gpio中断
/*先确定中断所在的组*/
interrupt-parent = <&gpio6>;
/*表示中断,GPIO6中的第8个IO,2为中断触发条件,下降沿触发*/
interrupts = <8 2>;
interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
可以参考GIC的规范,第一个u32表示中断类型,第二个是中断号,第三个是中断触发条件
而在驱动中使用 中断号 =irq_of_parse_and_map(node, index)
函数返回值来得到中断号
举例:
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
serial@101f0000 {
compatible = "arm,pl011";
reg = <0x10170000,0x1000>;
interrupts = <1 0>;
};
intc:interrupt-controller@10140000{
compatible = "arm,pl190";
reg = <0x10140000,0x1000>;
interrupt-controller;
#interrupt-cells = <2>;
};
}
2、在设备树中,如何描述在父中断控制器? (上述的interrupts属性用多少个u32来表示?由它的父中断控制器来描述)
在父中断控制器中, 至少有2个属性:
interrupt-controller; // 表示自己是一个中断控制器
#interrupt-cells // 表示自己的子设备里应该用几个U32的数据来描述中断
例如:
gpf {
gpio-controller;
#gpio-cells = <0x2>;
interrupt-controller;
#interrupt-cells = <0x2>; //使用两个u32数据来描述中断
phandle = <0x6>;
};
3、如何找到一个子中断节点的父中断控制器
一般在描述子中断节点中都会有一个属性interrupt-parent,由此属性描述。
如果子中断节点中没有此属性,需要查看此节点的父节点,一级一级往上直到父节点中出现interrupt-parent
4、interrupts属性的具体含义
参考:https://blog.csdn.net/qq_17270067/article/details/105056348
5、驱动中使用这些中断
参考:https://blog.csdn.net/qq_17270067/article/details/105056348
6、GPIO中断使用方法
参考:https://blog.csdn.net/qq_17270067/article/details/105056348