关键流程设计
DMA 模块包含以下关键流程:
初始化流程
DMA 驱动的初始化过程见 aic_dma_probe()函数,除了普通 platform 设备的处理过程(申请 regs 资源、clk、reset)外,需要调用 DMA 子系统的接口 dma_async_device_register()来注册 DMA 备。
intdma_async_device_register(structdma_device*device)
其中参数 device
需要提供的关键信息有:DMA 控制器能力描述、DMA 操作 API 等,其初始化内容如下:
/* 配置 DMA 控制器的能力描述信息 */ if (of_device_is_compatible(pdev->dev.of_node, "artinchip,aic-dma-v0.1")) sdev->slave.copy_align = DMAENGINE_ALIGN_128_BYTES; else sdev->slave.copy_align = DMAENGINE_ALIGN_8_BYTES; sdev->slave.src_addr_widths = AIC_DMA_BUS_WIDTH; sdev->slave.dst_addr_widths = AIC_DMA_BUS_WIDTH; sdev->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); sdev->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; INIT_LIST_HEAD(&sdev->slave.channels); dma_cap_set(DMA_PRIVATE, sdev->slave.cap_mask); dma_cap_set(DMA_MEMCPY, sdev->slave.cap_mask); dma_cap_set(DMA_SLAVE, sdev->slave.cap_mask); dma_cap_set(DMA_CYCLIC, sdev->slave.cap_mask); /* 初始化 DMA 操作 API */ sdev->slave.device_free_chan_resources = aic_dma_free_chan_resources; sdev->slave.device_prep_dma_memcpy = aic_dma_prep_dma_memcpy; sdev->slave.device_prep_slave_sg = aic_dma_prep_slave_sg; sdev->slave.device_prep_dma_cyclic = aic_dma_prep_dma_cyclic; sdev->slave.device_config = aic_dma_config; sdev->slave.device_pause = aic_dma_pause; sdev->slave.device_resume = aic_dma_resume; sdev->slave.device_terminate_all = aic_dma_terminate_all; sdev->slave.device_tx_status = aic_dma_tx_status; sdev->slave.device_issue_pending = aic_dma_issue_pending; sdev->slave.device_release = aic_dma_device_release;
其中,DMA 控制器的能力特性含义如下:
能力特性 | 含义 |
---|---|
DMA_PRIVATE | 不支持异步传输 |
DMA_MEMCPY | 支持内存到内存的拷贝操作 |
DMA_SLAVE | 支持设备到内存的传输操作 |
DMA_CYCLIC | 支持循环 Buffer 的情况 |
DMA Client 的调用流程
作为 DMA 用户,调用流程如下:
其中有两个操作的概念需要注意:
-
submit,是指传输请求提交给了 DMA Engine 的缓存中,还没有开始传输数据
-
issue pending,将传输请求加入到 DMA Device 的请求队列中,接下来才会启动数据传输动作
中断处理流程
中断处理流程主要是:
-
逐个 DMA 通道的查看完成状态;
-
如果当前传输是循环 Buffer 的情况,则直接调用预先注册好的回调接口;
-
如果不是循环模式,则更新相应的通道状态为 Complete。