使用DMAengine
DMAengine是Linux下一套通用的DMA驱动框架,用于通用的DMA,就是UART、SPI他们这些相对低速的接口使用的DMA,这些接口使用一个或两个DMA控制器。通过这个DMA控制器的不同端口共同使用这个控制器,控制器可以仲裁各个端口分时使用。
使用步骤如下:
1)申请一个DMA channel。
2)根据设备(slave)的特性,配置DMA channel的参数。
3)要进行DMA传输的时候,获取一个用于识别本次传输(transaction)的描述符(descriptor)。
4)将本次传输(transaction)提交给dma engine并启动传输。
5)等待传输(transaction)结束。
然后,重复3~5即可。
之所以有这个框架是因为这一个控制器就管理着好多的端口,可以应用的设备比较多。
不使用DMAengine
像以太网之类的外设有自己的专用DMA控制器,就没必要使用这个驱动框架了。比如上一步的第一步和第二部就是不适合用于那个框架。如果非要用,就比如第四部,启动传输由于连个DMA控制器的具体用法不一样,还得单独写一个DMAengine的中间层。
static void macb_configure_dma(struct macb *bp)
{
u32 dmacfg;
if (macb_is_gem(bp)) {
dmacfg=gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
dmacfg |=GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
if (bp->dma_burst_length)
dmacfg=GEM_BFINS(FBLDO, bp->dma_burst_length, dmacfg);
dmacfg |=GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
dmacfg &=~GEM_BIT(ENDIA_PKT);
...
比如这是一段dma控制器的初始化,就是随设备一起初始化。发送的时候也是直接写寄存器。如下所示
if (i==queue->tx_head) {
ctrl |=MACB_BF(TX_LSO, lso_ctrl);
ctrl |=MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
} else
ctrl |=MACB_BF(MSS_MFS, mss_mfs);
macb_set_addr(bp, desc, tx_skb->mapping);