Commit 3c67c523 authored by Frank Li's avatar Frank Li Committed by Vinod Koul
Browse files

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: 72f5801a ("dmaengine: fsl-edma: integrate v3 support")
Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20230921144652.3259813-1-Frank.Li@nxp.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 0bb80ecc
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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);

	if (fsl_chan->is_sw) {
	csr = le16_to_cpu(tcd->csr);

	if (fsl_chan->is_sw) {
		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);
}

+13 −1
Original line number Diff line number Diff line
@@ -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 */
+1 −1
Original line number Diff line number Diff line
@@ -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,