From 5e66bdb4a18a538e8011585716675e3180f52435 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Fri, 22 May 2020 22:00:28 +0800 Subject: [PATCH] dmaengine: fsl-edma-v3: dynamic change burst length Dynamic change burst length in case transfer length is not multiple of burst length to meet the edmav3 hardware limitation. Signed-off-by: Robin Gong Reviewed-by: Shengjiu Wang (cherry picked from commit 4b92c1194ba9f1c6f6d9a6f13a09639323787ce9) --- drivers/dma/fsl-edma-v3.c | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/dma/fsl-edma-v3.c b/drivers/dma/fsl-edma-v3.c index c38256c1060b..a14bee28fc59 100644 --- a/drivers/dma/fsl-edma-v3.c +++ b/drivers/dma/fsl-edma-v3.c @@ -590,6 +590,26 @@ static struct dma_async_tx_descriptor *fsl_edma3_prep_dma_cyclic( dma_buf_next = dma_addr; nbytes = fsl_chan->fsc.addr_width * fsl_chan->fsc.burst; + + /* + * Choose the suitable burst length if period_len is not multiple of + * burst length so that the whole transfer length is multiple of minor + * loop(burst length). + */ + if (period_len % nbytes) { + u32 width = fsl_chan->fsc.addr_width; + + for (i = fsl_chan->fsc.burst; i > 1; i--) { + if (!(period_len % (i * width))) { + nbytes = i * width; + break; + } + } + /* if no chance to get suitable burst size, use it as 1 */ + if (i == 1) + nbytes = width; + } + iter = period_len / nbytes; for (i = 0; i < sg_len; i++) { @@ -676,6 +696,26 @@ static struct dma_async_tx_descriptor *fsl_edma3_prep_slave_sg( doff = 0; } + /* + * Choose the suitable burst length if sg_dma_len is not + * multiple of burst length so that the whole transfer length is + * multiple of minor loop(burst length). + */ + if (sg_dma_len(sg) % nbytes) { + u32 width = fsl_chan->fsc.addr_width; + int j; + + for (j = fsl_chan->fsc.burst; j > 1; j--) { + if (!(sg_dma_len(sg) % (j * width))) { + nbytes = j * width; + break; + } + } + /* Set burst size as 1 if there's no suitable one */ + if (j == 1) + nbytes = width; + } + iter = sg_dma_len(sg) / nbytes; if (i < sg_len - 1) { last_sg = fsl_desc->tcd[(i + 1)].ptcd; -- 2.17.1