drivers: dma: Update NXP EDMA driver for version 5
1. The edma version 5 share one driver with edma 4. 2. Edma5 tcd structure some difference, Use tcd type to distinguish, and Edma5 uses 64 bytes for alignment instead of 32. 3. Some platforms have some address offsets for certain memory when processing from a DMA perspective, such as imx95 cm7 TCM, so add offset processing. Signed-off-by: Yongxu Wang <yongxu.wang@nxp.com>
This commit is contained in:
parent
774370a1d7
commit
0bf39e8213
@ -17,6 +17,7 @@ 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_EDMA_V5 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)
|
||||
|
||||
@ -28,7 +28,14 @@ config DMA_MCUX_EDMA_V4
|
||||
help
|
||||
DMA version 4 driver for MCUX series SoCs.
|
||||
|
||||
if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 || DMA_MCUX_EDMA_V4
|
||||
config DMA_MCUX_EDMA_V5
|
||||
bool "MCUX DMA v5 driver"
|
||||
default y
|
||||
depends on $(dt_compat_any_has_prop,$(EDMA_COMPAT),$(REV_PROP),5)
|
||||
help
|
||||
DMA version 5 driver for MCUX series SoCs.
|
||||
|
||||
if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 || DMA_MCUX_EDMA_V4 || DMA_MCUX_EDMA_V5
|
||||
|
||||
config DMA_TCD_QUEUE_SIZE
|
||||
int "number of TCD in a queue for SG mode"
|
||||
@ -55,4 +62,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 || DMA_MCUX_EDMA_V4
|
||||
endif # DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 || DMA_MCUX_EDMA_V4 || DMA_MCUX_EDMA_V5
|
||||
|
||||
@ -30,8 +30,14 @@ LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL);
|
||||
#define HAS_CHANNEL_GAP(n) DT_INST_NODE_HAS_PROP(n, channel_gap) ||
|
||||
#define DMA_MCUX_HAS_CHANNEL_GAP (DT_INST_FOREACH_STATUS_OKAY(HAS_CHANNEL_GAP) 0)
|
||||
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
typedef DMA5_Type DMAx_Type;
|
||||
#else
|
||||
typedef DMA_Type DMAx_Type;
|
||||
#endif
|
||||
|
||||
struct dma_mcux_edma_config {
|
||||
DMA_Type *base;
|
||||
DMAx_Type *base;
|
||||
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
|
||||
DMAMUX_Type **dmamux_base;
|
||||
#endif
|
||||
@ -116,7 +122,7 @@ struct dma_mcux_edma_data {
|
||||
#define DEV_CFG(dev) \
|
||||
((const struct dma_mcux_edma_config *const)dev->config)
|
||||
#define DEV_DATA(dev) ((struct dma_mcux_edma_data *)dev->data)
|
||||
#define DEV_BASE(dev) ((DMA_Type *)DEV_CFG(dev)->base)
|
||||
#define DEV_BASE(dev) ((DMAx_Type *)DEV_CFG(dev)->base)
|
||||
|
||||
#define DEV_CHANNEL_DATA(dev, ch) \
|
||||
((struct call_back *)(&(DEV_DATA(dev)->data_cb[ch])))
|
||||
@ -146,13 +152,13 @@ struct dma_mcux_edma_data {
|
||||
#else
|
||||
#define EDMA_HW_TCD_CH_ACTIVE_MASK (DMA_CSR_ACTIVE_MASK)
|
||||
#endif /* CONFIG_DMA_MCUX_EDMA_V3 */
|
||||
#elif defined(CONFIG_DMA_MCUX_EDMA_V4)
|
||||
#elif defined(CONFIG_DMA_MCUX_EDMA_V4) || defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
/* Above macros have been defined in fsl_edma_core.h */
|
||||
#define EDMA_HW_TCD_CH_ACTIVE_MASK (DMA_CH_CSR_ACTIVE_MASK)
|
||||
#endif
|
||||
|
||||
/* Definations for HW TCD fields */
|
||||
#ifdef CONFIG_DMA_MCUX_EDMA
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA) || defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
#define EDMA_HW_TCD_SADDR(dev, ch) (DEV_BASE(dev)->TCD[ch].SADDR)
|
||||
#define EDMA_HW_TCD_DADDR(dev, ch) (DEV_BASE(dev)->TCD[ch].DADDR)
|
||||
#define EDMA_HW_TCD_BITER(dev, ch) (DEV_BASE(dev)->TCD[ch].BITER_ELINKNO)
|
||||
@ -203,7 +209,8 @@ 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
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA_V3) || defined(CONFIG_DMA_MCUX_EDMA_V4)
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA_V3) || defined(CONFIG_DMA_MCUX_EDMA_V4) \
|
||||
|| defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
|| data_size == 64U
|
||||
#endif
|
||||
);
|
||||
@ -440,14 +447,23 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
|
||||
|
||||
/* Init all TCDs with the para in transfer config and link them. */
|
||||
for (int i = 0; i < CONFIG_DMA_TCD_QUEUE_SIZE; i++) {
|
||||
EDMA_TcdSetTransferConfig(
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
EDMA_TcdSetTransferConfigExt(DEV_BASE(dev),
|
||||
&DEV_CFG(dev)->tcdpool[channel][i], &data->transferConfig,
|
||||
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
|
||||
CONFIG_DMA_TCD_QUEUE_SIZE]);
|
||||
|
||||
CONFIG_DMA_TCD_QUEUE_SIZE]);
|
||||
/* Enable Major loop interrupt.*/
|
||||
EDMA_TcdEnableInterruptsExt(DEV_BASE(dev),
|
||||
&DEV_CFG(dev)->tcdpool[channel][i],
|
||||
kEDMA_MajorInterruptEnable);
|
||||
#else
|
||||
EDMA_TcdSetTransferConfig(&DEV_CFG(dev)->tcdpool[channel][i],
|
||||
&data->transferConfig,
|
||||
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
|
||||
CONFIG_DMA_TCD_QUEUE_SIZE]);
|
||||
EDMA_TcdEnableInterrupts(&DEV_CFG(dev)->tcdpool[channel][i],
|
||||
kEDMA_MajorInterruptEnable);
|
||||
kEDMA_MajorInterruptEnable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Load valid transfer parameters */
|
||||
@ -455,17 +471,33 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
|
||||
tcd = &(DEV_CFG(dev)->tcdpool[channel]
|
||||
[data->transfer_settings.write_idx]);
|
||||
|
||||
EDMA_TCD_SADDR(tcd, kEDMA_EDMA4Flag) = block_config->source_address;
|
||||
EDMA_TCD_DADDR(tcd, kEDMA_EDMA4Flag) = block_config->dest_address;
|
||||
EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) =
|
||||
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
|
||||
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
MEMORY_ConvertMemoryMapAddress(
|
||||
(uint32_t)(block_config->source_address),
|
||||
kMEMORY_Local2DMA);
|
||||
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
MEMORY_ConvertMemoryMapAddress(
|
||||
(uint32_t)(block_config->dest_address),
|
||||
kMEMORY_Local2DMA);
|
||||
#else
|
||||
|
||||
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
block_config->source_address;
|
||||
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
block_config->dest_address;
|
||||
#endif
|
||||
EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
block_config->block_size / config->source_data_size;
|
||||
EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) =
|
||||
EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
block_config->block_size / config->source_data_size;
|
||||
/*Enable auto stop for last transfer.*/
|
||||
if (block_config->next_block == NULL) {
|
||||
EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_DREQ(1U);
|
||||
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) |=
|
||||
DMA_CSR_DREQ(1U);
|
||||
} else {
|
||||
EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~DMA_CSR_DREQ(1U);
|
||||
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) &=
|
||||
~DMA_CSR_DREQ(1U);
|
||||
}
|
||||
|
||||
data->transfer_settings.write_idx =
|
||||
@ -566,7 +598,8 @@ static int dma_mcux_edma_start(const struct device *dev, uint32_t 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)
|
||||
#if !defined(CONFIG_DMA_MCUX_EDMA_V3) && !defined(CONFIG_DMA_MCUX_EDMA_V4) \
|
||||
&& !defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR);
|
||||
#endif
|
||||
data->busy = true;
|
||||
@ -667,13 +700,20 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
|
||||
tcd = &(DEV_CFG(dev)->tcdpool[channel][data->transfer_settings.write_idx]);
|
||||
pre_tcd = &(DEV_CFG(dev)->tcdpool[channel][pre_idx]);
|
||||
|
||||
EDMA_TCD_SADDR(tcd, kEDMA_EDMA4Flag) = src;
|
||||
EDMA_TCD_DADDR(tcd, kEDMA_EDMA4Flag) = dst;
|
||||
EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) = size;
|
||||
EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) = size;
|
||||
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
|
||||
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
MEMORY_ConvertMemoryMapAddress(src, kMEMORY_Local2DMA);
|
||||
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
|
||||
MEMORY_ConvertMemoryMapAddress(dst, kMEMORY_Local2DMA);
|
||||
#else
|
||||
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) = src;
|
||||
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) = dst;
|
||||
#endif
|
||||
EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) = size;
|
||||
EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) = size;
|
||||
/* Enable automatically stop */
|
||||
EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_DREQ(1U);
|
||||
sw_id = EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag);
|
||||
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) |= DMA_CSR_DREQ(1U);
|
||||
sw_id = EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev)));
|
||||
|
||||
/* Block the peripheral's hardware request trigger to prevent
|
||||
* starting the DMA before updating the TCDs. Make sure the
|
||||
@ -704,7 +744,8 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
|
||||
/* Previous TCD can automatically start this TCD.
|
||||
* Enable the peripheral DMA request in the previous TCD
|
||||
*/
|
||||
EDMA_TCD_CSR(pre_tcd, kEDMA_EDMA4Flag) &= ~DMA_CSR_DREQ(1U);
|
||||
EDMA_TCD_CSR(pre_tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) &=
|
||||
~DMA_CSR_DREQ(1U);
|
||||
|
||||
if (data->transfer_settings.empty_tcds == CONFIG_DMA_TCD_QUEUE_SIZE - 1 ||
|
||||
hw_id == (uint32_t)tcd) {
|
||||
@ -723,7 +764,7 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel,
|
||||
*/
|
||||
EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, kEDMA_DoneFlag);
|
||||
EDMA_HW_TCD_CSR(dev, channel) |= DMA_CSR_ESG_MASK;
|
||||
#elif (CONFIG_DMA_MCUX_EDMA_V3 || CONFIG_DMA_MCUX_EDMA_V4)
|
||||
#elif (CONFIG_DMA_MCUX_EDMA_V3 || CONFIG_DMA_MCUX_EDMA_V4 || CONFIG_DMA_MCUX_EDMA_V5)
|
||||
/*We have not verified if this issue exist on V3/V4 HW, jut place a holder here. */
|
||||
#endif
|
||||
/* TCDs are configured. Resume DMA */
|
||||
@ -802,6 +843,14 @@ static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel,
|
||||
LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_ES);
|
||||
LOG_DBG("DMA CHx_INT 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_INT);
|
||||
LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[hw_channel].TCD_CSR);
|
||||
#elif defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
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)->TCD[hw_channel].CH_ES);
|
||||
LOG_DBG("DMA CHx_CSR 0x%x", DEV_BASE(dev)->TCD[hw_channel].CH_CSR);
|
||||
LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->TCD[hw_channel].CH_ES);
|
||||
LOG_DBG("DMA CHx_INT 0x%x", DEV_BASE(dev)->TCD[hw_channel].CH_INT);
|
||||
LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->TCD[hw_channel].CSR);
|
||||
#else
|
||||
LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR);
|
||||
LOG_DBG("DMA INT 0x%x", DEV_BASE(dev)->INT);
|
||||
@ -957,16 +1006,22 @@ static int dma_mcux_edma_init(const struct device *dev)
|
||||
#define CHANNELS_PER_MUX(n)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DMA_MCUX_EDMA_V5)
|
||||
#define DMA_TCD_ALIGN_SIZE 64
|
||||
#else
|
||||
#define DMA_TCD_ALIGN_SIZE 32
|
||||
#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 __aligned(32) EDMA_TCDPOOL_CACHE_ATTR edma_tcd_t \
|
||||
static __aligned(DMA_TCD_ALIGN_SIZE) EDMA_TCDPOOL_CACHE_ATTR edma_tcd_t \
|
||||
dma_tcdpool##n[DT_INST_PROP(n, dma_channels)][CONFIG_DMA_TCD_QUEUE_SIZE];\
|
||||
static const struct dma_mcux_edma_config dma_config_##n = { \
|
||||
.base = (DMA_Type *)DT_INST_REG_ADDR(n), \
|
||||
.base = (DMAx_Type *)DT_INST_REG_ADDR(n), \
|
||||
DMAMUX_BASE_INIT(n) \
|
||||
.dma_requests = DT_INST_PROP(n, dma_requests), \
|
||||
.dma_channels = DT_INST_PROP(n, dma_channels), \
|
||||
|
||||
@ -18,4 +18,7 @@
|
||||
#include "fsl_dmamux.h"
|
||||
#endif
|
||||
|
||||
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
|
||||
#include "fsl_memory.h"
|
||||
#endif
|
||||
#endif /* DMA_MCUX_EDMA_H_*/
|
||||
|
||||
@ -62,6 +62,7 @@ properties:
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
description: |
|
||||
eDMA IP revision number.
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ set_variable_ifdef(CONFIG_DMA_MCUX_EDMA CONFIG_MCUX_COMPONENT_driver.edm
|
||||
set_variable_ifdef(CONFIG_DMA_MCUX_EDMA_V3 CONFIG_MCUX_COMPONENT_driver.dma3)
|
||||
set_variable_ifdef(CONFIG_DMA_MCUX_EDMA_V4 CONFIG_MCUX_COMPONENT_driver.edma4)
|
||||
set_variable_ifdef(CONFIG_DMA_NXP_EDMA CONFIG_MCUX_COMPONENT_driver.edma_rev2)
|
||||
set_variable_ifdef(CONFIG_DMA_MCUX_EDMA_V5 CONFIG_MCUX_COMPONENT_driver.edma4)
|
||||
set_variable_ifdef(CONFIG_ENTROPY_MCUX_RNGA CONFIG_MCUX_COMPONENT_driver.rnga)
|
||||
set_variable_ifdef(CONFIG_ENTROPY_MCUX_TRNG CONFIG_MCUX_COMPONENT_driver.trng)
|
||||
set_variable_ifdef(CONFIG_ENTROPY_MCUX_CAAM CONFIG_MCUX_COMPONENT_driver.caam)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user