3. 设备树常用属性详解

设备树(Device Tree)中的属性(property)是描述硬件配置与连接关系的基本单元。每个节点通过一组标准化的属性向内核驱动传递关键信息,包括设备类型、地址映射、中断路由、电源状态及时钟依赖等。本章将逐一剖析最常用的核心属性,并结合实际案例说明其使用规范与常见陷阱。

学习提示: 设备树属性是驱动与硬件之间的“契约”。理解每个属性的语义与约束,是编写正确设备树文件的前提。建议在阅读本节时,对照实际开发板的手册或内核源码中的设备树绑定文档(Documentation/devicetree/bindings/)进行验证。

3.1 compatible 属性:设备识别与驱动匹配

compatible 是设备树中最关键的属性,它定义了设备与驱动之间的匹配关系。该属性是一个字符串列表,内核通过该列表查找对应的平台驱动(platform driver)。

  • 格式: "厂商,型号" 或 "通用型号",优先使用厂商前缀以避免命名冲突。
  • 匹配顺序: 内核按照字符串在列表中的顺序依次尝试匹配,第一个匹配成功的驱动将被绑定。
  • 回退机制: 通常将最具体的型号放在最前面,通用型号放在后面,以实现兼容性。
// 示例:I2C控制器节点
i2c@1c2ac00 {
    compatible = "allwinner,sun8i-h3-i2c", "allwinner,sun6i-a31-i2c";
    reg = <0x01c2ac00 0x400>;
    interrupts = <0 6 4>;
    status = "okay";
};
关键点: 驱动匹配时,内核会遍历 of_match_table 中的 .compatible 字符串,与设备树节点中的 compatible 列表逐一比对。因此,驱动中必须包含与设备树完全一致的字符串。
compatible 属性匹配流程 设备树节点 compatible = "vendor,device-v2", "vendor,device-v1" 内核匹配引擎 遍历 of_match_table 逐字符串比对 平台驱动 probe() 调用 匹配规则说明 • 优先匹配 "vendor,device-v2",若驱动支持则绑定 • 若驱动不支持 v2,则回退匹配 "vendor,device-v1"

3.2 reg 属性:地址空间与内存映射

reg 属性用于描述设备在系统总线上的地址范围,通常由一组或多组 (地址, 长度) 对组成。其具体含义由父节点的 #address-cells 和 #size-cells 属性决定。

属性 含义 典型值
#address-cells 地址字段占用的 32 位单元数 1(32位地址)或 2(64位地址)
#size-cells 长度字段占用的 32 位单元数 1(32位长度)或 2(64位长度)
reg 地址与长度交替排列的数组 <0x10000000 0x1000>
// 示例:SPI控制器,64位地址总线
spi@0x30000000 {
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <0x30000000 0x1000>;  // 基地址0x30000000,范围4KB
    ...
    
    // 子设备(SPI从设备)
    device@0 {
        reg = <0>;  // 片选线0,无长度字段(size-cells=0)
        compatible = "some,spi-device";
    };
};
常见错误: 当父节点 #address-cells 或 #size-cells 设置错误时,内核解析 reg 会得到错误的地址或长度,导致驱动访问错误的物理地址。务必与硬件手册中的地址总线宽度保持一致。
reg 属性地址解析示例 父节点(总线) #address-cells = 2 #size-cells = 1 子节点(设备) reg = <0 0x10000000 0x1000> 内核解析结果 地址:0x10000000 长度:0x1000 (4KB) 解析规则 • 地址占用 2 个单元(高32位 + 低32位),即 0x00000000 0x10000000 → 0x10000000 • 长度占用 1 个单元,即 0x1000

3.3 interrupts 属性:中断信号描述

interrupts 属性用于描述设备产生的中断信号,其格式由父节点的 #interrupt-cells 属性定义。常见的中断控制器(如 GIC)使用 3 个 cell 来描述中断:中断类型、中断号、触发方式。

中断类型(cell 1) 含义 典型值
0 SPI(共享外设中断) 用于外设共享中断
1 PPI(私有外设中断) 用于 CPU 私有中断
2 虚拟中断 用于虚拟化场景
// 示例:UART设备,使用GIC中断控制器
uart@1c28000 {
    compatible = "ns16550a";
    reg = <0x01c28000 0x400>;
    interrupts = <0 1 4>;  // SPI类型,中断号1,高电平触发
    interrupt-parent = <&gic>;  // 指定中断控制器
    status = "okay";
};
注意: interrupt-parent 属性用于指定该设备连接的中断控制器节点。如果未显式指定,则默认继承父节点的中断控制器。在多层中断控制器级联时,务必明确指定。
中断属性连接关系 设备节点 interrupts = <0 1 4> interrupt-parent 中断控制器 (GIC) #interrupt-cells = 3 中断号映射 CPU 内核 中断处理 中断属性解析 • cell 1 (0): SPI 类型,共享外设中断 • cell 2 (1): 中断号,由中断控制器分配 • cell 3 (4): 触发方式,4 表示高电平触发

3.4 status 属性:设备状态控制

status 属性用于控制设备是否启用。该属性在设备树 overlay 中尤为重要,因为 overlay 常通过修改 status 来动态启用或禁用设备。

状态值 含义 使用场景
"okay" 设备已启用且正常工作 默认启用状态
"disabled" 设备被禁用,驱动不会 probe 硬件存在但未使用,或 overlay 启用前
"reserved" 设备保留,不由本系统管理 固件或安全世界占用
"fail" 设备检测失败 由 bootloader 设置,内核跳过
// 基础设备树中禁用,overlay 中启用
// 基础 DTS
&uart1 {
    status = "disabled";
};

// Overlay DTSO
&uart1 {
    status = "okay";
    pinctrl-0 = <&uart1_pins>;
};
最佳实践: 在基础设备树中,将所有未使用的外设默认设为 disabled,然后在 overlay 或板级配置中按需启用。这样可以避免未使用的外设占用中断、时钟等资源。

3.5 clocks 属性:时钟依赖与频率配置

clocks 属性用于指定设备所需的时钟源,通常与 clock-names 配合使用。时钟框架是 Linux 设备驱动中管理时钟频率与使能的核心机制。

  • clocks: 一个 phandle 列表,指向时钟提供者节点。
  • clock-names: 可选的字符串列表,为每个时钟指定名称,便于驱动通过名称查找。
  • clock-frequency: 可选属性,直接指定时钟频率(用于固定频率时钟)。
// 示例:以太网控制器时钟配置
ethernet@1c30000 {
    compatible = "allwinner,sun8i-h3-emac";
    reg = <0x01c30000 0x1000>;
    interrupts = <0 82 4>;
    clocks = <&ccu CLK_BUS_EMAC>, <&ccu CLK_EMAC>;
    clock-names = "bus", "mac";
    status = "okay";
};
驱动开发提示: 在驱动中通过 devm_clk_get(dev, "bus") 获取名为 "bus" 的时钟,然后调用 clk_prepare_enable() 使能时钟。时钟框架会自动处理时钟树的上游使能。
clocks 属性与时钟树关系 时钟控制器 (CCU) CLK_BUS_EMAC CLK_EMAC 以太网控制器 clocks = <&ccu ...> clock-names = "bus","mac" 驱动 clk_get("bus") clk_get("mac") 时钟使能流程 驱动通过 clock-names 获取时钟句柄 → clk_prepare_enable() 使能 → 时钟树向上游传递使能请求

3.6 其他常用属性速查

属性名 作用 典型示例
pinctrl-0 / pinctrl-names 引脚复用配置 pinctrl-0 = <&uart0_pins>;
dmas / dma-names DMA 通道配置 dmas = <&dma 2>;
power-domains 电源域控制 power-domains = <&pd_core>;
resets 复位信号控制 resets = <&rst 5>;
phy-handle PHY 设备连接 phy-handle = <&phy0>;
memory-region 预留内存区域 memory-region = <&reserved_mem>;
避坑指南: 使用 pinctrl 属性时,必须确保引脚配置节点中的 pins、function、bias-pull-up 等子属性与 SoC 手册完全一致。错误的引脚复用配置可能导致外设无法正常工作,甚至损坏硬件。

3.7 属性组合使用案例:完整设备节点

以下是一个完整的 SPI 控制器节点,展示了多个核心属性的组合使用方式:

spi@1c68000 {
    compatible = "allwinner,sun8i-h3-spi", "allwinner,sun6i-a31-spi";
    reg = <0x01c68000 0x1000>;
    interrupts = <0 65 4>;
    clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
    clock-names = "bus", "mod";
    resets = <&ccu RST_BUS_SPI0>;
    pinctrl-0 = <&spi0_pins>;
    pinctrl-names = "default";
    status = "disabled";  // 默认禁用,由 overlay 启用
    
    #address-cells = <1>;
    #size-cells = <0>;
    
    flash@0 {
        compatible = "jedec,spi-nor";
        reg = <0>;
        spi-max-frequency = <50000000>;
        status = "okay";
    };
};
总结: 设备树属性是驱动与硬件之间的桥梁。掌握 compatible(驱动匹配)、reg(地址映射)、interrupts(中断路由)、status(设备状态)和 clocks(时钟依赖)这五大核心属性,是编写正确设备树文件的基础。在后续章节中,我们将基于这些属性,深入讲解设备树 overlay 的动态配置技术。