Wait DMA hardware complete cleanup work by checking HRS bit before disabling the channel to make sure trail data is already written to memory. Fixes: 72f5801a4e2b7 ("dmaengine: fsl-edma: integrate v3 support") Signed-off-by: Larisa Grigore <larisa.grigore@xxxxxxxxxxx> --- drivers/dma/fsl-edma-common.c | 9 +++++++++ drivers/dma/fsl-edma-common.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c index 62d51b269e54..d364514f21be 100644 --- a/drivers/dma/fsl-edma-common.c +++ b/drivers/dma/fsl-edma-common.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/dma-mapping.h> +#include <linux/iopoll.h> #include <linux/pm_runtime.h> #include <linux/pm_domain.h> @@ -127,11 +128,19 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan) static void fsl_edma3_disable_request(struct fsl_edma_chan *fsl_chan) { + struct fsl_edma_engine *fsl_edma = fsl_chan->edma; + struct edma_regs *regs = &fsl_chan->edma->regs; u32 val = edma_readl_chreg(fsl_chan, ch_csr); + u32 ch = fsl_chan->vchan.chan.chan_id; u32 flags; flags = fsl_edma_drvflags(fsl_chan); + /* Make sure there is no hardware request in progress. */ + read_poll_timeout(edma_readl, val, !(val & EDMA_V3_MP_HRS_CH(ch)), + EDMA_USEC_POLL, EDMA_USEC_TIMEOUT, false, fsl_edma, + regs->v3.hrs); + if (flags & FSL_EDMA_DRV_HAS_CHMUX) edma_writel(fsl_chan->edma, 0, fsl_chan->mux_addr); diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h index 63e908fc3575..ed210bd71681 100644 --- a/drivers/dma/fsl-edma-common.h +++ b/drivers/dma/fsl-edma-common.h @@ -70,6 +70,10 @@ #define EDMA_V3_CH_CSR_ACTIVE BIT(31) #define EDMA_V3_CH_ES_ERR BIT(31) #define EDMA_V3_MP_ES_VLD BIT(31) +#define EDMA_V3_MP_HRS_CH(ch) BIT(ch) + +#define EDMA_USEC_POLL 10 +#define EDMA_USEC_TIMEOUT 10000 enum fsl_edma_pm_state { RUNNING = 0, -- 2.47.0