Skip to content

dma_reload is non-operational for channels >=12 on S32K344 #96772

@Dat-NguyenDuy

Description

@Dat-NguyenDuy

Describe the bug

On S32K344, there is a gap in the memory map between eDMA channel 11 and channel 12. In the driver code, channel indexing for register access must account for the gap (dma_mcux_edma_add/remove_channel_gap used for handling this offset).

Unfortunately, this change #80584 did not pay attention to the gap that impacts platform like S32K344. Something like this might fix the issue on top of v4.2.0 (not tested):

Note: using channels <= 11 should still be fine for now

diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c
index 67a3a4d5cdc..1ef257db8a3 100644
--- a/drivers/dma/dma_mcux_edma.c
+++ b/drivers/dma/dma_mcux_edma.c
@@ -679,6 +679,10 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
 	uint32_t hw_id, sw_id;
 	uint8_t pre_idx;
 
+	uint32_t hw_channel;
+
+	hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
+
 	/* Lock the channel configuration */
 	const unsigned int key = irq_lock();
 	int ret = 0;
@@ -729,13 +733,13 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
 		 * code between EDMA_DisableChannelRequest() and
 		 * EDMA_EnableChannelRequest() is minimum.
 		 */
-		EDMA_DisableChannelRequest(DEV_BASE(dev), channel);
+		EDMA_DisableChannelRequest(DEV_BASE(dev), hw_channel);
 
 		/* Wait for the DMA to be inactive before updating the TCDs.
 		 * The CSR[ACTIVE] bit will deassert quickly after the EDMA's
 		 * minor loop burst completes.
 		 */
-		while (EDMA_HW_TCD_CSR(dev, channel) & EDMA_HW_TCD_CH_ACTIVE_MASK) {
+		while (EDMA_HW_TCD_CSR(dev, hw_channel) & EDMA_HW_TCD_CH_ACTIVE_MASK) {
 			;
 		}
 
@@ -746,7 +750,7 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
 			/* All transfers have been done.DMA is stopped automatically,
 			 * invalid TCD has been loaded into the HW, update HW.
 			 */
-			dma_mcux_edma_update_hw_tcd(dev, channel, src, dst, size);
+			dma_mcux_edma_update_hw_tcd(dev, hw_channel, src, dst, size);
 			LOG_DBG("Transfer done,auto stop");
 
 		} else {
@@ -761,7 +765,7 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
 				/* DMA is running on last transfer. HW has loaded the last one,
 				 * we need ensure it's DREQ is cleared.
 				 */
-				EDMA_EnableAutoStopRequest(DEV_BASE(dev), channel, false);
+				EDMA_EnableAutoStopRequest(DEV_BASE(dev), hw_channel, false);
 				LOG_DBG("Last transfer.");
 			}
 			LOG_DBG("Manu stop");
@@ -777,7 +781,7 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
 		/*We have not verified if this issue exist on V3/V4 HW, jut place a holder here. */
 #endif
 		/* TCDs are configured.  Resume DMA */
-		EDMA_EnableChannelRequest(DEV_BASE(dev), channel);
+		EDMA_EnableChannelRequest(DEV_BASE(dev), hw_channel);

Regression

  • This is a regression.

Steps to reproduce

Attempting to use dma_reload with channels ≥ 12 on the S32K344 causes a software crash (e.g #96600)

Relevant log output

Impact

Functional Limitation – Some features not working as expected, but system usable.

Environment

No response

Additional Context

No response

Metadata

Metadata

Assignees

Labels

RegressionSomething, which was working, does not anymorebugThe issue is a bug, or the PR is fixing a bugplatform: NXPNXPplatform: NXP S32NXP Semiconductors, S32priority: lowLow impact/importance bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions