DTS文件,即Device Tree Source,是某些芯片(在Openwrt的target/linux/中,至少ramips,lantiq和BRCM有此文件)用於描述硬件設備資源的文件。此文件是驅動研發人員用來配置這些芯片驅動的必要文件。 要想弄清楚DTS文件中的含義,筆者認為至少需要如下資料:芯片Datasheet,芯片開發手冊,單板硬件連接圖,單板GPIO配置清單,單板實物(有上蓋) 。這里,筆者以配置一款采用MT7620A(主芯片)+MT7610E(5G wifi芯片)架構的路由器為例,描述一下對於DTS文件的解讀。
手上資源: “MT7620_Datasheet”,“MT7620_ProgrammingGuide”,“MT7620_EEPROM Content v1_7.pdf”,單板硬件連接圖,以及單板的GPIO配置清單,其中主要的幾條內容如下:
GPIO#39 |
WPS_LED/DRAM_TYPE |
GPIO#36 |
POWER ON RESET |
GPIO#13 |
Software Reset/ Factory/Default/WPS PBC |
GPIO#72 |
DRAM_FROM_EE/For non scan mode/2.4G-Wlan_LED |
GPIO#43 |
LINK3_LED;對應面板上的LAN1口燈 |
GPIO#42 |
LINK2_LED;對應面板上的LAN2口燈 |
GPIO#41 |
LINK1_LED;對應面板上的LAN3口燈 |
GPIO#40 |
LINK0_LED;對應面板上的LAN4口燈 |
通過分析硬件設計圖,可以知道:port4是作為WAN口, 7610E和主CPU是通過PCIE接口連接
此外,linux/Documentation/devicetree目錄中有一些說明文件,可以用於參考
OK,一切就緒;
下面解讀一下DTS文件:MT7620a_MT7610e.dts (紅色是我更改的部分;藍色部分是注釋)
/dts-v1/;
/include/ "mt7620a.dtsi"
/*引用此文件,但同名定義以此文件為主*/
/ {
/*根節點*/
compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc";
/*這些字符串列表被操作系統用來選擇用哪一個driver來驅動該設備*/
model = "Ralink MT7620A evaluation board";
/*此字符串會顯示在 單板status->system->model 頁面中*/
palmbus@10000000 {
/*寄存器映射位置,即0x1000,0000,見《MT7620_ProgrammingGuide》的1.3(P13)的 SYSCTL*/
sysc@0 {
/*相對於palmbus的偏移,即0x1000,0000,見《MT7620_ProgrammingGuide》的1.3(P13)的 SYSCTL*/
ralink,gpiomux = "i2c", "jtag";
/*表示i2c和jtag,也可以用於gpio控制;具體到這里,是由於按鍵要用到i2c*/
ralink,uartmux = "gpio";
/*表示gpio,也可以用於UART輸出*/
ralink,wdtmux = <1>;
};
/*MT7620A將GPIO分為4組,如下是針對各組的定義*/
gpio0: gpio@600 {
/*相對於palmbus的偏移,即0x1000,0600,見《MT7620_ProgrammingGuide》的1.3(P13)的 PIO*/
status = "okay";
/*狀態為okay,表示此GPIO組可用*/
};
gpio1: gpio@638 {
status = "okay";
};
gpio2: gpio@660 {
status = "okay";
};
gpio3: gpio@688 {
status = "okay";
};
spi@b00 {
/*相對於palmbus的偏移,即0x1000,0b00,見《MT7620_ProgrammingGuide》的1.3(P13)的 SPI*/
status = "okay";
m25p80@0 {
/*相對於SPI的偏移*/
#address-cells = <1>;
#size-cells = <1>;
compatible = "en25q64";
reg = <0 0>;
/*mtd中的偏移量和大小*/
linux,modalias = "m25p80", "en25q64";
spi-max-frequency = <
10000000>;
/*
Maximum SPI clocking speed of device in Hz;原來值是1000000,比驅動要求的值小;會導致Flash加載失敗
*/
/*如下分區只針對 8M 大小;當bootloader中沒有設定分區定義時,內核就據此來划分Flash分區了*/
partition@0 {
label = "u-boot";
/*此分區的標識,會體現在 /proc/mtd文件中*/
reg = <0x0 0x30000>;
/*此分區的偏移量和大小*/
read-only;
/*表示此分區只讀*/
};
partition@30000 {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};
factory: partition@40000 {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
};
kernel: partition@50000 {
label = "kernel";
reg = <0x50000 0x190000>;
};
rootfs: partition@1E0000 {
label = "rootfs";
reg = <0x1E0000 0x620000>;
};
partition{
label = "firmware";
reg = <0x50000 0x7b0000>; /*這是kernel+rootfs的合計*/
};
};
};
};
pinctrl { /*描述pin控制邏輯*/
state_default: pinctrl0 {
/*ralink,group和ralink,function,用於mt7620.c中的識別處理;
定義PIN節點:"ephy", "i2c", "uartf", "wled","spi refclk",也可以用於GPIO控制*/
gpio {
ralink,group = "ephy", "i2c", "uartf", "wled", "spi refclk";
ralink,function = "gpio";
};
};
};
ethernet@10100000 {
status = "okay";
pinctrl-names = "default";
mtd-mac-address = <&factory 0x28>;
/*在分區"factory"的偏移位置0x28,對應LAN側的MAC地址*/
ralink,port-map = "llllw";
/*ralink,port-map,對應 mt7530.c中的mt7530_find_mapping 識別處理;這里表示port0到port3是lan;port4是wan*/
};
sdhci@10130000 {
status = "okay";
};
pcie@10140000 {
status = "okay";
};
gpio-keys-polled {
compatible = "gpio-keys-polled";
/*用於在gpio-button-hotplug中的識別*/
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;
/*用於在gpio-button-hotplug中的輪訓間隔設置;單位是ms*/
reset {
/*特別定義reset按鍵*/
label = "reset";
gpios = <&gpio0 13 1>;
/*reset按鍵的GPIO編號*/
linux,code = <0x198>; /*當按下reset按鍵后,向內核發出的code;
這些code,用於input_event上報的code代碼,具體含義見input.h:比如這里的0x198就對應KEY_RESTART;而在gpio-button-hotplug.c中,有BH_MAP(KEY_RESTART,
"reset"),
*/
};
};
wmac@10180000 {
ralink,mtd-eeprom = <&factory 0>;
/*wifi的K值的讀取起始位置*/
mtd-mac-address = <&factory 0x4>;
/*wifi的MAC地址,讀取起始位置*/
};
/*如下定義led燈控*/
gpio-leds {
compatible = "gpio-leds";
wan {
label = "w856n:blue:wan";
/*led燈的標識,會體現在/sys/class/leds目錄中*/
gpios = <&gpio2 4 1>;
/*led燈對應的gpio編號;
表示是gpio2組中的第4個GPIO;這里的wan對應路由器面板外殼上的絲印
*/
};
lan4 {
label = "w856n:blue:lan4";
gpios = <&gpio2 0 1>;
};
lan3 {
label = "w856n:blue:lan3";
gpios = <&gpio2 1 1>;
};
lan2 {
label = "w856n:blue:lan2";
gpios = <&gpio2 2 1>;
};
lan1 {
label = "w856n:blue:lan1";
gpios = <&gpio2 3 1>;
};
wlan {
label = "w856n:blue:wlan";
gpios = <&gpio3 0 1>;
};
wps {
label = "w856n:blue:wps";
gpios = <&gpio1 15 1>;
};
};
};