2. 设备树基础:设备树语法、节点与属性、reg属性、compatible属性、中断与GPIO描述

设备树(Device Tree,DT)是嵌入式Linux系统中用于描述硬件拓扑结构和资源配置的核心机制。在ALSA音频驱动的上下文中,设备树负责向内核传递声卡硬件信息,包括编解码器型号、I2C/SPI总线地址、DMA通道、中断号以及GPIO控制引脚。本章将系统讲解设备树的语法规则、关键属性以及如何在音频设备节点中描述中断和GPIO资源。

学习目标:掌握设备树节点与属性的基本语法;理解 reg、compatible、interrupts、gpios 等核心属性的含义与用法;能够独立编写或修改音频编解码器设备树节点。

2.1 设备树语法基础

设备树源文件(.dts)采用树形结构描述硬件,每个硬件设备对应一个节点(node),节点内包含若干属性(property)。节点从根节点 / 开始,通过路径唯一标识。

2.1.1 节点定义与层次结构

节点使用 节点名@地址 的格式定义,地址通常为寄存器基址或总线地址。节点可以嵌套,形成父子关系。

/dts-v1/;

/ {
    model = "Embedded Audio Board";
    compatible = "vendor,audio-board";

    soc {
        #address-cells = <1>;
        #size-cells = <1>;

        i2c@40003000 {
            compatible = "vendor,i2c-controller";
            reg = <0x40003000 0x1000>;
            #address-cells = <1>;
            #size-cells = <0>;

            codec@1a {
                compatible = "vendor,audio-codec";
                reg = <0x1a>;
                #sound-dai-cells = <0>;
            };
        };
    };
};
关键点:节点名 codec@1a 中的 1a 是I2C从设备地址,与 reg 属性值对应。#address-cells 和 #size-cells 决定了子节点 reg 属性的编码长度。

2.1.2 属性类型与写法

属性类型 示例 说明
字符串 compatible = "vendor,device"; 用于匹配驱动,格式为 厂商,设备型号
32位整数 reg = <0x1a>; 尖括号内为32位无符号整数,可多个
64位整数 reg = <0x00000000 0x10000000>; 使用两个32位单元表示64位地址
布尔值 status = "disabled"; 通过字符串 "okay" 或 "disabled" 表示
字节数组 local-mac-address = [00 11 22 33 44 55]; 方括号内为十六进制字节序列
字符串列表 clock-names = "mclk", "bclk"; 用逗号分隔多个字符串
设备树节点层次结构示例 / (根节点) soc i2c@40003000 codec@1a 节点属性示例 compatible = "vendor,audio-codec"; reg = <0x1a>; #sound-dai-cells = <0>;

2.2 reg属性与地址编码

reg 属性用于描述设备在总线上的地址范围或寄存器基址。其编码方式由父节点的 #address-cells 和 #size-cells 决定。

2.2.1 地址单元与大小单元

  • #address-cells:表示地址字段占用的32位单元数,值为1表示32位地址,值为2表示64位地址。
  • #size-cells:表示地址长度字段占用的32位单元数,值为0表示无长度(如I2C设备),值为1表示32位长度。
总线类型 #address-cells #size-cells reg 示例
I2C 1 0 reg = <0x1a>;
SPI 1 0 reg = <0>; (片选号)
内存映射 1 1 reg = <0x40003000 0x1000>;
64位内存映射 2 1 reg = <0x00000000 0x10000000 0x1000>;
常见错误:I2C设备节点中忘记设置 #size-cells = <0>,导致内核解析 reg 时多读一个单元,造成地址错误。务必与父节点定义保持一致。

2.3 compatible属性与驱动匹配

compatible 是设备树中最关键的属性之一,它指定了设备与驱动之间的匹配关系。内核通过设备树匹配表(of_match_table)将设备节点与驱动绑定。

2.3.1 命名规范

格式为 "厂商,设备型号",厂商名使用小写字母,设备型号使用小写字母和数字。例如:

compatible = "ti,tlv320aic3x", "simple-audio-card";

多个字符串表示兼容性列表,内核按顺序匹配,优先使用第一个匹配成功的驱动。

2.3.2 驱动匹配流程

compatible 属性驱动匹配流程 设备树节点 compatible = "ti,tlv320aic3x" OF核心层 of_match_table 匹配 音频驱动 probe() 回调执行 驱动中的 of_match_table 定义 static const struct of_device_id audio_codec_of_match[] = { { .compatible = "ti,tlv320aic3x" }, { /* sentinel */ } }; 匹配失败 设备不被驱动绑定

2.4 中断描述

设备树使用 interrupts 属性描述设备的中断资源,配合 interrupt-parent 指定中断控制器。

2.4.1 中断属性格式

interrupt-parent = <&gpio1>;
interrupts = <5 IRQ_TYPE_EDGE_RISING>;

其中 interrupts 的第一个单元是中断号(相对于中断控制器),第二个单元是中断触发类型。常用触发类型宏定义在 include/dt-bindings/interrupt-controller/irq.h 中:

宏定义 值 说明
IRQ_TYPE_EDGE_RISING 1 上升沿触发
IRQ_TYPE_EDGE_FALLING 2 下降沿触发
IRQ_TYPE_LEVEL_HIGH 4 高电平触发
IRQ_TYPE_LEVEL_LOW 8 低电平触发

2.4.2 音频编解码器中断示例

codec@1a {
    compatible = "ti,tlv320aic3x";
    reg = <0x1a>;
    interrupt-parent = <&gpio2>;
    interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
};
实践建议:音频编解码器通常使用GPIO中断来通知主机编解码器状态变化(如插拔检测、错误标志)。确保中断号与硬件原理图一致,且GPIO引脚配置为输入模式。

2.5 GPIO描述

设备树使用 gpios 或 *-gpios 属性描述GPIO资源。ALSA音频驱动中常见的GPIO包括复位引脚、电源控制引脚、静音控制引脚等。

2.5.1 GPIO属性格式

reset-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;

每个GPIO描述包含三个字段:GPIO控制器引用、引脚号、标志位。标志位 GPIO_ACTIVE_HIGH(0)或 GPIO_ACTIVE_LOW(1)表示有效电平。

2.5.2 音频设备GPIO典型用法

GPIO用途 属性名 典型连接
复位 reset-gpios 编解码器复位引脚
电源使能 power-gpios 编解码器电源开关
静音控制 mute-gpios 功放静音引脚
插拔检测 jack-gpios 耳机插孔检测引脚

2.5.3 完整音频编解码器设备树节点

&i2c1 {
    status = "okay";

    tlv320aic3x: audio-codec@1a {
        compatible = "ti,tlv320aic3x";
        reg = <0x1a>;
        #sound-dai-cells = <0>;

        interrupt-parent = <&gpio2>;
        interrupts = <15 IRQ_TYPE_EDGE_FALLING>;

        reset-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
        power-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;

        clocks = <&clks IMX6QDL_CLK_CKO>;
        clock-names = "mclk";

        status = "okay";
    };
};
关键点:#sound-dai-cells = <0> 表示该节点作为DAI(数字音频接口)提供者,且不需要额外参数。时钟属性 clocks 和 clock-names 用于指定主时钟源,对音频采样率精度至关重要。

2.6 设备树在ALSA驱动中的使用流程

设备树到ALSA声卡注册的完整流程 1. 设备树解析 of_match_table 匹配驱动 2. 资源获取 reg / interrupts / gpios 3. 硬件初始化 编解码器复位/配置 4. DAI链接注册 snd_soc_register_dai() 5. 声卡注册 snd_soc_register_card() 6. ALSA设备就绪 /dev/snd/pcmC0D0p
核心API:驱动中通过 of_property_read_u32() 读取整数属性,of_get_named_gpio() 获取GPIO号,irq_of_parse_and_map() 解析中断。这些函数在 probe() 中调用,将设备树信息转换为内核资源。

2.7 本章小结

  • 设备树使用树形节点结构描述硬件,每个节点通过 compatible 属性与驱动匹配。
  • reg 属性编码地址信息,其格式由父节点的 #address-cells 和 #size-cells 决定。
  • 中断通过 interrupt-parent 和 interrupts 属性描述,支持多种触发类型。
  • GPIO资源使用 *-gpios 属性描述,包含控制器引用、引脚号和有效电平标志。
  • ALSA音频驱动从设备树中获取编解码器地址、中断号、GPIO控制引脚和时钟信息,完成硬件初始化并注册声卡。