一个CPU可能对应多个平台,为了方便开发,只能这么做,dts文件和dtsi文件相当于C语言的.c和.h文件.一样可以包含,下面以BBB的DTS文件分析学习格式规范.
涉及的文件包含:
- am33xx.dtsi
- am33xx-bone-common.dtsi
- am335x-bone-black.dts
其中每个AM3359[或者说AM33XX]平台都包含第一个文件am33xx.dtsi,而所有的Beaglebone都包含第二个文件,而第三个又是细化,包含.所有文件最后包含skeleton.dtsi,不过这个不用分析,固定的了.
如果把文件当成C看待,那会简单非常非常多,整体结构如下:
02 | compatible = "ti,am33xx" ; |
03 | interrupt-parent = <&intc>; |
10 | compatible = "simple-bus" ; |
14 | ti,hwmods = "l3_main" ; |
16 | intc: interrupt-controller@48200000 { |
17 | compatible = "ti,omap2-intc" ; |
19 | #interrupt-cells = <1>; |
21 | reg = <0x48200000 0x1000>; |
整体结构如上,先是说明平台,然后指向中断控制器的指针,还可以写一些别名.就是描述平台用的.比如上面的中断指向intc,那么在ocp下有intc,用于处理中断信号.aliases下把serial0当成uart1,所以下面就可以如下写法.
1 | uart1: serial@44e09000 { |
2 | compatible = "ti,omap3-uart" ; |
4 | clock -frequency = <48000000>; |
5 | reg = <0x44e09000 0x2000>; |
节点会遵循这个格式:
03 | a-string-property = "A string" ; |
04 | a-string-list-property = "first string" , "second string" ; |
05 | a-byte-data-property = [0x01 0x23 0x34 0x56]; |
08 | second-child-property = <1>; |
09 | a-string-property = "Hello, world" ; |
16 | a-cell-property = <1 2 3 4>; |
上面描述了两个node,node1下面还有两个child-node,比如处理器节点:
03 | compatible = "arm,cortex-a8" ; |
11 | voltage-tolerance = <2>; |
12 | clock -latency = <300000>; |
其中compatible是用于绑定设备的manufacturer,model,理解为用户驱动和设备的绑定.下面是可操作的点,频率电压,这里说明的是720M啊,那1G在哪里,不急,先慢慢分析.
再往下看看GPIO控制器:
01 | gpio1: gpio@44e07000 { |
02 | compatible = "ti,omap4-gpio" ; |
07 | #interrupt-cells = <1>; |
08 | reg = <0x44e07000 0x1000>; |
其中开始的gpio@44e07000属于<name>[@<unit-address>]格式,其中[]是可选的,这个说明他在44E0 7000地址上.gpio是类型,gpio1才是名字.
可寻址的外设[或者设备],reg字段,描述地址从0x44E0 7000开始,共0x1000长度,与手册描述的一样.而gpio-controller;说明自己是GPIO控制器,就如前面的中断控制器必须说明自己是中断控制器interrupt-controller[这里GPIO也包含中断控制],interrupts指定中断号,cell指定的是cell大小.
而在bone-common.dtsi,包含一些覆盖配置.
3 | cpu0-supply = <&dcdc2_reg>; |
也可以替代一些LED驱动之类的.
02 | compatible = "gpio-leds" ; |
03 | pinctrl-names = "default" ; |
04 | pinctrl-0 = <&userled_pins>; |
07 | label = "beaglebone:green:usr0" ; |
08 | gpios = <&gpio2 21 0>; |
09 | linux, default -trigger = "heartbeat" ; |
10 | default -state = "off" ; |
14 | label = "beaglebone:green:usr1" ; |
15 | gpios = <&gpio2 22 0>; |
16 | linux, default -trigger = "mmc0" ; |
17 | default -state = "off" ; |
21 | label = "beaglebone:green:usr2" ; |
22 | gpios = <&gpio2 23 0>; |
23 | linux, default -trigger = "cpu0" ; |
24 | default -state = "off" ; |
28 | label = "beaglebone:green:usr3" ; |
29 | gpios = <&gpio2 24 0>; |
30 | default -state = "off" ; |
31 | linux, default -trigger = "mmc1" ; |
在linux内核中用dtc编译dts文件到dtb,当我们运行make dtbs时候,如果已经选了ARCH_OMAP2PLUS,那么以下文件会被编译出来.
01 | dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ |
15 | am335x-boneblack.dtb \ |
有了dts这个东西,以前经常在mach-xxx的信息可以省掉了,ARM社区一贯充斥的大量垃圾代码导致Linus盛怒,因此社区在2011年到2012年进行了大量的工作,ARM Linux开始围绕Device Tree展开,Device Tree有自己的独立的语法,它的源文件为.dts,编译后得到.dtb,Bootloader在引导Linux内核的时候会将.dtb地址告知内核,之后内核会展开Device Tree并创建和注册相关的设备,因此arch/arm/mach-xxx和arch/arm/plat-xxx中大量的用于注册platform板级信息的代码被删除,而驱动也以新的方式和.dts中定义的设备结点进行匹配.