设备树实例(一)
2016-07-13 15:00
323 查看
如何单独编译设备树?
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:
目的把sun50iw1p1-soc.dts生成sun50iw1p1-soc.dtb
sun50iw1p1-soc.dts:
Line 8:包含sun50iw1p1.dtsi,一般表示这个SOC公共部分,而sun50iw1p1-soc.dts是延伸扩展公共部分。
sun50iw1p1.dtsi:
*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:
在"sun50iw1p1.dtsi"中"uart0: uart@01c28000"节点的"clock = <&clk_uart0>",引用的是"sun50iw1p1-clk.dtsi"中的"clk_uart0: uart0"节点。
sun50iw1p1-pinctrl.dtsi:
在"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,再看看生成的代码:
"sun50iw1p1-clk.dtsi"的clock和"sun50iw1p1-pinctrl.dtsi"的pinctrl@01c20800在根目录自动寻找适合的文件路径合并。
可以看出引用地址其实就是取目的地址的"phandle = <0x>"的值如uart@01c28000{pinctrl-0 = <0x19>;}其实就是找到phandle = <0x19>的属性,这个属性在uart0@0节点下面。
而”aliases“则引用地址的全路径,不用phandle。
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:
#dtb-$(CONFIG_ARCH_SUN50I) += sun50iw1p1-fpga.dtb sun50iw1p1-soc.dtb dtb-$(CONFIG_ARCH_SUN50I) += sun50iw1p1-t1.dtb #add by kevin_hwang targets += dtbs DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES)) ifneq ($(DTB_NAMES),) DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) else DTB_LIST := $(dtb-y) endif targets += $(DTB_LIST) dtbs: $(addprefix $(obj)/, $(DTB_LIST)) clean-files := dts/*.dtb *.dtb
目的把sun50iw1p1-soc.dts生成sun50iw1p1-soc.dtb
sun50iw1p1-soc.dts:
/* * Allwinner Technology CO., Ltd. sun50iw1p1 fpga board. * * */ /dts-v1/; #include "sun50iw1p1.dtsi" /{ soc@01c00000 { ...... ...... ...... }; };
Line 8:包含sun50iw1p1.dtsi,一般表示这个SOC公共部分,而sun50iw1p1-soc.dts是延伸扩展公共部分。
sun50iw1p1.dtsi:
/* * Allwinner Technology CO., Ltd. sun50iw1p1 platform * modify base on juno.dts */ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/gpio/gpio.h> #include "sun50iw1p1-clk.dtsi" #include "sun50iw1p1-pinctrl.dtsi" / { model = "sun50iw1p1"; compatible = "arm,sun50iw1p1", "arm,sun50iw1p1"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; aliases { serial0 = &uart0; ...... ...... ...... boot_disp = &boot_disp; }; chosen { bootargs = "earlyprintk=sunxi-uart,0x01c28000 loglevel=8 initcall_debug=1 console=ttyS0 init=/init"; linux,initrd-start = <0x0 0x0>; linux,initrd-end = <0x0 0x0>; }; cpus { #address-cells = <2>; #size-cells = <0>; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; cpufreq_tbl = < 480000 600000 720000 816000 1008000 1104000 1152000 1200000 1344000>; clock-latency = <2000000>; clock-frequency = <1008000000>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 &SYS_SLEEP_0>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; clock-frequency = <1008000000>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 &SYS_SLEEP_0>; }; cpu@2 { ...... ...... ...... }; cpu@3 { ...... ...... ...... }; }; memory@40000000 { device_type = "memory"; reg = <0x00000000 0x40000000 0x00000000 0x40000000>; }; gic: interrupt-controller@1c81000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; #address-cells = <0>; device_type = "gic"; interrupt-controller; reg = <0x0 0x01c81000 0 0x1000>, /* GIC Dist */ <0x0 0x01c82000 0 0x2000>, /* GIC CPU */ <0x0 0x01c84000 0 0x2000>, /* GIC VCPU Control */ <0x0 0x01c86000 0 0x2000>; /* GIC VCPU */ interrupts = <GIC_PPI 9 0xf04>; /* GIC Maintenence IRQ */ }; soc: soc@01c00000 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; ranges; device_type = "soc"; uart0: uart@01c28000 { compatible = "allwinner,sun50i-uart"; device_type = "uart0"; reg = <0x0 0x01c28000 0x0 0x400>; interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_uart0>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&uart0_pins_a>; pinctrl-1 = <&uart0_pins_b>; uart0_port = <0>; uart0_type = <2>; status = "disabled"; ...... ...... ...... }; ...... ...... ...... }; };
*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:
/{ clocks { compatible = "allwinner,sunxi-clk-init"; device_type = "clocks"; #address-cells = <2>; #size-cells = <2>; ranges; reg = <0x0 0x01c20000 0x0 0x0320> , /*cpux space*/ <0x0 0x01f01400 0x0 0x00B0> , /*cpus space*/ <0x0 0x01f00060 0x0 0x4>; /* register fixed rate clock*/ clk_uart0: uart0 { #clock-cells = <0>; compatible = "allwinner,sunxi-periph-clock"; clock-output-names = "uart0"; }; ...... ...... ...... };/*clocks end*/ };
在"sun50iw1p1.dtsi"中"uart0: uart@01c28000"节点的"clock = <&clk_uart0>",引用的是"sun50iw1p1-clk.dtsi"中的"clk_uart0: uart0"节点。
sun50iw1p1-pinctrl.dtsi:
/* * Allwinner 1689 pin config info. */ / { soc@01c00000{ ...... ...... ...... pio: pinctrl@01c20800 { compatible = "allwinner,sun50i-pinctrl"; reg = <0x0 0x01c20800 0x0 0x400>; interrupts = <GIC_SPI 11 4>, <GIC_SPI 17 4>, <GIC_SPI 21 4>; device_type = "pio"; clocks = <&clk_pio>; gpio-controller; interrupt-controller; #interrupt-cells = <2>; #size-cells = <0>; #gpio-cells = <6>; uart0_pins_a: uart0@0 { allwinner,pins = "PB8", "PB9"; allwinner,pname = "uart0_tx", "uart0_rx"; allwinner,function = "uart0"; allwinner,muxsel = <4>; allwinner,drive = <1>; allwinner,pull = <1>; }; uart0_pins_b: uart0@1 { allwinner,pins = "PB8", "PB9"; allwinner,function = "io_disabled"; allwinner,muxsel = <7>; allwinner,drive = <1>; allwinner,pull = <1>; }; ...... ...... ...... }; ...... ...... ...... }; };
在"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,再看看生成的代码:
/ { model = "sun50iw1p1"; compatible = "arm,sun50iw1p1", "arm,sun50iw1p1"; interrupt-parent = <0x1>; #address-cells = <0x2>; #size-cells = <0x2>; clocks { compatible = "allwinner,sunxi-clk-init"; device_type = "clocks"; #address-cells = <0x2>; #size-cells = <0x2>; ranges; reg = <0x0 0x1c20000 0x0 0x320 0x0 0x1f01400 0x0 0xb0 0x0 0x1f00060 0x0 0x4>; uart0 { #clock-cells = <0x0>; compatible = "allwinner,sunxi-periph-clock"; clock-output-names = "uart0"; linux,phandle = <0x18>; phandle = <0x18>; }; ...... ...... ...... }; soc@01c00000 { compatible = "simple-bus"; #address-cells = <0x2>; #size-cells = <0x2>; ranges; device_type = "soc"; pinctrl@01c20800 { compatible = "allwinner,sun50i-pinctrl"; reg = <0x0 0x1c20800 0x0 0x400>; interrupts = <0x0 0xb 0x4 0x0 0x11 0x4 0x0 0x15 0x4>; device_type = "pio"; clocks = <0xa>; gpio-controller; interrupt-controller; #interrupt-cells = <0x2>; #size-cells = <0x0>; #gpio-cells = <0x6>; linux,phandle = <0x30>; phandle = <0x30>; uart0@0 { allwinner,pins = "PB8", "PB9"; allwinner,pname = "uart0_tx", "uart0_rx"; allwinner,function = "uart0"; allwinner,muxsel = <0x4>; allwinner,drive = <0x1>; allwinner,pull = <0x1>; linux,phandle = <0x19>; phandle = <0x19>; }; uart0@1 { allwinner,pins = "PB8", "PB9"; allwinner,function = "io_disabled"; allwinner,muxsel = <0x7>; allwinner,drive = <0x1>; allwinner,pull = <0x1>; linux,phandle = <0x1a>; phandle = <0x1a>; }; ...... ...... ...... }; uart@01c28000 { compatible = "allwinner,sun50i-uart"; device_type = "uart0"; reg = <0x0 0x1c28000 0x0 0x400>; interrupts = <0x0 0x0 0x4>; clocks = <0x18>; pinctrl-names = "default", "sleep"; pinctrl-0 = <0x19>; pinctrl-1 = <0x1a>; uart0_port = <0x0>; uart0_type = <0x2>; status = "disabled"; }; ...... ...... ...... aliases { serial0 = "/soc@01c00000/uart@01c28000"; ...... ...... ...... boot_disp = "/soc@01c00000/boot_disp"; }; chosen { bootargs = "earlyprintk=sunxi-uart,0x01c28000 loglevel=8 initcall_debug=1 console=ttyS0 init=/init"; linux,initrd-start = <0x0 0x0>; linux,initrd-end = <0x0 0x0>; }; cpus { #address-cells = <0x2>; #size-cells = <0x0>; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; cpufreq_tbl = <0x75300 0x927c0 0xafc80 0xc7380 0xf6180 0x10d880 0x119400 0x124f80 0x148200>; clock-latency = <0x1e8480>; clock-frequency = <0x3c14dc00>; cpu-idle-states = <0x8e 0x8f 0x90>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; clock-frequency = <0x3c14dc00>; cpu-idle-states = <0x8e 0x8f 0x90>; }; cpu@2 { ...... ...... ...... }; cpu@3 { ...... ...... ...... }; ...... ...... ...... }; memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0x0 0x40000000>; }; interrupt-controller@1c81000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <0x3>; #address-cells = <0x0>; device_type = "gic"; interrupt-controller; reg = <0x0 0x1c81000 0x0 0x1000 0x0 0x1c82000 0x0 0x2000 0x0 0x1c84000 0x0 0x2000 0x0 0x1c86000 0x0 0x2000>; interrupts = <0x1 0x9 0xf04>; linux,phandle = <0x1>; phandle = <0x1>; }; ...... ...... ...... };
"sun50iw1p1-clk.dtsi"的clock和"sun50iw1p1-pinctrl.dtsi"的pinctrl@01c20800在根目录自动寻找适合的文件路径合并。
可以看出引用地址其实就是取目的地址的"phandle = <0x>"的值如uart@01c28000{pinctrl-0 = <0x19>;}其实就是找到phandle = <0x19>的属性,这个属性在uart0@0节点下面。
而”aliases“则引用地址的全路径,不用phandle。
相关文章推荐
- Java多线程2:Thread中的实例方法
- java 邮件 main方法实现
- 使用TexturePacker生成png和plist,在Cocos2dx中使用plist和png
- Iframe高度自适应(兼容IEFirefox、同域跨域)
- 指针数组和数组指针区别
- <LeetCode>题66~68: 二叉树的遍历
- LeetCode[371] Sum of Two Integers
- Eclipse插件卸载
- LeetCode Roman to Integer
- 迷失了方向,失去了动力
- [架构设计]关于消息队列的使用
- Iframe高度自适应(兼容IEFirefox、同域跨域)
- c++ 常见问题之string
- 第三方认证
- ON DUPLICATE KEY UPDATE
- .NET-分页处理方式
- 把pdf转换成word格式的转换方法
- 做饭给自己一人吃,如何最快速,且营养有保证?
- Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
- Git+GitHub,构建自己的开源仓库之Git命令