4. 设备树绑定文档:如何阅读内核 Documentation/devicetree/bindings 中的绑定文档

设备树绑定文档(Binding Document)是内核源码树中 Documentation/devicetree/bindings/ 目录下的一组 YAML 或文本文件。它们定义了每个硬件设备节点在设备树中必须遵循的属性和结构规范。对于驱动开发者而言,绑定文档是连接硬件手册与设备树源文件的“契约”,也是编写设备树覆盖(DTSO)时的权威参考。

核心认知:绑定文档不是内核代码,而是规范。它告诉设备树编写者“这个节点必须有哪些属性、属性值类型是什么、子节点如何组织”。驱动代码则按照这个规范来解析设备树。

4.1 绑定文档的目录结构与文件格式

绑定文档按硬件总线/类型组织在 Documentation/devicetree/bindings/ 下,常见子目录包括:

目录路径 包含的绑定类型 典型文件示例
arm/ ARM 架构 SoC 级绑定 arm,vexpress.yaml
clock/ 时钟控制器、时钟源 clk-imx8mm.yaml
gpio/ GPIO 控制器与 GPIO 按键 gpio.txt、gpio-keys.yaml
i2c/ I2C 控制器与从设备 i2c-imx.yaml
pinctrl/ 引脚复用与配置 pinctrl-bindings.txt
regulator/ 电压/电流调节器 fixed-regulator.yaml
sound/ 音频编解码器、DAI 链路 simple-audio-card.yaml
spi/ SPI 控制器与从设备 spi-controller.yaml

文件格式分为两种:

  • 传统 .txt 格式:纯文本描述,使用缩进和列表说明属性。多见于较老或未迁移的绑定。
  • 现代 .yaml 格式:使用 JSON Schema 子集(DT Schema)描述,支持自动化校验。新提交的绑定必须使用 YAML 格式。
实战建议:优先阅读 YAML 格式的绑定文档,因为它结构清晰、类型明确,且可以被 dt-validate 工具直接用于检查设备树源文件的正确性。

4.2 绑定文档的核心结构(以 YAML 为例)

一个典型的 YAML 绑定文档包含以下顶层字段。我们以 Documentation/devicetree/bindings/gpio/gpio-leds.yaml 为例进行拆解:

# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/gpio-leds.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: GPIO-based LED Device Tree Bindings

maintainers:
  - Jacek Anaszewski <jacek.anaszewski@gmail.com>
  - Pavel Machek <pavel@ucw.cz>

description: |
  This binding describes LEDs that are connected to GPIO lines.
  Each LED is represented as a sub-node of the GPIO LED controller node.

properties:
  compatible:
    const: gpio-leds

patternProperties:
  "^led-[0-9a-f]+$":
    type: object
    description: Represents a single LED connected to a GPIO line.
    properties:
      gpios:
        maxItems: 1
        description: GPIO specifier for the LED.
      label:
        $ref: "/schemas/types.yaml#/definitions/string"
        description: Name of the LED as visible in sysfs.
      linux,default-trigger:
        $ref: "/schemas/types.yaml#/definitions/string"
        description: Default trigger for the LED (e.g., "heartbeat").
      default-state:
        enum: [ on, off, keep ]
        description: Initial state of the LED.
    required:
      - gpios
    additionalProperties: false

required:
  - compatible

additionalProperties: false
...

各字段含义如下表:

字段 作用 说明
$id 唯一标识符 该绑定文档的 URI,用于引用和校验
title 简短标题 描述该绑定适用于哪类设备
maintainers 维护者列表 当绑定有疑问时可联系的人员
description 详细描述 解释该绑定的使用场景和约束
properties 节点级属性定义 定义 compatible、reg 等顶层属性
patternProperties 子节点模式定义 用正则表达式匹配子节点名称,定义其属性和约束
required 必填属性列表 缺少这些属性会导致设备树校验失败
additionalProperties 额外属性控制 false 表示不允许出现未定义的属性
常见陷阱:不要忽略 additionalProperties: false。如果绑定中声明了该约束,那么设备树节点中任何未在绑定中定义的属性都会导致 dt-validate 报错。在编写覆盖文件时,务必确保所有属性都在绑定文档的允许范围内。

4.3 如何从绑定文档中提取关键信息

阅读绑定文档时,按以下步骤提取驱动和设备树覆盖所需的关键信息:

  1. 确定 compatible 字符串:在 properties 或 patternProperties 中找到 compatible 的定义。这是驱动匹配设备树节点的唯一标识。
  2. 识别必填属性:查看 required 列表,这些属性在设备树节点中必须出现。
  3. 理解可选属性:查看 properties 中的其他字段,了解哪些属性可以用于配置驱动行为。
  4. 检查子节点结构:如果绑定定义了 patternProperties 或 properties 中包含 type: object,说明该节点下可以有子节点,需要进一步阅读子节点的属性定义。
  5. 注意类型约束:YAML 绑定中会使用 $ref 引用类型定义(如 uint32、string、phandle),确保属性值类型正确。
实战案例:假设你要为 I2C 温度传感器添加设备树覆盖。首先找到 Documentation/devicetree/bindings/i2c/ 下对应的绑定文件(如 lm75.yaml),提取 compatible: "national,lm75",确认 reg 属性为必填且类型为 uint32,然后编写覆盖节点。

4.4 绑定文档阅读流程示意图

下图展示了从绑定文档到设备树覆盖文件的完整信息提取流程:

绑定文档阅读与信息提取流程 绑定文档阅读与信息提取流程 打开绑定文档 定位 compatible 字符串 提取 required 必填属性 分析可选属性与类型 编写设备树覆盖文件 关键检查点 • compatible 是否完全匹配? • 必填属性是否都已提供? • 属性值类型是否正确? • 子节点命名是否符合模式? • 是否有未定义的额外属性?

4.5 传统 .txt 绑定文档的阅读要点

虽然 YAML 是趋势,但内核中仍有大量 .txt 格式的绑定文档。阅读时注意以下特征:

  • 节标题:通常以 == 或 --- 分隔不同设备的绑定。
  • 属性列表:使用缩进或 - 列出属性名和描述。
  • 必填/可选标记:有些文档用 Required properties: 和 Optional properties: 明确区分。
  • 示例节点:文档末尾通常包含一个完整的设备树节点示例,这是最直接的参考。
对比总结:YAML 绑定文档的优势在于机器可读、类型安全、支持自动化校验;.txt 绑定文档的优势在于人类可读、注释自由。在编写设备树覆盖时,优先参考 YAML 绑定,若只有 .txt 绑定,则仔细阅读示例节点和属性描述。

4.6 绑定文档与设备树覆盖的对应关系

下面以 GPIO 按键为例,展示绑定文档中的定义如何映射到实际的设备树覆盖节点:

绑定文档定义(YAML) 设备树覆盖节点 说明
compatible: "gpio-keys" compatible = "gpio-keys"; 驱动匹配标识
required: [ "gpios" ] gpios = &gpio1 15 GPIO_ACTIVE_LOW; 必填属性,指定 GPIO 引脚
label: { type: string } label = "power-key"; 可选属性,用于 sysfs 标识
linux,code: { $ref: "/schemas/types.yaml#/definitions/uint32" } linux,code = <KEY_POWER>; 可选属性,定义按键上报的键码
patternProperties: "^button-.*$" button-power { ... } 子节点命名必须匹配正则模式
常见错误:在设备树覆盖中使用了绑定文档未定义的属性。例如,在 GPIO 按键节点中添加 interrupt-parent 属性,但绑定文档中并未声明该属性,且 additionalProperties: false,这会导致校验失败。正确的做法是使用绑定文档中定义的属性,或者确认该属性是否被父节点或框架隐式支持。

4.7 使用 dt-validate 验证绑定合规性

内核提供了 dt-validate 工具,可以基于 YAML 绑定文档自动检查设备树源文件的合规性。使用方法如下:

# 安装 dt-schema 工具(Python 包)
pip install dtschema

# 验证单个设备树文件
dt-validate -s Documentation/devicetree/bindings/ my-board.dts

# 验证设备树覆盖文件
dt-validate -s Documentation/devicetree/bindings/ my-overlay.dts

# 只检查特定绑定
dt-validate -s Documentation/devicetree/bindings/gpio/gpio-keys.yaml my-overlay.dts

输出示例:

my-overlay.dts:10.3-18.5: 'button-power' does not match any of the regexes: '^button-.*$'
  from schema $id: http://devicetree.org/schemas/gpio/gpio-keys.yaml#

这个错误表明子节点名称 button-power 不匹配绑定中定义的 ^button-.*$ 模式。修正方法是将节点名改为 button-power 或符合模式的名称。

工作流建议:在提交设备树覆盖文件到内核或项目仓库之前,始终运行 dt-validate 进行合规性检查。这可以避免因绑定不匹配导致的驱动加载失败或内核警告。

4.8 本章小结

设备树绑定文档是驱动开发者与设备树编写者之间的“契约”。掌握以下要点即可高效阅读和使用绑定文档:

  • 优先阅读 YAML 格式的绑定文档,利用其结构化定义快速提取 compatible、required 和属性类型。
  • 对于 .txt 格式的绑定文档,重点关注示例节点和必填/可选属性列表。
  • 在编写设备树覆盖时,确保所有属性都在绑定文档的允许范围内,避免使用未定义的属性。
  • 使用 dt-validate 工具进行自动化校验,确保设备树覆盖文件与绑定文档完全一致。