drivers: dma_mcux_edma: add support for edma version 3

Add new dt binding for edma v3 that inherits whole dt
properties from current version. One more property is
added for SoCs that don't have separate error interrupt
id, use same id with channel interrupt

Signed-off-by: Dat Nguyen Duy <dat.nguyenduy@nxp.com>
This commit is contained in:
Dat Nguyen Duy 2023-06-14 08:58:39 +07:00 committed by David Leach
commit d4a2b2244f
4 changed files with 76 additions and 11 deletions

View file

@ -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)

View file

@ -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

View file

@ -24,7 +24,11 @@
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
#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"); \
}

View file

@ -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.