[IMX6DL][Android4.4] Linux dmaengine 使用方法

Platform: IMX6DL
OS: Android 4.4

Kernel branch: 3.0.35


1. 分配slave通道

#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
根据mask信息从系统中已经注册的dma list中找到一个符合条件的channel。

2. 设置slave和controller参数信息
static inline int dmaengine_slave_config(struct dma_chan *chan,
 struct dma_slave_config *config);
配置slave的地址,方向,地址宽度等。

3. 获取DMA对应的desc, 设置callback
struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
    struct dma_chan *chan, struct scatterlist *sgl,
    unsigned int sg_len, enum dma_transfer_direction direction,
    unsigned long flags);
或者
struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
    struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
    size_t period_len, enum dma_transfer_direction direction);
slave支持两种不同的传输方式 slave_sg 和 dma_cyclic,两者区别其实就是前者是全部传输完成产生中断,
而后者则是每传输完成一次产生一次中断,见下图。
[IMX6DL][Android4.4] Linux dmaengine 使用方法_第1张图片

                                                    slave_sg

[IMX6DL][Android4.4] Linux dmaengine 使用方法_第2张图片

                                                 dma_cyclic


4. 提交DMA请求,等待处理完成回调通知。

static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc);

5. 触发DMA
void (*device_issue_pending)(struct dma_chan *chan);
触发DMA无非就是使能DMA中断,然后开始传输,这一步也可以放到上一步的submit里处理。

处理完后会触发中断,然后回调函数会被调用。


IMX6DL的UART和Audio使用了DMA, 如下为Audio使用部分:

snd_imx_pcm_hw_params ->    //imx-pcm-dma-mx2.c
    imx_ssi_dma_alloc ->
        dma_request_channel
        dmaengine_slave_config
        
snd_imx_pcm_trigger    -> //imx-pcm-dma-mx2.c
    dmaengine_submit ->
        desc->tx_submit ->
            sdma_tx_submit ->
                sdma_enable_channel


参考:

Documentation/dmaengine.txt

你可能感兴趣的:(IMX6_Android4.4)