You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下如何筛选指定DMA通道(基于设备树compatible属性)

筛选指定DMA通道:获取通道compatible属性的实现方法

在设备驱动开发中,需要调用dma_request_channel并传入筛选函数,选中设备树中指定的DMA通道(即dma-channel@48000000节点,其compatible为xlnx,axi-dma-mm2s-channel)。

参考设备树片段

srio_hier0_srio_hier0_AXI_DMA_SGDMA0: dma@48000000 {
    #dma-cells = <1>;
    clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
    clocks = <&clkc 15>, <&clkc 16>, <&clkc 16>, <&clkc 16>;
    compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a";
    interrupt-names = "mm2s_introut", "s2mm_introut";
    interrupt-parent = <&intc>;
    interrupts = <0 30 4 0 29 4>;
    reg = <0x48000000 0x10000>;
    xlnx,addrwidth = <0x20>;
    xlnx,include-sg ;
    xlnx,sg-include-stscntrl-strm ;
    xlnx,sg-length-width = <0x17>;
    dma-channel@48000000 {                       
        compatible = "xlnx,axi-dma-mm2s-channel";  // 目标DMA通道
        dma-channels = <0x1>;
        interrupts = <0 30 4>;
        xlnx,datawidth = <0x40>;
        xlnx,device-id = <0x0>;
        xlnx,include-dre ;
    };
    dma-channel@48000030 {
        compatible = "xlnx,axi-dma-s2mm-channel";
        dma-channels = <0x1>;
        interrupts = <0 29 4>;
        xlnx,datawidth = <0x40>;
        xlnx,device-id = <0x0>;
        xlnx,include-dre ;
    };
};

现有调用代码

dma_cap_mask_t      dma_cap_mask;

dma_cap_zero(dma_cap_mask);
dma_cap_set(DMA_SLAVE, dma_cap_mask);

slave_dma_chan = dma_request_channel(dma_cap_mask, dma_filter_function, ptrToMyData);

待完善的筛选函数

static bool dma_filter_function (struct dma_chan *chan, void *filter_param)
{
    struct MyData* myData = (struct MyData*) filter_param;

    struct device*          dev                 = chan->device->dev;
    struct device_node*     device_tree_node    = dev->of_node;

    if (0 != strcmp(device_tree_node->full_name, "dma@48000000"))
      return false;

    // 求助:如何编写get_compatible函数,获取当前通道的compatible属性值?
    return (NULL != strstr( "axi-dma-mm2s-channel", get_compatible(chan)));
}

解决方案:无需自定义get_compatible函数

内核提供了现成的OF设备树操作API,直接利用这些API即可获取DMA通道对应的设备树节点并检查compatible属性。需要注意的是:原代码中chan->device->dev->of_node指向的是DMA控制器的父节点,而非具体的通道子节点,正确的做法是直接使用chan->of_node(Xilinx AXI DMA驱动会将每个通道的of_node字段关联到对应的设备树子节点)。

完整的筛选函数实现

#include <linux/of.h>
#include <linux/dmaengine.h>

static bool dma_filter_function(struct dma_chan *chan, void *filter_param)
{
    // 首先检查通道是否关联了设备树节点
    if (!chan->of_node)
        return false;

    // 检查当前通道节点的compatible是否匹配目标值
    if (of_device_is_compatible(chan->of_node, "xlnx,axi-dma-mm2s-channel")) {
        // 可选:如果需要额外匹配DMA控制器父节点的地址,可添加以下检查
        struct device_node *parent_node = of_get_parent(chan->of_node);
        bool parent_match = false;
        if (parent_node) {
            parent_match = !strcmp(parent_node->full_name, "dma@48000000");
            of_node_put(parent_node);
        }
        return parent_match;
    }

    return false;
}

代码说明

  1. 检查通道的设备树节点:先判断chan->of_node是否有效,避免空指针访问。
  2. 匹配compatible属性:使用of_device_is_compatible函数,该函数会自动遍历节点的compatible列表,检查是否包含指定字符串,比手动调用strstr更可靠。
  3. 可选的父节点匹配:如果需要确保选中的通道属于特定的DMA控制器,可以额外获取父节点并检查其名称,完成后记得调用of_node_put释放节点引用。

内容的提问来源于stack exchange,提问作者Pax to You

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:17:50