DTS设备树规则


参考链接:
https://kernel.meizu.com/device-tree.html
https://zhuanlan.zhihu.com/p/143167176

DTS语法

  • DeviceTree的结构非常简单,由两种元素组成:Node(节点)、Property(属性)
    在这里插入图片描述
  • Node节点。在DTS中使用一对花括号”node-name{}”来定义
  • Property属性。在Node中使用”property-name=value”字符串来定义

标准的property

Property的格式为”property-name=value”,其中value的取值类型如下:

Value描述
Property值为空,用property本身出现或者不出现来表示一个treue/false值
32bit的值,用大端格式存储
64bit的值,用大端格式存储
字符串
混合编码,自定义property的值
作为一个句柄指向一个Node,用来引用Node
字符串数组
  • 文本字符串(无结束符)可以用双引号表示:string-property = “a string”;
  • 无符号整数,用尖括号限定:cell-property = <0xbeef 123 0xabcd1234>;
  • 二进制数据用方括号限定:binary-property = [0x01 0x23 0x45 0x67];
  • 不同表示形式的数据可以使用逗号连在一起:mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;
  • 逗号也可用于创建字符串列表:string-list = “red fish”, “blue fish”;

compatible属性

  • “compatible”属性通常用来device和driver的适配,推荐的格式为”manufacturer,model”,如:compatible = “fsl,mpc8641”, “ns16550”;

model属性

  • “model”属性只是简单的表示型号,root节点用其来传递值给machine_desc_str,如:model = “fsl,MPC8349EMITX”;

phandle属性

  • “phandle”属性通用一个唯一的id来标识一个Node,在property可以使用这个id来引用Node,如:phandle = <1>;
  • 在DeviceTree中通过另一种方式进行phandle的定义和引用,定义一个“label:”,通过"&“来引用"label”,在编译是系统会自动为node生成一个phandle属性,如:cpu0: cpu@0{…},cpu = <&cpu0>;

#address-cells、#size-cells属性

  • “#address-cells, #size-cells”属性用来定义当前node的子node中”reg”属性的解析格式
  • #address-cells和#size-cells属性不会从设备树中的父节点继承
  • 1.如果node”soc”中”#address-cells=<1>”、”#size-cells=<1>”,那么子node”serial”中”reg”属性的解析为“addr1 = 0x0, size1 = 0x100, addr2 = 0x0, size2 = 0x200”
soc {
    #address-cells = <1>;
    #size-cells = <1>;
    serial {
        reg = <0x0 0x100 0x0 0x200>;
    }
}
  • 2.如果node”soc”中”#address-cells=<2>”、”#size-cells=<2>”,那么子node”serial”中”reg”属性的解析为“addr1 = 0x100, size1 = 0x200”
soc {
    #address-cells = <2>;
    #size-cells = <2>;
    serial {
        reg = <0x0 0x100 0x0 0x200>;
    }
}
  • 3.如果node”soc”中”#address-cells=<2>”、”#size-cells=<0>”,那么子node”serial”中”reg”属性的解析为“addr1 = 0x100, addr2 = 0x200”
soc {
    #address-cells = <2>;
    #size-cells = <0>;
    serial {
        reg = <0x0 0x100 0x0 0x200>;
    }
}

regs属性

  • “reg”属性解析出”address,length”数字,解析格式依据父节点的”#address-cells、#size-cells”定义
  • reg 属性描述设备资源在其父总线定义的地址空间内的地址
  • 任意数目的地址和长度对组成[地址 长度],由设备节点的父节点中#address-cells和#size-cells属性指定。如果父节点#size-cells值 为0,则应省略 reg 值中的长度字段。
  • 假设系统内的设备有两个寄存器块,偏移 0x3000 的 32 字节块和偏移 0xFE00 的 256 字节块。reg 属性的编码方式如下(假设#address-cells和#size-cells值为 1):reg = <0x3000 0x20 0xFE00 0x100>;

ranges属性

  • ranges提供了一种在总线的地址空间(子地址空间)和总线节点的父节点(父地址空间)的地址空间之间定义映射或转换的方法
  • 格式为(child-bus-address, parentbus-address, length)
  • child-bus-address是子总线地址空间内的物理地址。表示地址的单元数与总线相关,可以从该节点的#address-cells(显示范围属性的节点)确定
  • parentbus-address是父总线地址空间中的物理地址。表示父地址的单元数与总线相关,可以从定义父地址空间的节点的#address-cells属性确定
  • length指定子地址空间中范围的大小。表示大小的单元数可以从该节点的#size-cells(显示范围属性的节点)确定
  • 如果属性使用值定义,则指定父地址空间和子地址空间相同,并且不需要地址转换
  • 如果该属性不存在于总线节点中,则假定节点的子节点和父地址空间之间不存在映射
{
	...
	#address-cells = <1>;
	#size-cells = <1>;
	...
	soc {
	    compatible = "simple-bus";
	    #address-cells = <2>;
	    #size-cells = <1>;
	    ranges = <0x0  0x0 0x10100000 0x10000
	    		  0x1  0x0 0x10160000 0x10000
	    		  0x2  0x0 0x30000000 0x10000
	    		 >;
	    ethernet@0,0 {
            compatible = "smc,smc91c111";
            reg = <0 0 0x1000>;
        };

        i2c@1,0 {
            compatible = "acme,a1234-i2c-bus";
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <1 0 0x1000>;
            rtc@58 {
                compatible = "maxim,ds1338";
                reg = <58>;
            };
        };

        flash@2,0 {
            compatible = "samsung,k8f1315ebm", "cfi-flash";
            reg = <2 0 0x4000000>;
        };
	};
}
//child-bus-address:0 0或1 0或2 0(因为soc的#address-cells = <2>)
//parentbus-address:0x10100000或0x10160000或0x30000000(因为soc的父节点#address-cells =<1>)
//length:0x10000(因为soc的#size-cells = <1>)

ranges = <0x1 0x0 0x10160000 0x10000>对应i2c@1,0的reg = <1 0 0x1000>
此属性值指定在开始地址0x10160000,大小0x10000 地址空间范围,以物理 地址1寻址的子节点映射到物理 0x10160000的父地址。通过此映射,挂载设备1的节点可以通过负载或存储地址 0、0x1000(在 reg 中指定)的偏移量以及范围中指定的 0x10160000映射进行寻址

status属性

status属性指示设备的运行状态

  • “okay”:指示设备正在运行
  • “disabled”:表示该设备当前无法运行,但是将来可能会运行(比如未插入或关闭的某些设备)
  • “reserved”:表示设备可运行,但不应使用。通常,它用于由另一个软件组件(例如平台固件)控制的设备
  • “fail”:表示设备无法运行。在设备中检测到严重错误,且不进行修复就无法运行
  • “fail-sss”:表示设备无法运行。在设备中检测到严重错误,且如果不进行修复就无法开始运行。sss的部分指定设备,并指示侦测到的错误情况

dts的中断

在这里插入图片描述

产生中断的设备(device)

  • interrupts:定义设备的中断解析,根据其”interrupt-parent”node中定义的“#interrupt-cells”来解析, 会被interrupts-extended覆盖, 通常两者用其一
  • interrupt-parent: 用来制定当前设备的Interrupt Controllers/Interrupt Nexus,phandle指向对应的node, 如果没有设置这个属性, 会自动依附父节点的
  • interrupts-extended: 当设备连接到多个中断控制器时使用; 与interrupts相互排斥,当两者都存在时, interrupts-extended优先

中断控制器

  • #interrupt-cells: 用来规定连接到该中断控制器上的设备的”interrupts”属性的解析长度
  • interrupt-controller: 一个空属性,用来声明当前node为中断控制器

关联属性(nexus properties),实现从一个interrupt domain转化到另一个interrupt domain

  • interrupt-map: 用来描述interrupt nexus设备对中断的路由,解析格式为5元素序列“child unit address, child interrupt specifier, interrupt-parent, parent unit address, parent interrupt specifier”
interrupt-map = <child_unit_address child_interrupt_specifier interrupt_parent parent_unit_address parent_interrupt_specifier>
//child_unit_address:被映射的子节点的单元地址。cells长度由子节点的“#address-cells”指定
//child_interrupt_specifier: 被映射的子节点的中断说明符。 cells长度由子节点的“#interrupt-cells”指定
//interrupt_parent: phandle指向interrupt controller的引用
//parent_unit_address:父中断域中的单元地址。 cells长度由父节点的“#address-cells”指定
//parent_interrupt_specifier: 父域中的中断说明符。 cells长度由父节点的“#interrupt-cells”指定
  • interrupt-map-mask: 与"interrupt-map"执行&操作,cell的数量取决自身节点的"#address-cells"
  • #interrupt-cells: 用来规定连接到该中断控制器上的设备的”interrupts”属性的解析长度
soc {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	open-pic {
		clock-frequency = <0>;
		interrupt-controller;
		#address-cells =<0>;
		#interrupt-cells = <2>;
	};
	pci {
		#interrupt-cells = <1>;
		#size-cells = <2>;
		#address-cells = <3>;
		interrupt-map-mask = <0xf800 0 0 7>;
		interrupt-map = <
			/* IDSEL 0x11 - PCI slot 1 */
			0x8800 0 0 1 &open-pic 2 1 /* INTA */
			0x8800 0 0 2 &open-pic 3 1 /* INTB */
			0x8800 0 0 3 &open-pic 4 1 /* INTC */
			0x8800 0 0 4 &open-pic 1 1 /* INTD */
			/* IDSEL 0x12 - PCI slot 2 */
			0x9000 0 0 1 &open-pic 3 1 /* INTA */
			0x9000 0 0 2 &open-pic 4 1 /* INTB */
			0x9000 0 0 3 &open-pic 1 1 /* INTC */
			0x9000 0 0 4 &open-pic 2 1 /* INTD */
		>;
	};
};
//child unit address: 0x8800 0 0 (因为: #address-cells = <3>;)
//child interrupt specifiler: 1 (因为: #interrupt-cells = <1>;)
//interrupt-parent: &open-pic
//parent unit address: empty (因为open-pic的#address-cells =<0>;)
//parent interrupt specifier: 2 1 (因为open-pic的#interrupt-cells = <2>)

标准Node

Node Name常常由两部分组成“node-name@unit-address”,主要是为了防止Node Name重复冲突

  • “node-name”是node的名字
  • “unit-address”是node中“reg”属性描述的开始地址

Root node

每个DeviceTree只有一个根节点。根节点需要有以下必备属性:

属性名描述
#address-cells定义子node中”reg”属性的address cells长度
#size-cells定义子node中”reg”属性的address_size cells长度
modelroot节点用其来传递值给machine_desc_str
compatible用于在内核启动匹配对应的machine ID

/aliases node

用来给一些绝对路径定义别名

aliases {
    serial0 = "/simple-bus@fe000000/serial@llc500";
    ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};

/memory node

用来传递内存布局

\ {
    #address-cells = <2>;
    #size-cells = <2>;

    memory@0 {
        device_type = "memory";
        reg = <0x000000000 0x00000000 0x00000000 0x80000000
        0x000000001 0x00000000 0x00000001 0x00000000>;
    };
}

/chosen node

其中“bootargs”属性用来传递cmdline参数,“stdout-path”属性用来指定标准输出设备,“stdin-path”属性用来指定标准输入设备

/* chosen */
	chosen {
		bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram";
	};

/cpus node

/cpus节点也是必须有的

cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			device_type = "cpu";
			compatible = "arm,cortex-a35";
			reg = <0x000>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1248000000>;
		};

		cpu1: cpu@001 {
			device_type = "cpu";
			compatible = "arm,cortex-a35";
			reg = <0x001>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1248000000>;
		};

		cpu2: cpu@002 {
			device_type = "cpu";
			compatible = "arm,cortex-a35";
			reg = <0x002>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1248000000>;
		};

		cpu3: cpu@003 {
			device_type = "cpu";
			compatible = "arm,cortex-a35";
			reg = <0x003>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1248000000>;
		};

		cpu4: cpu@100 {
			device_type = "cpu";
			compatible = "arm,cortex-a53";
			reg = <0x100>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1378000000>;
		};

		cpu5: cpu@101 {
			device_type = "cpu";
			compatible = "arm,cortex-a53";
			reg = <0x101>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1378000000>;
		};

		cpu6: cpu@102 {
			device_type = "cpu";
			compatible = "arm,cortex-a53";
			reg = <0x102>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1378000000>;
		};

		cpu7: cpu@103 {
			device_type = "cpu";
			compatible = "arm,cortex-a53";
			reg = <0x103>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1378000000>;
		};

		cpu8: cpu@200 {
			device_type = "cpu";
			compatible = "arm,cortex-a73";
			reg = <0x200>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1638000000>;
		};

		cpu9: cpu@201 {
			device_type = "cpu";
			compatible = "arm,cortex-a73";
			reg = <0x201>;
			enable-method = "psci";
			cpu-idle-states = <&LEGACY_MCDI &LEGACY_SODI &LEGACY_SODI3 &LEGACY_DPIDLE>,
					  <&LEGACY_SUSPEND &MCDI &SODI &SODI3 &DPIDLE &SUSPEND>;
			cpu-release-addr = <0x0 0x40000200>;
			clock-frequency = <1638000000>;
		};

		cpu-map {
			cluster0 {
				core0 {
					cpu = <&cpu0>;
				};


				core1 {
					cpu = <&cpu1>;
				};

				core2 {
					cpu = <&cpu2>;
				};

				core3 {
					cpu = <&cpu3>;
				};

			};

			cluster1 {
				core0 {
					cpu = <&cpu4>;
				};

				core1 {
					cpu = <&cpu5>;
				};

				core2 {
					cpu = <&cpu6>;
				};

				core3 {
					cpu = <&cpu7>;
				};

			};

			cluster2 {
				core0 {
					cpu = <&cpu8>;
				};

				core1 {
					cpu = <&cpu9>;
				};

			};
		};

		idle-states {
			entry-method = "arm,psci";

			LEGACY_MCDI: legacy-mcdi {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0000001>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			LEGACY_SODI: legacy-sodi {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0000002>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			LEGACY_SODI3: legacy-sodi3 {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0000003>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			LEGACY_DPIDLE: legacy-dpidle {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0000004>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			LEGACY_SUSPEND: legacy-suspend {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0000005>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			MCDI: mcdi {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x0010001>;
				entry-latency-us = <600>;
				exit-latency-us = <600>;
				min-residency-us = <1200>;
			};

			SODI: sodi {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x1010002>;
				entry-latency-us = <800>;
				exit-latency-us = <1000>;
				min-residency-us = <2000>;
			};

			SODI3: sodi3 {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x1010003>;
				entry-latency-us = <800>;
				exit-latency-us = <1000>;
				min-residency-us = <2000>;
			};

			DPIDLE: dpidle {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x1010004>;
				entry-latency-us = <800>;
				exit-latency-us = <1000>;
				min-residency-us = <2000>;
			};

			SUSPEND: suspend {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x1010005>;
				entry-latency-us = <800>;
				exit-latency-us = <1000>;
				min-residency-us = <2000>;
			};

		};
	};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值