Devicetree 源码 (DTS) 编码规范¶
在编写 Devicetree 源码 (DTS) 时,请遵循以下准则。这些准则应被视为对 Devicetree 规范和 dtc 编译器(包括 W=1 和 W=2 构建)中已有规则的补充。
各个架构和子架构可以定义额外的规则,使编码规范更加严格。
命名与有效字符¶
Devicetree 规范允许在节点和属性名称中使用广泛的字符,但本编码规范缩小了字符范围,以获得更好的代码可读性。
节点和属性名称只能使用以下字符
小写字符:[a-z]
数字:[0-9]
连字符:-
标签(Labels)只能使用以下字符
小写字符:[a-z]
数字:[0-9]
下划线:_
除非总线另有定义,否则单元地址应使用小写十六进制数字,且不带前导零(填充)。
属性中的十六进制值(例如 “reg”)应使用小写十六进制。地址部分可以使用前导零进行填充。
示例
gpi_dma2: dma-controller@a00000 {
compatible = "qcom,sm8550-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0x0 0x00a00000 0x0 0x60000>;
}
节点顺序¶
总线上的节点(因此子节点使用单元地址)应按单元地址的升序排列。或者对于某些子架构,相同类型的节点可以归为一组,例如所有 I2C 控制器依次排列,即使这会破坏单元地址的顺序。
没有单元地址的节点应按节点名称的字母数字顺序排列。对于少数几种节点类型,可以按主要属性排序,例如引脚配置状态按 “pins” 属性的值排序。
通过 &label 在板级 DTS 中扩展节点时,条目应按字母数字顺序排列,或者保持与 DTSI 中相同的顺序,具体选择取决于子架构。
上述排序规则易于在审查期间执行,减少了同时向文件添加新节点时发生冲突的可能性,并有助于浏览 DTS 源码。
示例
/* SoC DTSI */
/ {
cpus {
/* ... */
};
psci {
/* ... */
};
soc@0 {
dma: dma-controller@10000 {
/* ... */
};
clk: clock-controller@80000 {
/* ... */
};
};
};
/* Board DTS - alphabetical order */
&clk {
/* ... */
};
&dma {
/* ... */
};
/* Board DTS - alternative order, keep as DTSI */
&dma {
/* ... */
};
&clk {
/* ... */
};
设备节点中属性的顺序¶
设备节点中属性的首选顺序如下
“compatible”
“reg”
“ranges”
标准/通用属性(由通用绑定定义,例如不带厂商前缀)
厂商特定属性
“status”(如果适用),如果该属性之前有内容,则在其前面加一个空行
子节点,每个节点前面加一个空行
“status” 属性默认为 “okay”,因此可以省略。
上述排序遵循以下原则
最重要的属性位于节点开头:首先是 compatible,然后是与单元地址匹配的总线寻址。
每个节点中的通用属性位置相似。
Status 是最后的信息,用于注明该设备节点是否已完成(是否需要板级资源)。
每个组内的各个属性应按属性名称的自然排序顺序排列。
示例
/* SoC DTSI */
device_node: device-class@6789abc {
compatible = "vendor,device";
reg = <0x0 0x06789abc 0x0 0xa123>;
ranges = <0x0 0x0 0x06789abc 0x1000>;
#dma-cells = <1>;
clocks = <&clock_controller 0>, <&clock_controller 1>;
clock-names = "bus", "host";
#address-cells = <1>;
#size-cells = <1>;
vendor,custom-property = <2>;
status = "disabled";
child_node: child-class@100 {
reg = <0x100 0x200>;
/* ... */
};
};
/* Board DTS */
&device_node {
vdd-0v9-supply = <&board_vreg1>;
vdd-1v8-supply = <&board_vreg4>;
vdd-3v3-supply = <&board_vreg2>;
vdd-12v-supply = <&board_vreg3>;
status = "okay";
}
缩进与换行¶
使用 Linux 内核编码规范 中规定的缩进和换行方式。
具有多个单元的数组中的每个条目(例如带有两个 IO 地址的 “reg”)都应包含在 <> 中。
对于跨行的数组,首选在项目边界处分割,并将后续条目与第一行的左尖括号 < 对齐。通常避免分割单个项目,除非它们明显超过了行换行限制。
示例
thermal-sensor@c271000 {
compatible = "qcom,sm8550-tsens", "qcom,tsens-v2";
reg = <0x0 0x0c271000 0x0 0x1000>,
<0x0 0x0c222000 0x0 0x1000>;
/* Lines exceeding coding style line wrap limit: */
interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>,
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;
};
组织 DTSI 和 DTS¶
DTSI 和 DTS 文件应以代表硬件通用、可重用部分的方式进行组织。通常,这意味着将 DTSI 和 DTS 文件组织成几个文件
包含整个 SoC 内容的 DTSI,不含 SoC 上不存在的硬件节点。
如果适用:包含硬件通用或可重用部分的 DTSI,例如整个系统模组 (System-on-Module)。
代表板级的 DTS。
板上存在的硬件组件应放置在板级 DTS 中,而不是 SoC 或 SoM DTSI 中。一个部分例外是常见的外部参考 SoC 输入时钟,它可以编码为 SoC DTSI 中的 fixed-clock,其频率由每个板级 DTS 提供。