/* * Overall DMAC remains enabled always. * * Disabling individual channels could lose data. * * Disable the peripheral DMA after disabling the DMAC * in order to allow the DMAC FIFO to drain, and * hence allow the channel to show inactive * */ void pl08x_disable_dmac_chan(unsigned int ci) { unsigned int reg; unsigned int chan_base = (unsigned int)pd.base + PL08X_OS_CHAN_BASE; chan_base += ci * PL08X_OS_CHAN; /* * Ignore subsequent requests */ reg = readl(chan_base + PL08X_OS_CCFG); reg |= PL08X_MASK_HALT; writel(reg, chan_base + PL08X_OS_CCFG); /* Wait for channel inactive */ reg = readl(chan_base + PL08X_OS_CCFG); while (reg & PL08X_MASK_ACTIVE) reg = readl(chan_base + PL08X_OS_CCFG); reg = readl(chan_base + PL08X_OS_CCFG); reg &= ~PL08X_MASK_CEN; writel(reg, chan_base + PL08X_OS_CCFG); mb(); return; }
此处对于disable一个DMA的channel的做法,是根据datasheet中的描述: “Disabling a DMA channel without losing data in the FIFO To disable a DMA channel without losing data in the FIFO:
即先设置Halt位,然后一直轮询检测对应channel,直到inactive,然后再清空对应的Channel Enable位,如果直接不做任何检测判断,上来就去清空对应的Enable位,那么就会“losing data in the FIFO ”,丢失了FIFO中的数据,是不太安全的 |