diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index bd96efbf0a5..5a11cd7f324 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_DMA_NIOS2_MSGDMA dma_nios2_msgdma.c) zephyr_library_sources_ifdef(CONFIG_DMA_SAM0 dma_sam0.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dma_handlers.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_EDMA dma_mcux_edma.c) +zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_EDMA_V3 dma_mcux_edma.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_LPC dma_mcux_lpc.c) zephyr_library_sources_ifdef(CONFIG_DMA_PL330 dma_pl330.c) zephyr_library_sources_ifdef(CONFIG_DMA_IPROC_PAX dma_iproc_pax_v1.c) diff --git a/drivers/dma/Kconfig.mcux_edma b/drivers/dma/Kconfig.mcux_edma index d4d44cb4cf7..4edd9d4a592 100644 --- a/drivers/dma/Kconfig.mcux_edma +++ b/drivers/dma/Kconfig.mcux_edma @@ -11,7 +11,14 @@ config DMA_MCUX_EDMA help DMA driver for MCUX series SoCs. -if DMA_MCUX_EDMA +config DMA_MCUX_EDMA_V3 + bool "MCUX DMA v3 driver" + default y + depends on DT_HAS_NXP_MCUX_EDMA_V3_ENABLED + help + DMA version 3 driver for MCUX series SoCs. + +if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 config DMA_TCD_QUEUE_SIZE int "number of TCD in a queue for SG mode" @@ -33,4 +40,4 @@ config DMA_MCUX_USE_DTCM_FOR_DMA_DESCRIPTORS When this option is activated, the descriptors for DMA transfer are located in the DTCM (Data Tightly Coupled Memory). -endif # DMA_MCUX_EDMA +endif # DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c index 10fc71bb6b7..ec940cc8f81 100644 --- a/drivers/dma/dma_mcux_edma.c +++ b/drivers/dma/dma_mcux_edma.c @@ -24,7 +24,11 @@ #include #include +#ifdef CONFIG_DMA_MCUX_EDMA #define DT_DRV_COMPAT nxp_mcux_edma +#elif CONFIG_DMA_MCUX_EDMA_V3 +#define DT_DRV_COMPAT nxp_mcux_edma_v3 +#endif LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL); @@ -117,8 +121,11 @@ static bool data_size_valid(const size_t data_size) { return (data_size == 4U || data_size == 2U || data_size == 1U || data_size == 8U || - data_size == 16U || - data_size == 32U); + data_size == 16U || data_size == 32U +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + || data_size == 64U +#endif + ); } static void nxp_edma_callback(edma_handle_t *handle, void *param, bool transferDone, @@ -147,8 +154,19 @@ static void dma_mcux_edma_irq_handler(const struct device *dev, uint32_t channel EDMA_HandleIRQ(DEV_EDMA_HANDLE(dev, channel)); LOG_DBG("IRQ DONE"); } + +#if DT_INST_PROP(0, no_error_irq) + /* Channel shares the same irq for error and transfer complete */ + else if (flag & kEDMA_ErrorFlag) { + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, 0xFFFFFFFF); + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, channel)); + DEV_CHANNEL_DATA(dev, channel)->busy = false; + LOG_INF("channel %d error status is 0x%x", channel, flag); + } +#endif } +#if !DT_INST_PROP(0, no_error_irq) static void dma_mcux_edma_error_irq_handler(const struct device *dev) { int i = 0; @@ -168,6 +186,7 @@ static void dma_mcux_edma_error_irq_handler(const struct device *dev) barrier_dsync_fence_full(); #endif } +#endif /* Configure a channel */ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, @@ -311,8 +330,11 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, LOG_ERR("Error submitting EDMA Transfer: 0x%x", submit_status); ret = -EFAULT; } - edma_tcd_t *tcdRegs = (edma_tcd_t *)(uint32_t)&p_handle->base->TCD[channel]; - LOG_DBG("data csr is 0x%x", tcdRegs->CSR); +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[channel].TCD_CSR); +#else + LOG_DBG("data csr is 0x%x", DEV_BASE(dev)->TCD[channel].CSR); +#endif } if (config->dest_chaining_en) { @@ -347,7 +369,10 @@ static int dma_mcux_edma_start(const struct device *dev, uint32_t channel) LOG_DBG("START TRANSFER"); LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]); + +#ifndef CONFIG_DMA_MCUX_EDMA_V3 LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR); +#endif data->busy = true; EDMA_StartTransfer(DEV_EDMA_HANDLE(dev, channel)); return 0; @@ -442,7 +467,6 @@ cleanup: static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel, struct dma_status *status) { - edma_tcd_t *tcdRegs; uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel); uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel); @@ -456,14 +480,24 @@ static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel, } status->dir = DEV_CHANNEL_DATA(dev, channel)->transfer_settings.direction; LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]); + +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + LOG_DBG("DMA MP_CSR 0x%x", DEV_BASE(dev)->MP_CSR); + LOG_DBG("DMA MP_ES 0x%x", DEV_BASE(dev)->MP_ES); + LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->CH[channel].CH_ES); + LOG_DBG("DMA CHx_CSR 0x%x", DEV_BASE(dev)->CH[channel].CH_CSR); + LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->CH[channel].CH_ES); + LOG_DBG("DMA CHx_INT 0x%x", DEV_BASE(dev)->CH[channel].CH_INT); + LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[channel].TCD_CSR); +#else LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR); LOG_DBG("DMA INT 0x%x", DEV_BASE(dev)->INT); LOG_DBG("DMA ERQ 0x%x", DEV_BASE(dev)->ERQ); LOG_DBG("DMA ES 0x%x", DEV_BASE(dev)->ES); LOG_DBG("DMA ERR 0x%x", DEV_BASE(dev)->ERR); LOG_DBG("DMA HRS 0x%x", DEV_BASE(dev)->HRS); - tcdRegs = (edma_tcd_t *)((uint32_t)&DEV_BASE(dev)->TCD[channel]); - LOG_DBG("data csr is 0x%x", tcdRegs->CSR); + LOG_DBG("data csr is 0x%x", DEV_BASE(dev)->TCD[channel].CSR); +#endif return 0; } @@ -507,6 +541,10 @@ static int dma_mcux_edma_init(const struct device *dev) EDMA_GetDefaultConfig(&userConfig); EDMA_Init(DEV_BASE(dev), &userConfig); +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + /* Channel linking available and will be controlled by each channel's link settings */ + EDMA_EnableAllChannelLink(DEV_BASE(dev), true); +#endif config->irq_config_func(dev); memset(dev->data, 0, sizeof(struct dma_mcux_edma_data)); memset(tcdpool, 0, sizeof(tcdpool)); @@ -517,7 +555,11 @@ static int dma_mcux_edma_init(const struct device *dev) } /* The shared error interrupt (if have) must be declared as the last element in devicetree */ +#if !DT_INST_PROP(0, no_error_irq) #define NUM_IRQS_WITHOUT_ERROR_IRQ(n) UTIL_DEC(DT_NUM_IRQS(DT_DRV_INST(n))) +#else +#define NUM_IRQS_WITHOUT_ERROR_IRQ(n) DT_NUM_IRQS(DT_DRV_INST(n)) +#endif #define IRQ_CONFIG(n, idx, fn) \ { \ @@ -552,8 +594,9 @@ static int dma_mcux_edma_init(const struct device *dev) LISTIFY(NUM_IRQS_WITHOUT_ERROR_IRQ(n), \ DMA_MCUX_EDMA_IRQ_CONFIG, (;), n) \ \ - IRQ_CONFIG(n, NUM_IRQS_WITHOUT_ERROR_IRQ(n), \ - dma_mcux_edma_error_irq_handler); \ + IF_ENABLED(UTIL_NOT(DT_INST_NODE_HAS_PROP(n, no_error_irq)), \ + (IRQ_CONFIG(n, NUM_IRQS_WITHOUT_ERROR_IRQ(n), \ + dma_mcux_edma_error_irq_handler))) \ \ LOG_DBG("install irq done"); \ } diff --git a/dts/bindings/dma/nxp,mcux-edma-v3.yaml b/dts/bindings/dma/nxp,mcux-edma-v3.yaml new file mode 100644 index 00000000000..2711c3be124 --- /dev/null +++ b/dts/bindings/dma/nxp,mcux-edma-v3.yaml @@ -0,0 +1,14 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP MCUX EDMA version 3 controller + +compatible: "nxp,mcux-edma-v3" + +include: nxp,mcux-edma.yaml + +properties: + no-error-irq: + type: boolean + description: | + If the SoCs don't have a separate interrupt id for error IRQ.