4. 设备树绑定文档:格式、作用与查阅方法

设备树绑定(Device Tree Binding)是连接硬件描述与驱动代码的“契约文档”。它定义了设备树节点中哪些属性是必需的、哪些是可选的、各属性的数据类型与含义,以及设备与驱动的匹配方式。没有绑定文档,设备树就成了无源之水——内核无法正确解析节点,驱动也无法可靠地获取硬件配置。

核心观点:绑定文档是设备树与驱动之间的“API 规范”。驱动开发者通过绑定文档知道“设备树里该写什么”,设备树编写者通过绑定文档知道“驱动需要什么”。双方遵循同一份文档,才能保证硬件配置正确传递。

4.1 绑定文档的格式与结构

内核中的设备树绑定文档采用 YAML 格式(文件后缀为 .yaml),遵循 json-schema 规范。这种格式既便于人类阅读,也支持自动化校验工具(如 dt-validate)对设备树源文件进行静态检查。

一个典型的绑定文档包含以下核心部分:

章节 作用 示例内容
$id 绑定文档的唯一标识符(URL) http://devicetree.org/schemas/i2c/i2c-imx.yaml
title 设备或控制器名称 NXP i.MX I2C Controller
maintainers 维护者列表(邮箱) ["Peng Fan "]
properties 定义节点中所有合法属性 compatible、reg、clocks、interrupts
required 列出必须存在的属性列表 ["compatible", "reg", "clocks"]
additionalProperties 是否允许未定义的额外属性 false(禁止额外属性)
examples 一个或多个完整的设备树节点示例 包含 i2c@... 节点的 DTS 片段
绑定文档的作用:
  • 规范硬件描述:确保同一类设备在不同 SoC 上的设备树写法一致。
  • 驱动开发参考:驱动代码通过 of_ 系列 API 读取的属性名、类型、含义全部来自绑定文档。
  • 自动化校验:内核构建系统可调用 dt_binding_check 目标,自动检查 DTS 是否符合绑定文档。
  • 社区评审依据:提交新设备树节点或驱动时,Reviewer 首先检查是否引用了正确的绑定文档。

4.2 绑定文档与驱动 probe 流程的关系

绑定文档并不直接参与代码执行,但它决定了驱动 probe 函数中能获取到哪些信息。下图展示了绑定文档、设备树节点与驱动 probe 三者之间的数据流:

绑定文档 → 设备树 → 驱动 probe 数据流 绑定文档 i2c-imx.yaml 定义属性名/类型/必选 约束 设备树节点 i2c@30a20000 compatible / reg / clocks 解析 驱动 probe probe() 函数 of_i2c_get_board_info() 关键流程说明 1. 绑定文档定义属性规范(如 compatible 必须为 "fsl,imx6q-i2c") 2. 设备树节点按绑定文档编写,提供具体硬件配置值 3. 驱动 probe 通过 of_ 系列 API 读取节点属性,获取寄存器地址、中断号、时钟频率等 自动化校验工具链 dt-validate 工具读取 .yaml 绑定文档 → 校验 .dts 文件 → 报告属性缺失/类型错误/值越界 内核构建命令:make dt_binding_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/i2c/i2c-imx.yaml
常见误区:初学者常以为设备树节点中的属性可以随意命名。实际上,驱动 probe 中调用的 of_property_read_u32() 等 API 所读取的属性名,必须与绑定文档中定义的名称完全一致。属性名拼写错误是导致 probe 失败的最常见原因之一。

4.3 如何查阅内核中的绑定文档

内核源码树中的绑定文档统一存放在 Documentation/devicetree/bindings/ 目录下,按子系统分类组织。以下是几种常用的查阅方法:

4.3.1 本地源码目录结构

绑定文档的目录组织与 Linux 内核子系统一一对应:

Documentation/devicetree/bindings/
├── arm/                  # ARM 架构相关
├── clock/                # 时钟控制器
├── gpio/                 # GPIO 控制器
├── i2c/                  # I2C 控制器与设备
├── interrupt-controller/ # 中断控制器
├── media/                # 多媒体设备(摄像头、显示等)
├── memory/               # 内存控制器
├── mfd/                  # 多功能设备
├── mmc/                  # MMC/SD 卡控制器
├── net/                  # 网络设备
├── pinctrl/              # 引脚控制
├── pwm/                  # PWM 控制器
├── regulator/            # 电压调节器
├── serial/               # 串口(UART)
├── sound/                # 音频设备
├── spi/                  # SPI 控制器
├── timer/                # 定时器
├── usb/                  # USB 控制器
└── vendor-prefixes.yaml  # 厂商前缀列表(如 fsl, imx, ti, stm 等)

4.3.2 查找特定设备的绑定文档

假设你要为 NXP i.MX6Q 的 I2C 控制器编写设备树节点,可以按以下步骤查找绑定文档:

  1. 确定 compatible 字符串:查看驱动源码或芯片手册,找到 compatible 值,例如 "fsl,imx6q-i2c"。
  2. 搜索绑定文档:在 Documentation/devicetree/bindings/ 目录下搜索该字符串:
grep -r "fsl,imx6q-i2c" Documentation/devicetree/bindings/
# 输出示例:
# Documentation/devicetree/bindings/i2c/i2c-imx.yaml:          - fsl,imx6q-i2c
  1. 打开绑定文档:直接查看 i2c-imx.yaml 文件,获取完整的属性定义。

4.3.3 在线查阅(无需下载内核源码)

如果你没有本地内核源码,可以通过以下在线资源查阅绑定文档:

资源 URL 特点
Linux 内核官方源码 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings 最新主线版本,支持直接浏览
devicetree.org 规范 https://devicetree-specification.readthedocs.io/ 设备树通用规范,非特定厂商
芯片厂商 SDK NXP / TI / ST 等厂商的 Linux BSP 包 包含厂商定制的绑定文档

4.4 绑定文档实战:解析一个 I2C 设备绑定

下面以 i2c-imx.yaml 为例,展示如何从绑定文档中提取关键信息,并编写对应的设备树节点。

4.4.1 绑定文档关键片段

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

title: NXP i.MX I2C Controller

maintainers:
  - Peng Fan <peng.fan@nxp.com>

properties:
  compatible:
    oneOf:
      - items:
          - enum:
              - fsl,imx1-i2c
              - fsl,imx21-i2c
              - fsl,imx6q-i2c
              - fsl,imx7d-i2c
      - items:
          - const: fsl,imx6ul-i2c
          - const: fsl,imx21-i2c

  reg:
    maxItems: 1

  interrupts:
    maxItems: 1

  clocks:
    maxItems: 1

  clock-names:
    items:
      - const: ipg

  fsl,clk-div:
    $ref: /schemas/types.yaml#/definitions/uint32
    description: I2C 时钟分频值(可选)

required:
  - compatible
  - reg
  - interrupts
  - clocks

additionalProperties: false

examples:
  - |
    i2c@30a20000 {
        compatible = "fsl,imx6q-i2c";
        reg = <0x30a20000 0x10000>;
        interrupts = <0 38 4>;
        clocks = <&clks IMX6Q_CLK_I2C1>;
        clock-names = "ipg";
        fsl,clk-div = <1>;
        #address-cells = <1>;
        #size-cells = <0>;
    };

4.4.2 从绑定文档到设备树节点

根据上述绑定文档,我们可以提取以下关键信息:

属性 类型 必需 说明
compatible 字符串(枚举) 是 必须为 fsl,imx6q-i2c 等预定义值之一
reg 32 位整数对 是 基地址 + 长度,如 <0x30a20000 0x10000>
interrupts 中断描述 是 中断号、触发类型等
clocks phandle 是 时钟源引用
clock-names 字符串 否(但建议提供) 固定为 "ipg"
fsl,clk-div 32 位整数 否 可选时钟分频值
实战要点:
  • compatible 必须精确匹配:驱动通过 of_match_table 匹配 compatible 字符串,多一个空格或少一个字符都会导致 probe 失败。
  • reg 地址范围不能重叠:同一总线上的设备 reg 地址必须唯一,否则内核会报地址冲突。
  • clocks 与 clock-names 对应:如果绑定文档定义了 clock-names,则必须按顺序提供对应的 clocks phandle。
  • additionalProperties: false 表示该节点不允许出现未定义的属性,添加自定义属性会导致校验失败。

4.5 绑定文档的校验与调试

编写完设备树节点后,可以使用内核提供的校验工具验证其是否符合绑定文档:

# 安装 dt-validate 工具(通常在内核源码目录下)
make dt_binding_check

# 校验单个 DTS 文件
make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/i2c/i2c-imx.yaml

# 如果校验通过,无输出;如果失败,会显示具体错误:
# <stdin>:30.24-31.8: ERROR: node@30a20000: 'compatible' is a required property
调试建议:如果设备无法 probe,首先检查内核日志中是否有与设备树相关的错误:dmesg | grep -i "of\|dt\|device tree"。常见错误包括:OF: fsl,imx6q-i2c: missing 'compatible' property、i2c-imx 30a20000.i2c: failed to get clock 等。这些错误通常直接指向绑定文档中定义的必需属性缺失。

4.6 本章小结

设备树绑定文档是驱动开发中不可或缺的参考手册。它定义了设备树节点的“语法”和“语义”,确保设备树编写者与驱动开发者使用同一种语言沟通。掌握绑定文档的格式、查阅方法和校验工具,是写出正确、可维护的设备树节点的前提。

技能点 掌握程度 对应操作
绑定文档格式 理解 YAML 结构 能读懂 properties / required / examples 等章节
绑定文档查阅 熟练使用 grep 和在线资源 能快速找到特定设备的绑定文档
属性提取 能从绑定文档中提取必需属性和可选属性 能根据绑定文档编写正确的设备树节点
校验工具 了解 dt_binding_check 用法 能运行校验并解读错误信息