From 9e4832d0a9b77b4c6cd518c2b6c64275ec3479e5 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 11 Apr 2019 13:57:35 +0200 Subject: [PATCH] dw-dma: change dw_dma_stop for byt and cht Changes implementation of dw_dma_stop function for baytrail and cherrytrail platforms. On this platforms we cannot simply disable channel during transfer, because it will hang DMA. Previously we were waiting for transfer finish, which could take up to one period size (1 ms in most cases). This patch uses suspend and drain FIFO mechanism, which lowers time needed to stop DMA channel to steady ~0.34 ms. Signed-off-by: Tomasz Lauda --- src/drivers/dw/dma.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/drivers/dw/dma.c b/src/drivers/dw/dma.c index 20b27983c152..937c77ebf1f0 100644 --- a/src/drivers/dw/dma.c +++ b/src/drivers/dw/dma.c @@ -639,13 +639,24 @@ static int dw_dma_stop(struct dma *dma, int channel) spin_lock_irq(&dma->lock, flags); - ret = poll_for_register_delay(dma_base(dma) + DW_DMA_CHAN_EN, - CHAN_MASK(channel), 0, + /* channel cannot be disabled right away, so first we need to + * suspend it and drain the FIFO + */ + dw_write(dma, DW_CFG_LOW(channel), chan->cfg_lo | DW_CFG_CH_SUSPEND | + DW_CFG_CH_DRAIN); + + /* now we wait for FIFO to be empty */ + ret = poll_for_register_delay(dma_base(dma) + DW_CFG_LOW(channel), + DW_CFG_CH_FIFO_EMPTY, + DW_CFG_CH_FIFO_EMPTY, PLATFORM_DMA_TIMEOUT); if (ret < 0) trace_dwdma_error("dw-dma: %d channel %d timeout", dma->plat_data.id, channel); + /* channel can be disabled */ + dw_write(dma, DW_DMA_CHAN_EN, CHAN_DISABLE(channel)); + if (!chan->irq_disabled) dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);