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 页面中*/
[email protected] { /*寄存器映射位置,即0x1000,0000,见《MT7620_ProgrammingGuide》的1.3(P13)的 SYSCTL*/
[email protected] {/*相对于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: [email protected] {/*相对于palmbus的偏移,即0x1000,0600,见《MT7620_ProgrammingGuide》的1.3(P13)的 PIO*/
status = "okay"; /*状态为okay,表示此GPIO组可用*/
};
gpio1: [email protected] {
status = "okay";
};
gpio2: [email protected] {
status = "okay";
};
gpio3: [email protected] {
status = "okay";
};
[email protected] {/*相对于palmbus的偏移,即0x1000,0b00,见《MT7620_ProgrammingGuide》的1.3(P13)的 SPI*/
status = "okay";
[email protected] {/*相对于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分区了*/
[email protected] {
label = "u-boot"; /*此分区的标识,会体现在 /proc/mtd文件中*/
reg = <0x0 0x30000>; /*此分区的偏移量和大小*/
read-only; /*表示此分区只读*/
};
[email protected] {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};
factory: [email protected] {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
};
kernel: [email protected] {
label = "kernel";
reg = <0x50000 0x190000>;
};
rootfs: [email protected] {
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";
};
};
};
[email protected] {
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*/
};
[email protected] {
status = "okay";
};
[email protected] {
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"),*/
};
};
[email protected] {
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>;
};
};
};