drivers: dma_mcux_edma: add support for multiple DMAMuxes
This adds support for platforms that have multiple DMAMUXes per DMA instance Signed-off-by: Dat Nguyen Duy <dat.nguyenduy@nxp.com>
This commit is contained in:
parent
f27815d645
commit
03b5ba5990
1 changed files with 51 additions and 28 deletions
|
@ -30,7 +30,8 @@ LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL);
|
|||
|
||||
struct dma_mcux_edma_config {
|
||||
DMA_Type *base;
|
||||
DMAMUX_Type *dmamux_base;
|
||||
DMAMUX_Type **dmamux_base;
|
||||
uint8_t channels_per_mux;
|
||||
int dma_channels; /* number of channels */
|
||||
void (*irq_config_func)(const struct device *dev);
|
||||
};
|
||||
|
@ -102,14 +103,16 @@ struct dma_mcux_edma_data {
|
|||
#define DEV_DATA(dev) ((struct dma_mcux_edma_data *)dev->data)
|
||||
#define DEV_BASE(dev) ((DMA_Type *)DEV_CFG(dev)->base)
|
||||
|
||||
#define DEV_DMAMUX_BASE(dev) ((DMAMUX_Type *)DEV_CFG(dev)->dmamux_base)
|
||||
|
||||
#define DEV_CHANNEL_DATA(dev, ch) \
|
||||
((struct call_back *)(&(DEV_DATA(dev)->data_cb[ch])))
|
||||
|
||||
#define DEV_EDMA_HANDLE(dev, ch) \
|
||||
((edma_handle_t *)(&(DEV_CHANNEL_DATA(dev, ch)->edma_handle)))
|
||||
|
||||
#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)
|
||||
|
||||
static bool data_size_valid(const size_t data_size)
|
||||
{
|
||||
return (data_size == 4U || data_size == 2U ||
|
||||
|
@ -188,6 +191,7 @@ 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;
|
||||
edma_transfer_type_t transfer_type;
|
||||
unsigned int key;
|
||||
int ret = 0;
|
||||
|
@ -202,6 +206,8 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
dmamux_idx = DEV_DMAMUX_IDX(dev, channel);
|
||||
dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel);
|
||||
data->transfer_settings.valid = false;
|
||||
|
||||
switch (config->channel_direction) {
|
||||
|
@ -256,16 +262,16 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
|
|||
transfer_type == kEDMA_MemoryToMemory) {
|
||||
/*software trigger make the channel always on*/
|
||||
LOG_DBG("ALWAYS ON");
|
||||
DMAMUX_EnableAlwaysOn(DEV_DMAMUX_BASE(dev), channel, true);
|
||||
DMAMUX_EnableAlwaysOn(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, true);
|
||||
} else {
|
||||
DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot);
|
||||
DMAMUX_SetSource(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, slot);
|
||||
}
|
||||
#else
|
||||
DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot);
|
||||
DMAMUX_SetSource(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, slot);
|
||||
#endif
|
||||
|
||||
/* dam_imx_rt_set_channel_priority(dev, channel, config); */
|
||||
DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev), channel);
|
||||
DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel);
|
||||
|
||||
if (data->busy) {
|
||||
EDMA_AbortTransfer(p_handle);
|
||||
|
@ -345,9 +351,11 @@ 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);
|
||||
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)->CHCFG[channel]);
|
||||
LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]);
|
||||
LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR);
|
||||
data->busy = true;
|
||||
EDMA_StartTransfer(DEV_EDMA_HANDLE(dev, channel));
|
||||
|
@ -444,6 +452,8 @@ 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);
|
||||
|
||||
if (DEV_CHANNEL_DATA(dev, channel)->busy) {
|
||||
status->busy = true;
|
||||
|
@ -454,7 +464,7 @@ 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)->CHCFG[channel]);
|
||||
LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]);
|
||||
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);
|
||||
|
@ -496,9 +506,14 @@ 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");
|
||||
DMAMUX_Init(DEV_DMAMUX_BASE(dev));
|
||||
|
||||
for (i = 0; i < config->dma_channels / config->channels_per_mux; i++) {
|
||||
DMAMUX_Init(DEV_DMAMUX_BASE(dev, i));
|
||||
}
|
||||
|
||||
EDMA_GetDefaultConfig(&userConfig);
|
||||
EDMA_Init(DEV_BASE(dev), &userConfig);
|
||||
config->irq_config_func(dev);
|
||||
|
@ -546,27 +561,35 @@ 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))
|
||||
|
||||
/*
|
||||
* define the dma
|
||||
*/
|
||||
#define DMA_INIT(n) \
|
||||
static void dma_imx_config_func_##n(const struct device *dev); \
|
||||
static const struct dma_mcux_edma_config dma_config_##n = { \
|
||||
.base = (DMA_Type *)DT_INST_REG_ADDR(n), \
|
||||
.dmamux_base = \
|
||||
(DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(n, 1), \
|
||||
.dma_channels = DT_INST_PROP(n, dma_channels), \
|
||||
.irq_config_func = dma_imx_config_func_##n, \
|
||||
}; \
|
||||
\
|
||||
struct dma_mcux_edma_data dma_data_##n; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
&dma_mcux_edma_init, NULL, \
|
||||
&dma_data_##n, &dma_config_##n, \
|
||||
PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \
|
||||
&dma_mcux_edma_api); \
|
||||
\
|
||||
#define DMA_INIT(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], \
|
||||
.dma_channels = DT_INST_PROP(n, dma_channels), \
|
||||
.channels_per_mux = DT_INST_PROP(n, dma_channels) / \
|
||||
ARRAY_SIZE(dmamux_base_##n), \
|
||||
.irq_config_func = dma_imx_config_func_##n, \
|
||||
}; \
|
||||
\
|
||||
struct dma_mcux_edma_data dma_data_##n; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
&dma_mcux_edma_init, NULL, \
|
||||
&dma_data_##n, &dma_config_##n, \
|
||||
PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \
|
||||
&dma_mcux_edma_api); \
|
||||
\
|
||||
DMA_MCUX_EDMA_CONFIG_FUNC(n);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DMA_INIT)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue