dmaengine: fsl-dma: fix DMA error when enabling sg if 'DONE' bit is set
authorFrank Li <Frank.Li@nxp.com>
Thu, 21 Sep 2023 14:46:52 +0000 (10:46 -0400)
committerVinod Koul <vkoul@kernel.org>
Thu, 28 Sep 2023 11:20:34 +0000 (16:50 +0530)
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>
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-common.h
drivers/dma/fsl-edma-main.c

index a0f5741..50203b8 100644 (file)
@@ -448,12 +448,25 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
 
        edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga);
 
+       csr = le16_to_cpu(tcd->csr);
+
        if (fsl_chan->is_sw) {
-               csr = le16_to_cpu(tcd->csr);
                csr |= EDMA_TCD_CSR_START;
                tcd->csr = cpu_to_le16(csr);
        }
 
+       /*
+        * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3
+        * eDMAv4 have not such requirement.
+        * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4.
+        */
+       if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) &&
+               (csr & EDMA_TCD_CSR_E_SG)) ||
+           ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) &&
+               (csr & EDMA_TCD_CSR_E_LINK)))
+               edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr);
+
+
        edma_write_tcdreg(fsl_chan, tcd->csr, csr);
 }
 
index 3cc0cc8..40d50cc 100644 (file)
@@ -183,11 +183,23 @@ struct fsl_edma_desc {
 #define FSL_EDMA_DRV_BUS_8BYTE         BIT(10)
 #define FSL_EDMA_DRV_DEV_TO_DEV                BIT(11)
 #define FSL_EDMA_DRV_ALIGN_64BYTE      BIT(12)
+/* Need clean CHn_CSR DONE before enable TCD's ESG */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_SG   BIT(13)
+/* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14)
 
 #define FSL_EDMA_DRV_EDMA3     (FSL_EDMA_DRV_SPLIT_REG |       \
                                 FSL_EDMA_DRV_BUS_8BYTE |       \
                                 FSL_EDMA_DRV_DEV_TO_DEV |      \
-                                FSL_EDMA_DRV_ALIGN_64BYTE)
+                                FSL_EDMA_DRV_ALIGN_64BYTE |    \
+                                FSL_EDMA_DRV_CLEAR_DONE_E_SG | \
+                                FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
+
+#define FSL_EDMA_DRV_EDMA4     (FSL_EDMA_DRV_SPLIT_REG |       \
+                                FSL_EDMA_DRV_BUS_8BYTE |       \
+                                FSL_EDMA_DRV_DEV_TO_DEV |      \
+                                FSL_EDMA_DRV_ALIGN_64BYTE |    \
+                                FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
 
 struct fsl_edma_drvdata {
        u32                     dmamuxs; /* only used before v3 */
index 63d48d0..621a460 100644 (file)
@@ -355,7 +355,7 @@ static struct fsl_edma_drvdata imx93_data3 = {
 };
 
 static struct fsl_edma_drvdata imx93_data4 = {
-       .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
+       .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4,
        .chreg_space_sz = 0x8000,
        .chreg_off = 0x10000,
        .setup_irq = fsl_edma3_irq_init,