关于Linux 设备树
0. DTS、DTC和DTB
① DTS,位于arch/arm/boot/dts/
;
② DTC,将.dts
编译为.dtb
的工具,源码位于scripts/dtc/
;
③ DTB (Device Tree Big large object),.dts
的被DTC编译后得二进制文件。
1. 兼容属性
/* 具体 --> 抽象 */
compatible = "manufacturer, model", "manufacturer2,model2"... ;
- 用于板与
DT_MACHINE_START
或者 设备与驱动 的匹配。
2. 设备节点命名
/*设备类型@内存基地址或总线地址
| | */
<name>[@<unit_addr>] {
...
};
- "< >"表示必须有; "[ ]"表示可选;
3. label命名
<设备类型><index> :
-
其他节点通过
&label
来访问该节点,进行引用或者修改属性的值。 -
"< >"表示必须有;
4. 地址编码
reg = <addr_1 len_1 addr_2 len_2 ...>;
/* | |_______________
| |
父节点#address-cells=<n> 和 #size-cells=<n> 决定其单元数 */
子 —> 父地址转换表:ranges = <child_addr parent_addr map_len
child_addr1 parent_addr1 map_len1
... >;
5. 中断连接
① 中断控制器:
interrupt-controller; /* 表明身份 */
#interrupt-cells = <n>; /* 指示连接此中断控制器之设备的中断属性cells个数 */
② 开启中断的设备:
interrupt-parent = <&int_ctrl_label>; /* 指示所依附的中断控制器 */
interrupt = < x ... >, <y ... >; /* 中断控制器#interrupt-cells决定cell个数,逗号隔开多个中断号 */
interrupt-name = "x_name","y_name", ... ; /* 给特定中断号起名 */
- 用index获取中断号:
int platform_get_irq(struct platform_device *dev, unsigned int num)
; - 用中断名获得中断号:
int platform_get_irq_byname(struct platform_device *dev, const char *name)
;
6. GPIO、时钟、pinmux的连接
6.1 GPIO
① GPIO控制器:
gpio-controller; /* 表明身份 */
#gpio-cells = <n>; /* 连接此GPIO控制器之设备的xxx-gpios属性cells个数 */
② 使用GPIO的设备:
xxx-gpios = <&ctrl_label n ...>; /* 所依附的gpio控制器之#gpio-cells决定cells个数 */
- 使用
xxx-gpios
获得gpio口:static inline int of_get_named_gpio(struct device_node *np, const char *propname, int index)
; - 设备只有一个gpio属性时,不关心GPIO名字获得gpio口:
static inline int of_get_gpio(struct device_node *np, int index)
;
6.2 时钟
① 外部时钟
clock-frequency = <n>; /* 表明外部时钟之频率 */
clock-output-names = "xxx"; /* 外部时钟导出名字到设备驱动 */
#clock-cells = <0>; /* 规定引用此节点之设备的clocks属性的cells个数 */
② 时钟控制器
clocks: clock-controller@n {
...
clock-names = "xxx", "yyy"; /* 定义属性clocks中时钟之名 */
clocks = <&xxx>, <&yyy>; /* 引用外部时钟节点定义属性clocks */
#clock-cells = <n>; /* 规定引用此节点之设备的clocks属性的cells个数 */
...
};
③ 使用时钟的设备
/* 长度为时钟控制器#clock-cells
+--^--+ */
clocks = <&clocks n1 ...>, <&clocks n2 ...>, ...; /* 引用时钟控制器节点来定义属性clocks */
clock-names = "iii", "jjj", ...; /* 定义属性clocks中时钟之名 */
- 用
clock-name
定义的名字获得时钟:struct clk *clk_get(struct device *dev, const char *con_id)
;
6.3 pinmux
① pinmux引脚群
xxx: yyy {
vendor_name,pins = "pin_name1", "pin_name2", ...;
vendor_name,pin-function = <n>; /* 引脚功能设置 */
vendor_name,pin-pud = <n>; /* 引脚支路电阻上下拉或不接设置 */
vendor_name,pin-drv = <n>; /* 引脚电流驱动能力等级设置 */
};
② 设备使用引脚群
pinctrl-names = "default";
pinctrl-0 = <&xxx>; /* 引用引脚群xxx */
参考文献
[1] 宋宝华. Linux设备驱动开发详解[M].北京:机械工业出版社,2015