Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: fsl-dma: fix DMA error when enabling sg if 'DONE' bit is set

In eDMAv3, clearing 'DONE' bit (bit 30) of CHn_CSR is required when
enabling scatter-gather (SG). eDMAv4 does not require this change.

Cc: stable@vger.kernel.org
Fixes: 72f5801a4e2b ("dmaengine: fsl-edma: integrate v3 support")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20230921144652.3259813-1-Frank.Li@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Frank Li and committed by
Vinod Koul
3c67c523 0bb80ecc

+28 -3
+14 -1
drivers/dma/fsl-edma-common.c
··· 448 448 449 449 edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga); 450 450 451 + csr = le16_to_cpu(tcd->csr); 452 + 451 453 if (fsl_chan->is_sw) { 452 - csr = le16_to_cpu(tcd->csr); 453 454 csr |= EDMA_TCD_CSR_START; 454 455 tcd->csr = cpu_to_le16(csr); 455 456 } 457 + 458 + /* 459 + * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3 460 + * eDMAv4 have not such requirement. 461 + * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4. 462 + */ 463 + if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) && 464 + (csr & EDMA_TCD_CSR_E_SG)) || 465 + ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) && 466 + (csr & EDMA_TCD_CSR_E_LINK))) 467 + edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr); 468 + 456 469 457 470 edma_write_tcdreg(fsl_chan, tcd->csr, csr); 458 471 }
+13 -1
drivers/dma/fsl-edma-common.h
··· 183 183 #define FSL_EDMA_DRV_BUS_8BYTE BIT(10) 184 184 #define FSL_EDMA_DRV_DEV_TO_DEV BIT(11) 185 185 #define FSL_EDMA_DRV_ALIGN_64BYTE BIT(12) 186 + /* Need clean CHn_CSR DONE before enable TCD's ESG */ 187 + #define FSL_EDMA_DRV_CLEAR_DONE_E_SG BIT(13) 188 + /* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */ 189 + #define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14) 186 190 187 191 #define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \ 188 192 FSL_EDMA_DRV_BUS_8BYTE | \ 189 193 FSL_EDMA_DRV_DEV_TO_DEV | \ 190 - FSL_EDMA_DRV_ALIGN_64BYTE) 194 + FSL_EDMA_DRV_ALIGN_64BYTE | \ 195 + FSL_EDMA_DRV_CLEAR_DONE_E_SG | \ 196 + FSL_EDMA_DRV_CLEAR_DONE_E_LINK) 197 + 198 + #define FSL_EDMA_DRV_EDMA4 (FSL_EDMA_DRV_SPLIT_REG | \ 199 + FSL_EDMA_DRV_BUS_8BYTE | \ 200 + FSL_EDMA_DRV_DEV_TO_DEV | \ 201 + FSL_EDMA_DRV_ALIGN_64BYTE | \ 202 + FSL_EDMA_DRV_CLEAR_DONE_E_LINK) 191 203 192 204 struct fsl_edma_drvdata { 193 205 u32 dmamuxs; /* only used before v3 */
+1 -1
drivers/dma/fsl-edma-main.c
··· 355 355 }; 356 356 357 357 static struct fsl_edma_drvdata imx93_data4 = { 358 - .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3, 358 + .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4, 359 359 .chreg_space_sz = 0x8000, 360 360 .chreg_off = 0x10000, 361 361 .setup_irq = fsl_edma3_irq_init,