Linux設備樹學習(1)

1.什麼是設備樹?
描述設備樹的文件叫做DTS,這個DTS文件採用樹形結構描述板級設備,也就是開發板上的設備信息,比如CPU 數量、 內存基地址、 IIC 接口上接了哪些設備、 SPI 接口上接了哪些設備等等

==簡而言之的概括一下,linux和設備樹分開了,設備樹包含的是描述板級硬件信息的內容,設備樹的文件拓展名.dts 一個SOC可以有做出不同的板子,將板子的共同信息進行提提取得到通用文件,文件拓展名爲.dtsi ==

2.DTS、 DTB 和 DTC
DTS 是設備樹源碼文件, DTB 是將DTS 編譯以後得到的二進制文件。將.c 文件編譯爲.o 需要用到 gcc 編譯器,那麼將.dts 編譯爲.dtb 需要用到 DTC 工具! DTC 工具源碼在 Linux 內核的 scripts/dtc 目錄下

基於ARM架構的SOC有很多種,一種SOC又可以製作出很多板子,每個板子都有一個對應的DTS文件,那麼如何確定編譯編譯哪個DTS, arch/arm/boot/dts/Makefile,有如下內容:

381 dtb-$(CONFIG_SOC_IMX6UL) += \
382 imx6ul-14x14-ddr3-arm2.dtb \
383 imx6ul-14x14-ddr3-arm2-emmc.dtb \
......
400 dtb-$(CONFIG_SOC_IMX6ULL) += \
401 imx6ull-14x14-ddr3-arm2.dtb \
402 imx6ull-14x14-ddr3-arm2-adc.dtb \
403 imx6ull-14x14-ddr3-arm2-cs42888.dtb \
404 imx6ull-14x14-ddr3-arm2-ecspi.dtb \
405 imx6ull-14x14-ddr3-arm2-emmc.dtb \
406 imx6ull-14x14-ddr3-arm2-epdc.dtb \
407 imx6ull-14x14-ddr3-arm2-flexcan2.dtb \
408 imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \
409 imx6ull-14x14-ddr3-arm2-lcdif.dtb \
410 imx6ull-14x14-ddr3-arm2-ldo.dtb \
411 imx6ull-14x14-ddr3-arm2-qspi.dtb \
412 imx6ull-14x14-ddr3-arm2-qspi-all.dtb \
413 imx6ull-14x14-ddr3-arm2-tsc.dtb \
414 imx6ull-14x14-ddr3-arm2-uart2.dtb \
415 imx6ull-14x14-ddr3-arm2-usb.dtb \

當選中 I.MX6ULL 這個 SOC 以後(CONFIG_SOC_IMX6ULL=y),所有使用到I.MX6ULL 這個 SOC 的板子對應的.dts 文件都會被編譯爲.dtb。如果我們使用 I.MX6ULL 新做了一個板子,只需要新建一個此板子對應的.dts 文件,然後將對應的.dtb 文件名添加到 dtb-$(CONFIG_SOC_IMX6ULL)下,這樣在編譯設備樹的時候就會將對應的.dts 編譯爲二進制的.dtb文件。

DTB語法

1.dtsi頭文件

在.dts 設備樹文件中,可以通過“#include”來引用.h、 .dtsi 和.dts 文件
一般.dtsi 文件用於描述 SOC 的內部外設信息,比如 CPU 架構、主頻、外設寄存器地址範圍,比如 UART、 IIC 等等。比如 imx6ull.dtsi 就是描述 I.MX6ULL 這顆 SOC 內部外設情況信息的,內容如下:
imx6ull.dtsi文件如下

10 #include <dt-bindings/clock/imx6ul-clock.h>
11 #include <dt-bindings/gpio/gpio.h>
12 #include <dt-bindings/interrupt-controller/arm-gic.h>
13 #include "imx6ull-pinfunc.h"
14 #include "imx6ull-pinfunc-snvs.h"
15 #include "skeleton.dtsi"
16
17 / {
18		aliases {
19 			can0 = &flexcan1;
			......
48 				};
49
50		cpus {
51 			#address-cells = <1>;
52 			#size-cells = <0>;
53
54 			cpu0: cpu@0 {
55 			compatible = "arm,cortex-a7";
56 			device_type = "cpu";
			......
89		 };
90 };

第54~89行就是cpu0這個設備節點信息,這個節點信息描述了I.MX6ULL 這顆 SOC 所使用的 CPU 信息,比如架構是 cortex-A7,頻率支持 996MHz、 792MHz、528MHz、396MHz 和 198MHz 等等。

2.設備節點

設備樹採用屬性結構來描述包子上的設備信息的文件,每個設備都是一個節點,叫做設備節點
設備樹模板如下:

1 / {
2 		aliases {
3 		can0 = &flexcan1;
4 	};
5 
6 		cpus {
7 			#address-cells = <1>;
8 			#size-cells = <0>;
9
10 		cpu0: cpu@0 {
11 			compatible = "arm,cortex-a7";
12 			device_type = "cpu";
13 			reg = <0>;
14 			};
15 		};
16
17 		intc: interrupt-controller@00a01000 {
18 			compatible = "arm,cortex-a7-gic";
19 			#interrupt-cells = <3>;
20 			interrupt-controller;
21 			reg = <0x00a01000 0x1000>,
22 				  <0x00a02000 0x100>;
23		 };
24 }

第1行:根節點
第2、6、17行:aliases、cpus和intc是三個子節點,命名格式爲lable:node-name@unit-address,其中"node-name"是節點名字,“unit-address”一般表示設備的地址或寄存器首地址,如果某個節點沒有地址或者寄存器的話“unit-address”可以不要,label的目的是爲了方面訪問節點,可以通過&label直接訪問
第 10 行: cpu0 也是一個節點,只是 cpu0 是 cpus 的子節點。

每個節點都有不同屬性,不同的屬性又有不同的內容,屬性都是鍵值對,值可以爲空或任意的字節流。設備樹源碼中常用的幾種數據形式如下:
①、字符串
compatible = "arm,cortex-a7";
上述代碼設置 compatible 屬性的值爲字符串“arm,cortex-a7”。
②、 32 位無符號整數
reg = <0>;
上述代碼設置 reg 屬性的值爲 0, reg 的值也可以設置爲一組值,比如:
reg = <0 0x123456 100>;
③、字符串列表
屬性值也可以爲字符串列表,字符串和字符串之間採用“,”隔開,如下所示:
compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
上述代碼設置屬性 compatible 的值爲“fsl,imx6ull-gpmi-nand”和“fsl, imx6ul-gpmi-nand”。

3.標準屬性

除了用戶定義的屬性之外,有很多屬性是標準屬性,幾個常用的標準屬性如下:

** 1、compatible屬性**
compatible 屬性也叫做“兼容性”屬性,這是非常重要的一個屬性! compatible 屬性的值是一個字符串列表, compatible 屬性用於將設備和驅動綁定起來。字符串列表用於選擇設備所要使用的驅動程序, compatible 屬性的值格式如下所示:
"manufacturer,model"
其中 manufacturer 表示廠商, model 一般是模塊對應的驅動名字。比如 imx6ull-alientekemmc.dts 中 sound 節點是I.MX6U-ALPHA 開發板的音頻設備節點, I.MX6U-ALPHA 開發板上的音頻芯片採用的歐勝(WOLFSON)出品的 WM8960,sound 節點的 compatible 屬性值如下:
compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";
屬性值有兩個,分別爲“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl”表示廠商是飛思卡爾,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驅動模塊名字。 sound這個設備首先使用第一個兼容值在 Linux 內核裏面查找,看看能不能找到與之匹配的驅動文件,如果沒有找到的話就使用第二個兼容值查。
一般驅動程序文件都會有一個 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果設備節點的 compatible 屬性值和 OF 匹配表中的任何一個值相等,那麼就表示設備可以使用這個驅動。

2、model 屬性
model 屬性值也是一個字符串,一般 model 屬性描述設備模塊信息,比如名字什麼的,比如:
model = "wm8960-audio";

3、status 屬性
status 屬性看名字就知道是和設備狀態有關的, status 屬性值也是字符串,字符串是設備的狀態信息

描述
“okay” 表明設備是可操作的
“disabled” 表明設備當前是不可操作的,但是在未來可以變爲可操作的
“fail” 表明設備不可操作
“fail-sss” 含義和fail相同,後面的sss部分是檢測到的錯誤

4、#address-cells 和#size-cells 屬性
這兩個屬性的值都是無符號 32 位整形, #address-cells 和#size-cells 這兩個屬性可以用在任何擁有子節點的設備中,用於描述子節點的地址信息。
#address-cells :屬性值決定了子節點 reg 屬性中地址信息所佔用的字長(32 位)
#size-cells: 屬性值決定了子節點 reg 屬性中長度信息所佔的字長
reg = <address1 length1 address2 length2 address3 length3……>
每個“address length”組合表示一個地址範圍,其中 address 是起始地址, length 是地址長度, #address-cells 表明 address 這個數據所佔用的字長, #size-cells 表明 length 這個數據所佔用的字長

5、reg屬性
reg 屬性的值一般是(address, length)對。 reg 屬性一般用於描述設備地址空間資源信息,一般都是某個外設的寄存器地址範圍信息

6、ranges 屬性
ranges屬性值可以爲空或者按照(child-bus-address,parent-bus-address,length)格式編寫的數字矩陣, ranges 是一個地址映射/轉換表, ranges 屬性每個項目由子地址、父地址和地址空間長度這三部分組成:
child-bus-address:子總線地址空間的物理地址,由父節點的#address-cells 確定此物理地址所佔用的字長。
parent-bus-address: 父總線地址空間的物理地址,同樣由父節點的#address-cells 確定此物理地址所佔用的字長。
length: 子地址空間的長度,由父節點的#size-cells 確定此地址長度所佔用的字長。
如果 ranges 屬性值爲空值,說明子地址空間和父地址空間完全相同,不需要進行地址轉換

4.根節點 compatible 屬性

每個節點都有 compatible 屬性,根節點“/”也不例外,根節點compatible有兩個值:
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

設備節點的 compatible 屬性值是爲了匹配 Linux 內核中的驅動程序,那麼根節點中的 compatible屬性是爲了做什麼工作的? 通過根節點的 compatible 屬性可以知道我們所使用的設備,一般第一個值描述了所使用的硬件設備名字,比如這裏使用的是“imx6ull-14x14-evk”這個設備,第二個值描述了設備所使用的 SOC,比如這裏使用的是“imx6ull”這顆 SOC。 Linux 內核會通過根節點的 compoatible 屬性查看是否支持此設備,如果支持的話設備就會啓動 Linux 內核

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章