2.4. pl08x_disable_dmac_chan

/*
 * 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);
    1
	/* 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;
}
        

1

此处对于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:

  1. Set the Halt bit in the relevant channel Configuration Register. See Channel Configuration Registers on page 3-27. This causes any subsequent DMA requests to be ignored
  2. Poll the Active bit in the relevant channel Configuration Register until it reaches 0. This bit indicates whether there is any data in the channel that has to be transferred
  3. Clear the Channel Enable bit in the relevant channel Configuration Register

即先设置Halt位,然后一直轮询检测对应channel,直到inactive,然后再清空对应的Channel Enable位,如果直接不做任何检测判断,上来就去清空对应的Enable位,那么就会“losing data in the FIFO ”,丢失了FIFO中的数据,是不太安全的