您的位置:首页 > 其它

设备树实例(一)

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:

#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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: