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"; |
用逗号分隔多个字符串 |
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>; |
#size-cells = <0>,导致内核解析 reg 时多读一个单元,造成地址错误。务必与父节点定义保持一致。
2.3 compatible属性与驱动匹配
compatible 是设备树中最关键的属性之一,它指定了设备与驱动之间的匹配关系。内核通过设备树匹配表(of_match_table)将设备节点与驱动绑定。
2.3.1 命名规范
格式为 "厂商,设备型号",厂商名使用小写字母,设备型号使用小写字母和数字。例如:
compatible = "ti,tlv320aic3x", "simple-audio-card";
多个字符串表示兼容性列表,内核按顺序匹配,优先使用第一个匹配成功的驱动。
2.3.2 驱动匹配流程
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>;
};
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驱动中的使用流程
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控制引脚和时钟信息,完成硬件初始化并注册声卡。