设备树实例(一)

如何单独编译设备树?

cd linux-x.xx & make dtbs

生成的dtb在目录linux-x.xx/arch/xxx/boot/dts下

反编译dtb,生成dts: linux-x.xx/scripts/dtc/dtc -I dtb -O dts xxxx.dtb -o xxxx.dts 

 

全志A64实例:

arch/arm64/boot/dts/Makefile:

 1 #dtb-$(CONFIG_ARCH_SUN50I) += sun50iw1p1-fpga.dtb sun50iw1p1-soc.dtb 
 2 dtb-$(CONFIG_ARCH_SUN50I) += sun50iw1p1-t1.dtb #add by kevin_hwang
 3 
 4 targets += dtbs
 5 
 6 DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES))
 7 ifneq ($(DTB_NAMES),)
 8 DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
 9 else
10 DTB_LIST := $(dtb-y)
11 endif
12 targets += $(DTB_LIST)
13 
14 dtbs: $(addprefix $(obj)/, $(DTB_LIST))
15 
16 clean-files := dts/*.dtb *.dtb

目的把sun50iw1p1-soc.dts生成sun50iw1p1-soc.dtb

 

sun50iw1p1-soc.dts:

 1 /*
 2  * Allwinner Technology CO., Ltd. sun50iw1p1 fpga board.
 3  *
 4  * 
 5  */
 6 
 7 /dts-v1/;
 8 #include "sun50iw1p1.dtsi"
 9 
10 /{
11 
12     soc@01c00000 {
13         ......
14         ......
15         ......
16     };
17 };

Line 8:包含sun50iw1p1.dtsi,一般表示这个SOC公共部分,而sun50iw1p1-soc.dts是延伸扩展公共部分。

 

sun50iw1p1.dtsi:

  1 /*
  2  * Allwinner Technology CO., Ltd. sun50iw1p1 platform
  3  * modify base on juno.dts
  4  */
  5 
  6 #include <dt-bindings/interrupt-controller/arm-gic.h>
  7 #include <dt-bindings/gpio/gpio.h>
  8  #include "sun50iw1p1-clk.dtsi"
  9  #include "sun50iw1p1-pinctrl.dtsi"
 10  / {
 11      model = "sun50iw1p1";
 12      compatible = "arm,sun50iw1p1", "arm,sun50iw1p1";
 13      interrupt-parent = <&gic>;
 14      #address-cells = <2>;
 15      #size-cells = <2>;
 16  
 17      aliases {
 18          serial0 = &uart0;
 19          ......
 20          ......
 21          ......
 22          boot_disp = &boot_disp;
 23      };
 24  
 25      chosen {
 26          bootargs = "earlyprintk=sunxi-uart,0x01c28000 loglevel=8 initcall_debug=1 console=ttyS0 init=/init";
 27          linux,initrd-start = <0x0 0x0>;
 28          linux,initrd-end = <0x0 0x0>;
 29      };
 30  
 31      cpus {
 32          #address-cells = <2>;
 33          #size-cells = <0>;
 34  
 35          cpu@0 {
 36              device_type = "cpu";
 37              compatible = "arm,cortex-a53","arm,armv8";
 38              reg = <0x0 0x0>;
 39              enable-method = "psci";
 40              cpufreq_tbl = < 480000 600000 720000 816000 1008000 
 41                      1104000 1152000 1200000 1344000>;
 42              clock-latency = <2000000>;
 43              clock-frequency = <1008000000>;
 44              cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 &SYS_SLEEP_0>;
 45          };
 46          cpu@1 {
 47              device_type = "cpu";
 48              compatible = "arm,cortex-a53","arm,armv8";
 49              reg = <0x0 0x1>;
 50              enable-method = "psci";
 51              clock-frequency = <1008000000>;
 52              cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 &SYS_SLEEP_0>;
 53          };
 54          cpu@2 {
 55              ......
 56              ......
 57              ......
 58          };
 59          cpu@3 {
 60              ......
 61              ......
 62              ......
 63          };
 64      };
 65  
 66      memory@40000000 {
 67          device_type = "memory";
 68          reg = <0x00000000 0x40000000 0x00000000 0x40000000>;
 69      };
 70  
 71      gic: interrupt-controller@1c81000 {
 72          compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
 73          #interrupt-cells = <3>;
 74          #address-cells = <0>;
 75          device_type = "gic"; 
 76          interrupt-controller;
 77          reg = <0x0 0x01c81000 0 0x1000>, /* GIC Dist */
 78                <0x0 0x01c82000 0 0x2000>, /* GIC CPU */
 79                <0x0 0x01c84000 0 0x2000>, /* GIC VCPU Control */
 80                <0x0 0x01c86000 0 0x2000>; /* GIC VCPU */
 81          interrupts = <GIC_PPI 9 0xf04>; /* GIC Maintenence IRQ */
 82      };
 83  
 84      soc: soc@01c00000 {
 85          compatible = "simple-bus";
 86          #address-cells = <2>;
 87          #size-cells = <2>;
 88          ranges;
 89          device_type = "soc";
 90  
 91          uart0: uart@01c28000 {
 92              compatible = "allwinner,sun50i-uart";
 93              device_type = "uart0";
 94              reg = <0x0 0x01c28000 0x0 0x400>;
 95              interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
 96              clocks = <&clk_uart0>;
 97              pinctrl-names = "default", "sleep";
 98              pinctrl-0 = <&uart0_pins_a>;
 99              pinctrl-1 = <&uart0_pins_b>;
100              uart0_port = <0>;
101              uart0_type = <2>;
102              status = "disabled";
103              ......
104              ......
105              ......            
106          };
107          ......
108          ......
109          ......
110      };
111  };

 *note:<name>[@<unit-address>]是节点的格式,其中unit-address是单位偏移地址,本人验证去掉[]内的内容依然可以运行,也没在source code找到必须存在的理由。

“/"代表根节点;

“model”是板的ID;

"compatible"是平台兼容,一般格式是"manufacturer,model"。内核或者uboot依靠这个属性找到相对应driver,若"compatible"出现多个属性,按序匹配driver;

“#address-cells”是address的单位(32bit);

“#size-cells”是length的单位(32bit);

"reg"是寄存器,格式是"<address,length>",作为平台内存资源;

"aliase" 是别名,必须节点全称,可以通过地址引用获取;

”chosen“是板级启动参数;

"cpus"是SOC的CPU信息,可以改变运行频率或者开关CPU;

"memory"是板级内存的信息。

"interrupts"是中断控制器,根据SOC自定义格式,这里是<输入类型 中断号 触发方式>,作为平台中断资源;

“interrupt-controller”指示这个节点是中断控制节点;

"[label:]"如gic: interrupt-controller@1c81000,这个标签可以作为地址赋值到其他节点的属性;

“device_type":设备类型,寻找节点可以依据这个属性;

"status"是开关节点设备的状态,取值"okay"或者"ok"表示使能,"disabled"表示失能。

 

Line 10和11包含"sun50iw1p1-clk.dtsi"和"sun50iw1p1-pinctrl.dtsi"以下简略查看代码:

sun50iw1p1-clk.dtsi:

 1 /{
 2 clocks {
 3    compatible = "allwinner,sunxi-clk-init";
 4    device_type = "clocks";
 5    #address-cells = <2>;
 6    #size-cells = <2>;
 7    ranges;
 8    reg = <0x0 0x01c20000 0x0 0x0320> ,  /*cpux space*/
 9          <0x0 0x01f01400 0x0 0x00B0> , /*cpus space*/
10           <0x0 0x01f00060 0x0 0x4>; 
11 /* register fixed rate clock*/
12         clk_uart0: uart0 {
13             #clock-cells = <0>;
14             compatible = "allwinner,sunxi-periph-clock";
15             clock-output-names = "uart0";
16         };
17         ......
18         ......
19         ......        
20     
21     };/*clocks end*/
22 };

 

在"sun50iw1p1.dtsi"中"uart0: uart@01c28000"节点的"clock = <&clk_uart0>",引用的是"sun50iw1p1-clk.dtsi"中的"clk_uart0: uart0"节点。

 

sun50iw1p1-pinctrl.dtsi:

 1 /*
 2 * Allwinner 1689 pin config info.
 3 */
 4 / {
 5     soc@01c00000{
 6         ......
 7         ......
 8         ......
 9         pio: pinctrl@01c20800 {
10             compatible = "allwinner,sun50i-pinctrl";
11             reg = <0x0 0x01c20800 0x0 0x400>;
12             interrupts = <GIC_SPI 11 4>,
13                      <GIC_SPI 17 4>,
14                      <GIC_SPI 21 4>;
15             device_type = "pio";
16             clocks = <&clk_pio>;
17             gpio-controller;
18             interrupt-controller;
19             #interrupt-cells = <2>;
20             #size-cells = <0>;
21             #gpio-cells = <6>;
22 23             uart0_pins_a: uart0@0 {
24                 allwinner,pins = "PB8", "PB9";
25                 allwinner,pname = "uart0_tx", "uart0_rx";
26                 allwinner,function = "uart0";
27                 allwinner,muxsel = <4>;
28                 allwinner,drive = <1>;
29                 allwinner,pull = <1>;
30             };
31 
32             uart0_pins_b: uart0@1 {
33                 allwinner,pins = "PB8", "PB9";
34                 allwinner,function = "io_disabled";
35                 allwinner,muxsel = <7>;
36                 allwinner,drive = <1>;
37                 allwinner,pull = <1>;
38             };
39             ......
40             ......
41             ......
42         };
43         ......
44         ......
45         ......        
46     };
47 };

 

在"sun50iw1p1.dtsi"中"uart0: uart@01c28000"节点的"pinctrl-0 = <&uart0_pins_a>"和"pinctrl-1 = <&uart0_pins_b>",引用的是"sun50iw1p1-pinctrl.dtsi"中的"uart0_pins_a"和"uart0_pins_b"节点,分别对应工作和睡眠的IO状态。"sun50iw1p1-pinctrl.dtsi"是全志a64的具体io配置。

 

编译dts生成dtb,然后反编译得到.dts,再看看生成的代码:

  1 / {
  2     model = "sun50iw1p1";
  3     compatible = "arm,sun50iw1p1", "arm,sun50iw1p1";
  4     interrupt-parent = <0x1>;
  5     #address-cells = <0x2>;
  6     #size-cells = <0x2>;
  7 
  8     clocks {
  9         compatible = "allwinner,sunxi-clk-init";
 10         device_type = "clocks";
 11         #address-cells = <0x2>;
 12         #size-cells = <0x2>;
 13         ranges;
 14         reg = <0x0 0x1c20000 0x0 0x320 0x0 0x1f01400 0x0 0xb0 0x0 0x1f00060 0x0 0x4>;
 15 
 16         uart0 {
 17             #clock-cells = <0x0>;
 18             compatible = "allwinner,sunxi-periph-clock";
 19             clock-output-names = "uart0";
 20             linux,phandle = <0x18>;
 21             phandle = <0x18>;
 22         };
 23 
 24         ......
 25         ......
 26         ......
 27     };
 28 
 29     soc@01c00000 {
 30         compatible = "simple-bus";
 31         #address-cells = <0x2>;
 32         #size-cells = <0x2>;
 33         ranges;
 34         device_type = "soc";
 35 
 36         pinctrl@01c20800 {
 37             compatible = "allwinner,sun50i-pinctrl";
 38             reg = <0x0 0x1c20800 0x0 0x400>;
 39             interrupts = <0x0 0xb 0x4 0x0 0x11 0x4 0x0 0x15 0x4>;
 40             device_type = "pio";
 41             clocks = <0xa>;
 42             gpio-controller;
 43             interrupt-controller;
 44             #interrupt-cells = <0x2>;
 45             #size-cells = <0x0>;
 46             #gpio-cells = <0x6>;
 47             linux,phandle = <0x30>;
 48             phandle = <0x30>;
 49 
 50             uart0@0 {
 51                 allwinner,pins = "PB8", "PB9";
 52                 allwinner,pname = "uart0_tx", "uart0_rx";
 53                 allwinner,function = "uart0";
 54                 allwinner,muxsel = <0x4>;
 55                 allwinner,drive = <0x1>;
 56                 allwinner,pull = <0x1>;
 57                 linux,phandle = <0x19>;
 58                 phandle = <0x19>;
 59             };
 60 
 61             uart0@1 {
 62                 allwinner,pins = "PB8", "PB9";
 63                 allwinner,function = "io_disabled";
 64                 allwinner,muxsel = <0x7>;
 65                 allwinner,drive = <0x1>;
 66                 allwinner,pull = <0x1>;
 67                 linux,phandle = <0x1a>;
 68                 phandle = <0x1a>;
 69             };
 70 
 71             ......
 72             ......
 73             ......    
 74         };
 75 
 76         uart@01c28000 {
 77             compatible = "allwinner,sun50i-uart";
 78             device_type = "uart0";
 79             reg = <0x0 0x1c28000 0x0 0x400>;
 80             interrupts = <0x0 0x0 0x4>;
 81             clocks = <0x18>;
 82             pinctrl-names = "default", "sleep";
 83             pinctrl-0 = <0x19>;
 84             pinctrl-1 = <0x1a>;
 85             uart0_port = <0x0>;
 86             uart0_type = <0x2>;
 87             status = "disabled";
 88         };
 89 
 90         ......
 91         ......
 92         ......
 93 
 94     aliases {
 95         serial0 = "/soc@01c00000/uart@01c28000";
 96         ......
 97         ......
 98         ......
 99         boot_disp = "/soc@01c00000/boot_disp";
100     };
101 
102     chosen {
103         bootargs = "earlyprintk=sunxi-uart,0x01c28000 loglevel=8 initcall_debug=1 console=ttyS0 init=/init";
104         linux,initrd-start = <0x0 0x0>;
105         linux,initrd-end = <0x0 0x0>;
106     };
107 
108     cpus {
109         #address-cells = <0x2>;
110         #size-cells = <0x0>;
111 
112         cpu@0 {
113             device_type = "cpu";
114             compatible = "arm,cortex-a53", "arm,armv8";
115             reg = <0x0 0x0>;
116             enable-method = "psci";
117             cpufreq_tbl = <0x75300 0x927c0 0xafc80 0xc7380 0xf6180 0x10d880 0x119400 0x124f80 0x148200>;
118             clock-latency = <0x1e8480>;
119             clock-frequency = <0x3c14dc00>;
120             cpu-idle-states = <0x8e 0x8f 0x90>;
121         };
122 
123         cpu@1 {
124             device_type = "cpu";
125             compatible = "arm,cortex-a53", "arm,armv8";
126             reg = <0x0 0x1>;
127             enable-method = "psci";
128             clock-frequency = <0x3c14dc00>;
129             cpu-idle-states = <0x8e 0x8f 0x90>;
130         };
131 
132         cpu@2 {
133             ......
134             ......
135             ......
136         };
137 
138         cpu@3 {
139             ......
140             ......
141             ......
142         };
143         ......
144         ......
145         ......
146     };
147 
148     memory@40000000 {
149         device_type = "memory";
150         reg = <0x0 0x40000000 0x0 0x40000000>;
151     };
152 
153     interrupt-controller@1c81000 {
154         compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
155         #interrupt-cells = <0x3>;
156         #address-cells = <0x0>;
157         device_type = "gic";
158         interrupt-controller;
159         reg = <0x0 0x1c81000 0x0 0x1000 0x0 0x1c82000 0x0 0x2000 0x0 0x1c84000 0x0 0x2000 0x0 0x1c86000 0x0 0x2000>;
160         interrupts = <0x1 0x9 0xf04>;
161         linux,phandle = <0x1>;
162         phandle = <0x1>;
163     };
164 
165     ......
166     ......
167     ......
168 };

"sun50iw1p1-clk.dtsi"的clock和"sun50iw1p1-pinctrl.dtsi"的pinctrl@01c20800在根目录自动寻找适合的文件路径合并。

可以看出引用地址其实就是取目的地址的"phandle = <0x>"的值如uart@01c28000{pinctrl-0 = <0x19>;}其实就是找到phandle = <0x19>的属性,这个属性在uart0@0节点下面。

而”aliases“则引用地址的全路径,不用phandle。

 

posted @ 2016-07-13 15:00  Kevin_Hwang  阅读(10852)  评论(0编辑  收藏  举报