4. 设备树常用属性详解:compatible、reg、interrupts、status、clocks、resets 等核心属性的含义与用法

设备树(Device Tree)中的属性(Property)是描述硬件配置与连接关系的基本单元。每个设备节点通过一组标准属性向内核驱动传递关键信息,包括设备类型、寄存器地址、中断号、时钟源、复位信号以及当前状态等。本章将逐一剖析这些核心属性的语义、语法规则与典型用法,帮助你在编写 SPI 与 I2C 设备节点时做到准确无误。

学习提示: 设备树属性是驱动与硬件之间的“契约”。属性值写错或遗漏,轻则设备无法识别,重则系统崩溃。建议在阅读本章时对照实际开发板的手册或原理图进行验证。

4.1 compatible 属性:设备与驱动的匹配钥匙

compatible 是设备树中最关键的属性,它指定了设备所兼容的驱动名称列表。内核在启动时通过该属性查找匹配的驱动,并完成设备与驱动的绑定。

  • 格式: 字符串列表,按优先级从高到低排列。
  • 命名规范: "厂商,设备型号",例如 "ti,ads1115"、"microchip,mcp2515"。
  • 匹配机制: 内核遍历列表,依次尝试匹配驱动中的 of_match_table。
// SPI 设备节点示例
spi_device: ads1115@0 {
    compatible = "ti,ads1115", "ti,ads1015";  // 优先匹配 ads1115,其次 ads1015
    reg = <0>;
    spi-max-frequency = <1000000>;
};

// I2C 设备节点示例
i2c_device: mpu6050@68 {
    compatible = "invensense,mpu6050";
    reg = <0x68>;
};
最佳实践: 始终将最精确的兼容字符串放在第一位,通用兼容字符串放在后面。这样既能支持特定型号的优化驱动,又能回退到通用驱动。
compatible 属性匹配流程 设备节点 compatible = "ti,ads1115", "ti,ads1015" 内核匹配引擎 遍历 of_match_table 驱动 A:ads1115 匹配成功 → 绑定 驱动 B:ads1015 回退匹配 说明: 内核按列表顺序依次尝试匹配。若驱动 A 存在则直接绑定;若不存在,则尝试驱动 B。 这种机制保证了向后兼容性与驱动优先级控制。

4.2 reg 属性:地址空间与片选编号

reg 属性用于描述设备在总线上的地址信息。对于 SPI 设备,它表示片选(CS)编号;对于 I2C 设备,它表示从设备地址。该属性由一组或多组 <地址 长度> 对组成。

总线类型 reg 含义 典型格式 示例
SPI 片选编号(CS) reg = <cs_num>; reg = <0>; 表示 CS0
I2C 7 位从设备地址 reg = <address>; reg = <0x68>; 表示地址 0x68
内存映射设备 基地址 + 映射长度 reg = <base_addr length>; reg = <0x10000000 0x1000>;
// SPI 多片选示例
spi_controller: spi@ff040000 {
    compatible = "rockchip,rk3399-spi";
    reg = <0xff040000 0x1000>;  // SPI 控制器自身寄存器
    #address-cells = <1>;
    #size-cells = <0>;

    device0: flash@0 {
        compatible = "jedec,spi-nor";
        reg = <0>;  // 片选 0
        spi-max-frequency = <50000000>;
    };

    device1: sensor@1 {
        compatible = "bosch,bme280";
        reg = <1>;  // 片选 1
        spi-max-frequency = <10000000>;
    };
};

// I2C 多设备示例
i2c_controller: i2c@ff3c0000 {
    compatible = "rockchip,rk3399-i2c";
    reg = <0xff3c0000 0x1000>;
    #address-cells = <1>;
    #size-cells = <0>;

    rtc@51 {
        compatible = "nxp,pcf8563";
        reg = <0x51>;  // I2C 从地址 0x51
    };

    eeprom@50 {
        compatible = "atmel,24c02";
        reg = <0x50>;  // I2C 从地址 0x50
    };
};
常见错误: I2C 地址写错是最高频的故障原因。注意:设备树中 I2C 地址使用 7 位地址(不含读写位),且必须与数据手册中的从设备地址一致。例如,MPU6050 的 7 位地址为 0x68,而非 0xD0(8 位地址)。

4.3 interrupts 属性:中断信号的描述

interrupts 属性定义了设备的中断请求信号。它通常与 interrupt-parent 配合使用,后者指定中断控制器节点。中断描述符包含中断号、触发类型等信息。

  • 格式: interrupts = <中断号 触发类型>;
  • 触发类型宏:
    • IRQ_TYPE_EDGE_RISING (1) — 上升沿触发
    • IRQ_TYPE_EDGE_FALLING (2) — 下降沿触发
    • IRQ_TYPE_LEVEL_HIGH (4) — 高电平触发
    • IRQ_TYPE_LEVEL_LOW (8) — 低电平触发
// 带中断的 I2C 触摸屏节点
i2c@ff3c0000 {
    touchscreen@38 {
        compatible = "edt,edt-ft5406";
        reg = <0x38>;
        interrupt-parent = <&gpio3>;  // 中断连接到 gpio3 控制器
        interrupts = <14 IRQ_TYPE_EDGE_FALLING>;  // GPIO3_14,下降沿触发
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
    };
};

// 带中断的 SPI 网络控制器
spi@ff040000 {
    can@0 {
        compatible = "microchip,mcp2515";
        reg = <0>;
        interrupt-parent = <&gpio1>;
        interrupts = <7 IRQ_TYPE_LEVEL_LOW>;  // GPIO1_7,低电平触发
        clocks = <&can_osc>;
        spi-max-frequency = <10000000>;
    };
};
设备中断路由架构 外设设备 触摸屏 / CAN 控制器 中断请求 GPIO 控制器 interrupt-parent 中断号映射 中断控制器 GIC / INTC 关键属性说明: • interrupt-parent:指向中断控制器节点(如 gpio3、gic) • interrupts:包含中断号与触发类型,触发类型使用宏定义(如 IRQ_TYPE_EDGE_FALLING) • 中断号是相对于 interrupt-parent 的本地编号,不同控制器编号规则不同

4.4 status 属性:设备状态控制

status 属性用于控制设备节点的启用或禁用状态。它允许在不修改设备树源文件的情况下,通过设备树覆盖(overlay)或引导加载程序动态调整设备状态。

状态值 含义 使用场景
"okay" 设备启用,驱动正常加载 默认启用状态
"disabled" 设备禁用,驱动不加载 硬件未焊接、引脚冲突、调试时临时关闭
"reserved" 设备保留,不由操作系统管理 固件或安全世界使用
"fail" 设备检测失败 由引导程序自动设置
// 在 dtsi 文件中默认禁用,在具体板级 dts 中启用
// soc.dtsi
i2c2: i2c@ff3c0000 {
    compatible = "rockchip,rk3399-i2c";
    reg = <0xff3c0000 0x1000>;
    status = "disabled";  // 默认禁用
};

// board.dts
&i2c2 {
    status = "okay";  // 板级启用
    clock-frequency = <400000>;

    eeprom@50 {
        compatible = "atmel,24c02";
        reg = <0x50>;
        status = "okay";
    };
};
调试技巧: 当某个外设不工作时,首先检查 status 属性是否为 "okay"。很多情况下,设备树覆盖或引导参数可能意外地将设备设置为 "disabled"。使用 dtc -I dtb -O dts 反编译设备树二进制文件即可查看实际状态。

4.5 clocks 属性:时钟源与频率配置

clocks 属性指定设备使用的时钟源。它通过 phandle 引用时钟控制器节点,并可附带时钟索引或时钟 ID。时钟框架是 Linux 设备驱动中管理时钟频率与功耗的核心机制。

  • 格式: clocks = <&clock_controller clock_id>;
  • clock-names: 为每个时钟指定名称,便于驱动通过名称查找。
  • 常见场景: SPI 控制器需要总线时钟,I2C 控制器需要参考时钟,外设需要工作时钟。
// SPI 控制器时钟配置
spi1: spi@ff1d0000 {
    compatible = "rockchip,rk3399-spi";
    reg = <0xff1d0000 0x1000>;
    interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
    clock-names = "spi", "apb";
    status = "disabled";
};

// I2C 设备时钟配置
i2c0: i2c@ff3c0000 {
    compatible = "rockchip,rk3399-i2c";
    reg = <0xff3c0000 0x1000>;
    interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
    clock-names = "i2c", "apb";
    status = "disabled";
};

// 外设时钟示例:SPI 连接的 ADC 需要外部时钟
spi0: spi@ff040000 {
    adc@0 {
        compatible = "ti,ads1256";
        reg = <0>;
        clocks = <&adc_osc>;  // 外部晶振
        clock-names = "adc_clk";
        spi-max-frequency = <20000000>;
    };
};

4.6 resets 属性:复位信号管理

resets 属性用于描述设备的复位信号。与时钟类似,它通过 phandle 引用复位控制器,并指定复位 ID。复位信号在设备初始化、电源管理以及错误恢复中至关重要。

  • 格式: resets = <&reset_controller reset_id>;
  • reset-names: 为每个复位信号命名,便于驱动识别。
  • 典型用法: 在设备 probe 时释放复位,在 suspend 时断言复位以节省功耗。
// SPI 控制器复位配置
spi2: spi@ff1e0000 {
    compatible = "rockchip,rk3399-spi";
    reg = <0xff1e0000 0x1000>;
    interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
    clock-names = "spi", "apb";
    resets = <&cru SRST_SPI2>;
    reset-names = "spi";
    status = "disabled";
};

// I2C 控制器复位配置
i2c3: i2c@ff3d0000 {
    compatible = "rockchip,rk3399-i2c";
    reg = <0xff3d0000 0x1000>;
    interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
    clock-names = "i2c", "apb";
    resets = <&cru SRST_I2C3>;
    reset-names = "i2c";
    status = "disabled";
};
时钟与复位拓扑结构 CRU 时钟与复位单元 SCLK_SPI1 PCLK_SPI1 SRST_SPI1 SPI 控制器 clocks / resets I2C 控制器 clocks / resets 关键点: • clocks 属性引用 CRU 输出的时钟信号,驱动通过 clk_get 获取并控制频率 • resets 属性引用 CRU 输出的复位信号,驱动在 probe/suspend/resume 时管理复位状态

4.7 属性综合对比表

下表汇总了本章介绍的六个核心属性,方便你在编写设备节点时快速查阅。

属性名 功能 SPI 设备用法 I2C 设备用法 是否必需
compatible 驱动匹配标识 "厂商,型号" "厂商,型号" 是
reg 地址 / 片选 片选编号(0, 1, 2...) 7 位 I2C 地址 是
interrupts 中断描述 中断号 + 触发类型 中断号 + 触发类型 视设备而定
status 设备状态控制 "okay" / "disabled" "okay" / "disabled" 推荐
clocks 时钟源引用 <&cru SCLK_SPI> <&cru SCLK_I2C> 视设备而定
resets 复位信号引用 <&cru SRST_SPI> <&cru SRST_I2C> 视设备而定
核心原则: 每个设备节点至少需要 compatible 和 reg 两个属性才能被内核正确识别。其他属性根据硬件设计需求选择性添加。在编写节点时,建议参考同一 SoC 平台的其他设备节点写法,保持风格一致。

4.8 本章小结

本章详细讲解了设备树中六个核心属性的语义与用法:

  • compatible — 设备与驱动的匹配钥匙,遵循“厂商,型号”命名规范。
  • reg — 地址空间描述,SPI 用片选编号,I2C 用从设备地址。
  • interrupts — 中断信号描述,需配合 interrupt-parent 使用。
  • status — 设备状态控制,支持 okay/disabled/reserved/fail。
  • clocks — 时钟源引用,通过 phandle 指向 CRU 或外部晶振。
  • resets — 复位信号引用,用于设备初始化与电源管理。