4. DMA控制器设备树绑定规范

设备树中DMA控制器的绑定规范是驱动开发者与硬件描述之间的契约。本章详细解析dma-controller节点、#dma-cells属性、dma-channel-mask以及dma-capabilities的核心定义与配置方法。

学习目标:掌握DMA控制器设备树节点的标准结构,理解各属性的语义与约束,能够独立编写或校验DMA控制器的设备树绑定。

4.1 dma-controller 节点结构

每个DMA控制器在设备树中必须声明为一个dma-controller节点,该节点是DMA Engine框架识别硬件控制器的入口。节点通常位于soc总线节点下,包含一组标准属性和控制器特定的属性。

以下是一个典型的DMA控制器节点示例:

dma: dma-controller@1c00000 {
    compatible = "vendor,axi-dma-1.0";
    reg = <0x01c00000 0x1000>;
    interrupts = <0 12 4>;
    #dma-cells = <3>;
    dma-channel-mask = <0x3f>;
    dma-capabilities = <0x0007>;
    clocks = <&clk 5>;
    resets = <&rst 5>;
    dma-channels = <6>;
    status = "okay";
};
关键字段说明:
  • compatible:驱动匹配字符串,必须与驱动中的of_device_id表一致。
  • reg:DMA控制器的寄存器基地址和地址范围。
  • interrupts:DMA控制器中断号,通常为1个或多个。
  • #dma-cells:指定DMA请求端(consumer)节点中dma属性所需的参数个数。
  • dma-channels:硬件支持的DMA通道总数(可选,但推荐显式声明)。
dma-controller 节点结构 dma-controller@1c00000 标识属性 • compatible • reg • interrupts • clocks • resets • status DMA绑定属性 • #dma-cells • dma-channel-mask • dma-capabilities • dma-channels 可选属性 • dma-coherent • iommus • power-domains • resets

4.2 #dma-cells 属性详解

#dma-cells是DMA控制器节点中最重要的绑定属性之一,它定义了DMA请求端(consumer)节点中dmas属性所需的参数个数。该属性直接决定了DMA通道、请求线、优先级等信息的编码方式。

#dma-cells 值 典型含义 使用场景
1 仅指定DMA通道号 简单DMA控制器,每个外设固定通道
2 通道号 + 请求线/外设ID 多请求线DMA,如PL330、DMA-330
3 通道号 + 请求线 + 传输类型/优先级 复杂DMA控制器,支持多种传输模式
4+ 扩展参数(如突发长度、地址宽度等) 自定义或特殊DMA控制器

consumer节点中的dmas属性使用示例:

/* #dma-cells = <2> 的情况 */
uart0: serial@1f00000 {
    compatible = "vendor,uart";
    reg = <0x01f00000 0x1000>;
    interrupts = <0 20 4>;
    dmas = <&dma 0 2>,  /* 通道0,请求线2(TX) */
           <&dma 1 3>;  /* 通道1,请求线3(RX) */
    dma-names = "tx", "rx";
};
常见错误:#dma-cells的值必须与驱动中of_dma_xlate_by_chan_id或自定义翻译函数的参数个数严格匹配。若consumer节点中dmas提供的参数个数少于#dma-cells,内核解析时会报错并返回NULL,导致DMA请求失败。

4.3 dma-channel-mask 属性

dma-channel-mask是一个位掩码属性,用于标识DMA控制器中哪些通道是物理可用的。该属性在硬件设计存在通道缺失或保留通道时尤为重要。

属性格式:

dma-channel-mask = <0x3f>;  /* 位0~5有效,共6个通道 */

位掩码的每一位对应一个DMA通道:

  • 位0 → 通道0
  • 位1 → 通道1
  • 位2 → 通道2
  • ……
  • 位N → 通道N

当某位为1时,表示该通道可用;为0时表示该通道不可用或保留。

掩码值 二进制 可用通道 说明
0x3F 0011 1111 通道0~5 6个通道全部可用
0x0F 0000 1111 通道0~3 仅低4个通道可用
0x55 0101 0101 通道0,2,4,6 仅偶数通道可用
0x00 0000 0000 无 所有通道禁用(异常情况)
驱动处理逻辑:DMA Engine驱动在初始化时读取dma-channel-mask,遍历所有位,仅对标记为1的通道进行注册和初始化。未标记的通道不会出现在dma_device的chan_list中,consumer无法请求到这些通道。
dma-channel-mask 位映射示例 (0x3F) 位7 0 位6 0 位5 1 位4 1 位3 1 位2 1 位1 1 位0 1 通道映射结果 通道0~5可用(位0~5为1),通道6~7不可用(位6~7为0)

4.4 dma-capabilities 属性

dma-capabilities是一个位掩码属性,用于描述DMA控制器硬件支持的能力集。该属性帮助DMA Engine框架在运行时快速判断控制器是否支持特定传输类型或特性,避免无效的通道请求。

标准能力位定义:

位 宏定义 值 描述
0 DMA_CAP_MEMCPY 0x0001 支持内存到内存拷贝
1 DMA_CAP_MEMSET 0x0002 支持内存填充(memset)
2 DMA_CAP_INTERLEAVE 0x0004 支持交错传输(scatter-gather)
3 DMA_CAP_SG 0x0008 支持分散/聚集列表
4 DMA_CAP_CYCLIC 0x0010 支持循环传输(音频流常用)
5 DMA_CAP_PRIVATE 0x0020 支持私有/专用通道

配置示例:

/* 支持MEMCPY + MEMSET + SG */
dma-capabilities = <0x000B>;  /* 0x0001 | 0x0002 | 0x0008 */

/* 支持所有标准能力 */
dma-capabilities = <0x003F>;  /* 位0~5全部置1 */
驱动最佳实践:在DMA Engine驱动的probe函数中,读取dma-capabilities后,应将其与硬件实际能力进行交叉校验。如果设备树声明了某能力但硬件不支持,驱动应记录警告并清除该能力位,避免上层模块误用。

4.5 属性组合与校验流程

DMA控制器设备树绑定的完整校验流程如下:

  1. 节点识别:内核通过compatible匹配驱动,调用of_match_node。
  2. 资源获取:解析reg、interrupts、clocks等基础资源。
  3. 通道解析:读取dma-channel-mask,确定可用通道位图。
  4. 能力解析:读取dma-capabilities,填充dma_device的cap_mask。
  5. 翻译注册:根据#dma-cells注册of_dma_xlate回调函数。
  6. 通道初始化:遍历可用通道位图,为每个通道分配dma_chan结构并初始化。
DMA控制器设备树属性校验流程 1. 节点识别 2. 资源获取 3. 通道解析 4. 能力解析 5. 翻译注册 6. 通道初始化 关键属性依赖 • compatible → 驱动匹配 • reg / interrupts → 基础资源 • dma-channel-mask → 通道位图 • dma-capabilities → 能力掩码 • #dma-cells → 翻译函数注册 • dma-channels → 通道总数 • 所有属性校验通过后 驱动完成初始化 并注册到DMA Engine框架

4.6 常见问题与避坑指南

避坑1:#dma-cells 与 dmas 参数不匹配
若控制器声明#dma-cells = <3>,但consumer节点中dmas只提供2个参数,内核解析时会返回NULL。务必检查所有consumer节点的dmas属性参数个数是否一致。
避坑2:dma-channel-mask 与 dma-channels 冲突
dma-channel-mask中置1的位数必须小于等于dma-channels声明的总数。例如dma-channels = <4>但dma-channel-mask = <0x3F>(6个位为1),会导致驱动尝试初始化不存在的通道,引发访问越界。
调试技巧:在驱动中添加以下打印语句,可快速验证设备树属性是否正确解析:
dev_info(dev, "channel mask: 0x%x\n", chan_mask);
dev_info(dev, "capabilities: 0x%x\n", caps);
dev_info(dev, "#dma-cells: %d\n", cells);
通过dmesg日志即可确认设备树解析结果。

4.7 完整绑定示例

以下是一个完整的DMA控制器设备树绑定示例,包含所有核心属性:

/ {
    soc {
        dma0: dma-controller@10000000 {
            compatible = "arm,pl330", "arm,primecell";
            reg = <0x10000000 0x1000>;
            interrupts = <0 25 4>;
            #dma-cells = <2>;
            dma-channel-mask = <0x0F>;       /* 通道0~3可用 */
            dma-capabilities = <0x000B>;     /* MEMCPY | MEMSET | SG */
            dma-channels = <4>;
            clocks = <&clk 10>;
            clock-names = "apb_pclk";
            status = "okay";
        };

        uart1: serial@10100000 {
            compatible = "arm,pl011";
            reg = <0x10100000 0x1000>;
            interrupts = <0 30 4>;
            dmas = <&dma0 0 2>,  /* 通道0,请求线2(TX) */
                   <&dma0 1 3>;  /* 通道1,请求线3(RX) */
            dma-names = "tx", "rx";
        };
    };
};

该示例中:

  • DMA控制器使用PL330 IP核,兼容ARM PrimeCell标准。
  • 仅通道0~3可用(掩码0x0F),支持内存拷贝、内存填充和分散/聚集传输。
  • UART1使用通道0和通道1,分别对应TX和RX请求线。
本章小结:DMA控制器的设备树绑定规范是DMA Engine驱动开发的基石。dma-controller节点定义了硬件资源,#dma-cells决定了consumer与controller之间的参数契约,dma-channel-mask和dma-capabilities则分别从通道可用性和能力集两个维度描述了控制器的特性。正确理解和配置这些属性,是确保DMA子系统稳定运行的前提。