drivers: dma: Update NXP EDMA driver for version 4

1. Update EDMA driver for version 4
2. The DMAMux module is not always present. Use the
   feature define to make this optional.
3. Use the EDMA_SetChannelMux API for SoC's that supports
   this feature.

Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
This commit is contained in:
Mahesh Mahadevan 2023-03-14 11:54:16 -05:00 committed by Anas Nashif
parent f9e3084daf
commit 55abfcb31e
5 changed files with 91 additions and 27 deletions

View file

@ -16,6 +16,7 @@ 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_EDMA_V4 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

@ -18,7 +18,14 @@ config DMA_MCUX_EDMA_V3
help
DMA version 3 driver for MCUX series SoCs.
if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3
config DMA_MCUX_EDMA_V4
bool "MCUX DMA v4 driver"
default y
depends on DT_HAS_NXP_MCUX_EDMA_V4_ENABLED
help
DMA version 4 driver for MCUX series SoCs.
if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 || DMA_MCUX_EDMA_V4
config DMA_TCD_QUEUE_SIZE
int "number of TCD in a queue for SG mode"
@ -41,4 +48,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 || DMA_MCUX_EDMA_V3
endif # DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 || DMA_MCUX_EDMA_V4

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 NXP Semiconductor INC.
* All rights reserved.
* Copyright 2020-23 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -28,6 +27,8 @@
#define DT_DRV_COMPAT nxp_mcux_edma
#elif CONFIG_DMA_MCUX_EDMA_V3
#define DT_DRV_COMPAT nxp_mcux_edma_v3
#elif CONFIG_DMA_MCUX_EDMA_V4
#define DT_DRV_COMPAT nxp_mcux_edma_v4
#endif
LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL);
@ -37,7 +38,9 @@ LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL);
struct dma_mcux_edma_config {
DMA_Type *base;
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
DMAMUX_Type **dmamux_base;
#endif
uint8_t channels_per_mux;
uint8_t dmamux_reg_offset;
int dma_channels; /* number of channels */
@ -120,11 +123,13 @@ struct dma_mcux_edma_data {
#define DEV_EDMA_HANDLE(dev, ch) \
((edma_handle_t *)(&(DEV_CHANNEL_DATA(dev, ch)->edma_handle)))
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#define DEV_DMAMUX_BASE(dev, idx) ((DMAMUX_Type *)DEV_CFG(dev)->dmamux_base[idx])
#define DEV_DMAMUX_IDX(dev, ch) (ch / DEV_CFG(dev)->channels_per_mux)
#define DEV_DMAMUX_CHANNEL(dev, ch) \
(ch % DEV_CFG(dev)->channels_per_mux) ^ (DEV_CFG(dev)->dmamux_reg_offset)
#endif
/*
* The hardware channel (takes the gap into account) is used when access DMA registers.
@ -163,7 +168,7 @@ 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
#ifdef CONFIG_DMA_MCUX_EDMA_V3
#if defined(CONFIG_DMA_MCUX_EDMA_V3) || defined(CONFIG_DMA_MCUX_EDMA_V4)
|| data_size == 64U
#endif
);
@ -246,7 +251,6 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
struct dma_block_config *block_config = config->head_block;
uint32_t slot = config->dma_slot;
uint8_t dmamux_idx, dmamux_channel;
uint32_t hw_channel;
edma_transfer_type_t transfer_type;
unsigned int key;
@ -263,8 +267,12 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
}
hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
uint8_t dmamux_idx, dmamux_channel;
dmamux_idx = DEV_DMAMUX_IDX(dev, channel);
dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel);
#endif
data->transfer_settings.valid = false;
switch (config->channel_direction) {
@ -314,6 +322,8 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
/* Lock and page in the channel configuration */
key = irq_lock();
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#if DT_INST_PROP(0, nxp_a_on)
if (config->source_handshake || config->dest_handshake ||
transfer_type == kEDMA_MemoryToMemory) {
@ -330,6 +340,8 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
/* dam_imx_rt_set_channel_priority(dev, channel, config); */
DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel);
#endif
if (data->busy) {
EDMA_AbortTransfer(p_handle);
}
@ -337,6 +349,12 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
EDMA_CreateHandle(p_handle, DEV_BASE(dev), hw_channel);
EDMA_SetCallback(p_handle, nxp_edma_callback, (void *)data);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
/* First release any peripheral previously associated with this channel */
EDMA_SetChannelMux(DEV_BASE(dev), hw_channel, 0);
EDMA_SetChannelMux(DEV_BASE(dev), hw_channel, slot);
#endif
LOG_DBG("channel is %d", channel);
EDMA_EnableChannelInterrupts(DEV_BASE(dev), hw_channel, kEDMA_ErrorInterruptEnable);
@ -377,7 +395,7 @@ 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;
}
#ifdef CONFIG_DMA_MCUX_EDMA_V3
#if defined(CONFIG_DMA_MCUX_EDMA_V3) || defined(CONFIG_DMA_MCUX_EDMA_V4)
LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[hw_channel].TCD_CSR);
#else
LOG_DBG("data csr is 0x%x", DEV_BASE(dev)->TCD[hw_channel].CSR);
@ -411,13 +429,17 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
static int dma_mcux_edma_start(const struct device *dev, uint32_t channel)
{
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
LOG_DBG("START TRANSFER");
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel);
uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel);
LOG_DBG("START TRANSFER");
LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]);
#endif
#ifndef CONFIG_DMA_MCUX_EDMA_V3
#if !defined(CONFIG_DMA_MCUX_EDMA_V3) && !defined(CONFIG_DMA_MCUX_EDMA_V4)
LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR);
#endif
data->busy = true;
@ -518,9 +540,6 @@ cleanup:
static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel,
struct dma_status *status)
{
uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel);
uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel);
uint32_t hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
if (DEV_CHANNEL_DATA(dev, channel)->busy) {
@ -532,9 +551,15 @@ static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel,
status->pending_length = 0;
}
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
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel);
uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel);
LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]);
#endif
#if defined(CONFIG_DMA_MCUX_EDMA_V3) || defined(CONFIG_DMA_MCUX_EDMA_V4)
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[hw_channel].CH_ES);
@ -584,13 +609,16 @@ static int dma_mcux_edma_init(const struct device *dev)
struct dma_mcux_edma_data *data = dev->data;
edma_config_t userConfig = { 0 };
uint8_t i;
LOG_DBG("INIT NXP EDMA");
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
uint8_t i;
for (i = 0; i < config->dma_channels / config->channels_per_mux; i++) {
DMAMUX_Init(DEV_DMAMUX_BASE(dev, i));
}
#endif
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DEV_BASE(dev), &userConfig);
@ -654,9 +682,6 @@ static int dma_mcux_edma_init(const struct device *dev)
LOG_DBG("install irq done"); \
}
#define DMA_MCUX_EDMA_MUX(idx, n) \
(DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(n, UTIL_INC(idx))
#if DMA_MCUX_HAS_CHANNEL_GAP
#define DMA_MCUX_EDMA_CHANNEL_GAP(n) \
.channel_gap = DT_INST_PROP_OR(n, channel_gap, \
@ -665,21 +690,37 @@ static int dma_mcux_edma_init(const struct device *dev)
#define DMA_MCUX_EDMA_CHANNEL_GAP(n)
#endif
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#define DMA_MCUX_EDMA_MUX(idx, n) \
(DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(n, UTIL_INC(idx))
#define DMAMUX_BASE_INIT_DEFINE(n) \
static DMAMUX_Type *dmamux_base_##n[] = { \
LISTIFY(UTIL_DEC(DT_NUM_REGS(DT_DRV_INST(n))), \
DMA_MCUX_EDMA_MUX, (,), n) \
};
#define DMAMUX_BASE_INIT(n) .dmamux_base = &dmamux_base_##n[0],
#define CHANNELS_PER_MUX(n) .channels_per_mux = DT_INST_PROP(n, dma_channels) / \
ARRAY_SIZE(dmamux_base_##n),
#else
#define DMAMUX_BASE_INIT_DEFINE(n)
#define DMAMUX_BASE_INIT(n)
#define CHANNELS_PER_MUX(n)
#endif
/*
* define the dma
*/
#define DMA_INIT(n) \
DMAMUX_BASE_INIT_DEFINE(n) \
static void dma_imx_config_func_##n(const struct device *dev); \
static DMAMUX_Type *dmamux_base_##n[] = { \
LISTIFY(UTIL_DEC(DT_NUM_REGS(DT_DRV_INST(n))), \
DMA_MCUX_EDMA_MUX, (,), n) \
}; \
static const struct dma_mcux_edma_config dma_config_##n = { \
.base = (DMA_Type *)DT_INST_REG_ADDR(n), \
.dmamux_base = &dmamux_base_##n[0], \
DMAMUX_BASE_INIT(n) \
.dma_channels = DT_INST_PROP(n, dma_channels), \
.channels_per_mux = DT_INST_PROP(n, dma_channels) / \
ARRAY_SIZE(dmamux_base_##n), \
CHANNELS_PER_MUX(n) \
.irq_config_func = dma_imx_config_func_##n, \
.dmamux_reg_offset = DT_INST_PROP(n, dmamux_reg_offset), \
DMA_MCUX_EDMA_CHANNEL_GAP(n) \

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 NXP Semiconductor INC.
* All rights reserved.
* Copyright 2020-23 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,6 +14,8 @@
#include <fsl_common.h>
#include "fsl_edma.h"
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#include "fsl_dmamux.h"
#endif
#endif /* DMA_MCUX_EDMA_H_*/

View file

@ -0,0 +1,14 @@
# Copyright 2024 NXP
# SPDX-License-Identifier: Apache-2.0
description: NXP MCUX EDMA version 4 controller
compatible: "nxp,mcux-edma-v4"
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.