设计和编写 Devicetree 绑定的应做事项与禁止事项

这是关于绑定设计(binding design)的常见评审意见列表。每条规则都有例外,并且绑定设计中存在许多灰色地带。

有关补丁相关的指南,请参见 提交 Devicetree (DT) 绑定补丁

总体设计

  • 应(DO)尝试使绑定保持完整,即使驱动程序不支持某些功能。例如,如果设备具有中断,则应包含 ‘interrupts’ 属性,即使驱动程序仅工作在轮询模式下。

  • 切勿(DON’T)在绑定中提及 Linux 或“设备驱动程序”。绑定应基于硬件本身具备的功能,而不是操作系统和驱动程序当前支持的功能。

  • 应(DO)使用与设备类别相匹配的节点名称。DT 规范中定义了许多标准名称。如果没有,请考虑添加一个。

  • 应(DO)检查示例是否与文档相匹配,特别是在进行评审修改之后。

  • 切勿(DON’T)仅仅为了实例化驱动程序而创建节点。多功能设备(Multi-function devices)仅在子节点拥有自己的 DT 资源时才需要子节点。单个节点可以作为多个提供者(例如时钟和复位)。

  • 切勿(DON’T)将设备节点名称视为稳定的 ABI,而应使用 phandle 或 compatible 来查找同级设备。例外:如果绑定中明确记录了某个给定设备的子节点可以作为 ABI 处理,则可以视为 ABI。

  • 切勿(DON’T)在没有特定 compatible 字符串的情况下单独使用 ‘syscon’。‘syscon’ 硬件块应具有足够独特的 compatible 字符串,以便(至少)推断整个块的寄存器布局。

  • 切勿(DON’T)对复杂的设备使用 ‘simple-mfd’ compatible,因为其子节点依赖于父节点的某些资源。同理,不应将 ‘simple-bus’ 用于复杂的总线,甚至带有 ‘regs’ 属性就意味着该设备不是一个简单的总线。

属性

  • 应(DO)使 ‘compatible’ 属性具有具体性。

    • 切勿(DON’T)在 compatible 字符串中使用通配符或设备系列名称。

    • 当设备与以前的实现相同或为其超集时,应(DO)使用回退(fallback)compatible。回退 compatible 尤其适用于共享编程接口或能够发现变体的情况。

    • 如果软件无法利用此类回退来匹配和绑定到设备并仍能正常运行,则切勿(DON’T)添加伪造的回退 compatible。

    • 应(DO)使用提交信息(commit message)来解释为什么某些设备在 diff 中看起来是兼容的(例如属性使用上没有差异、软件处理方式相同),但在绑定中却没有被设为兼容。

    • 如果有新功能或错误(bug),应(DO)添加新的 compatible。

    • 所有 SoC 设备都应(DO)使用 SoC 特定的 compatible,并在适当时在其后跟一个回退(fallback)compatible。对于回退项,也首选 SoC 特定的 compatible。

    • 切勿(DON’T)使用总线后缀来编码设备正在使用的接口类型。父总线节点已经隐含了该接口。如果设备不可能属于其他任何类型,则切勿添加设备类型。

  • 设备特定的属性名称应(DO)使用厂商前缀。请考虑这些属性是否可以跨同类设备通用。请检查针对类似设备的现有其他绑定。

  • 切勿(DON’T)重新定义通用属性。只需引用其定义并定义该设备特定的约束条件。

  • 切勿(DON’T)为了避开特定的 compatible 而添加属性。如果属性可以由 compatible 暗示(推导)得出,则切勿添加它们。

  • 对于带有科学单位的属性,应(DO)使用通用的属性单位后缀。推荐的后缀列在 https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/property-units.yaml

  • 应(DO)根据约束条件来定义属性。有多少个条目?有哪些可能的值?顺序是什么?所有这些约束条件同时也代表了 ABI。

  • 切勿(DON’T)进行破坏 ABI 的更改,除非有明确且详细的理由说明为什么必须进行这些更改以及它们的影响。ABI 的影响超出了 Linux 内核的范围,因为它还涵盖其他开源上游项目。

典型案例与注意事项

  • 诸如 clocks/dmas/interrupts/resets 之类的 Phandle 条目应始终显式排序。如果存在多个 phandle,请包含 {clock,dma,interrupt,reset}-names。使用时,这两个字段都需要具有相同的约束条件(例如项列表)。

  • 对于 {clock,dma,interrupt,reset}-names 中使用的名称,不要添加任何后缀,例如:使用 “tx” 而不是 “txirq”(针对中断)。

  • 没有 schema 类型的属性(例如没有标准后缀或未由 schema 定义的属性)需要显式指定类型,即使这是一个枚举(enum)类型也是如此。

  • 如果 schema 包含了其他 schema(例如 /schemas/i2c/i2c-controller.yaml),请使用 “unevaluatedProperties:false”。在其他情况下,通常使用 “additionalProperties:false”。

  • 对于更大设备的子块/组件(例如 SoC 块),应使用基于设备的 compatible(例如基于 SoC 的 compatible),而不是对该组件使用自定义的版本控制。例如,使用 “vendor,soc1234-i2c” 而不是 “vendor,i2c-v2”。

  • “syscon” 不是一个通用属性。请使用厂商和类型,例如 “vendor,power-manager-syscon”。

  • 不要添加实例索引(ID)属性或自定义的 OF 别名。如果设备具有不同的编程模型,它们可能需要不同的 compatible。如果此类设备以不同的方式使用其他设备(例如它们以不同的方式对 phy 进行编程),请使用 cell/phandle 参数。

  • 绑定文件的命名应类似于 compatible: vendor,device.yaml。如果在绑定中有多个 compatible,请使用其中一个回退项或更通用的名称,但仍需符合 compatible 的命名风格。

板级/SoC .dts 文件

  • 应(DO)将所有 MMIO 设备放在总线节点下,而不是放在顶层。

  • 应(DO)使用非空的 ‘ranges’ 来限制子总线/设备的大小。64 位平台不需要所有设备都具有 64 位的地址和大小。