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 中调用的
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 控制器编写设备树节点,可以按以下步骤查找绑定文档:
- 确定 compatible 字符串:查看驱动源码或芯片手册,找到 compatible 值,例如
"fsl,imx6q-i2c"。 - 搜索绑定文档:在
Documentation/devicetree/bindings/目录下搜索该字符串:
grep -r "fsl,imx6q-i2c" Documentation/devicetree/bindings/
# 输出示例:
# Documentation/devicetree/bindings/i2c/i2c-imx.yaml: - fsl,imx6q-i2c
- 打开绑定文档:直接查看
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 用法 | 能运行校验并解读错误信息 |