關於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