From 10fc7a38ccbcca4b3a0e1743ea008b7f1ea331cc Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Fri, 15 May 2020 17:49:42 +0800 Subject: [PATCH] dma: add EDMA MCUX support for RT and k6s tested on mimxrt1060_evt MEMORY_NOCACHE is needed test on frdmk64f special test slot need configure with CONFIG_DMA_TEST_SLOT_START Signed-off-by: Hake Huang --- boards/arm/frdm_k64f/frdm_k64f.dts | 4 + boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts | 5 + boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml | 1 + drivers/dma/CMakeLists.txt | 1 + drivers/dma/Kconfig | 2 + drivers/dma/Kconfig.mcux_edma | 29 + drivers/dma/dma_mcux_edma.c | 536 ++++++++++++++++++ drivers/dma/dma_mcux_edma.h | 20 + modules/Kconfig.mcux | 5 + soc/arm/nxp_imx/rt/Kconfig.defconfig.series | 4 + soc/arm/nxp_imx/rt/Kconfig.soc | 8 + .../nxp_kinetis/k6x/Kconfig.defconfig.series | 4 + soc/arm/nxp_kinetis/k6x/Kconfig.soc | 2 + 13 files changed, 621 insertions(+) create mode 100644 drivers/dma/Kconfig.mcux_edma create mode 100644 drivers/dma/dma_mcux_edma.c create mode 100644 drivers/dma/dma_mcux_edma.h diff --git a/boards/arm/frdm_k64f/frdm_k64f.dts b/boards/arm/frdm_k64f/frdm_k64f.dts index ec2152672f..cf6a823be8 100644 --- a/boards/arm/frdm_k64f/frdm_k64f.dts +++ b/boards/arm/frdm_k64f/frdm_k64f.dts @@ -218,3 +218,7 @@ arduino_spi: &spi0 { status = "okay"; bus-speed = <125000>; }; + +&edma0 { + status = "okay"; +}; diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts index e9793d55b1..4fb548bd60 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts @@ -140,4 +140,9 @@ arduino_serial: &lpuart3 {}; status = "okay"; pwr-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; cd-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&edma0 { + status = "okay"; }; diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml index 984769869e..c2bb5633de 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml @@ -24,3 +24,4 @@ supported: - sdhc - usb_device - kscan:touch + - dma diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index 4a55b9a3e5..c5314d2dc9 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -11,3 +11,4 @@ zephyr_library_sources_ifdef(CONFIG_DMA_DW dma_dw.c) 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) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 896fcf9fad..c5099848e9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -48,4 +48,6 @@ source "drivers/dma/Kconfig.nios2_msgdma" source "drivers/dma/Kconfig.sam0" +source "drivers/dma/Kconfig.mcux_edma" + endif # DMA diff --git a/drivers/dma/Kconfig.mcux_edma b/drivers/dma/Kconfig.mcux_edma new file mode 100644 index 0000000000..abf56df130 --- /dev/null +++ b/drivers/dma/Kconfig.mcux_edma @@ -0,0 +1,29 @@ +# DMA configuration options + +# Copyright (c) 2020, NXP +# SPDX-License-Identifier: Apache-2.0 + +config DMA_MCUX_EDMA + bool "Enable MCUX DMA driver" + depends on HAS_MCUX_EDMA + select NOCACHE_MEMORY if HAS_MCUX_CACHE + help + DMA driver for MCUX series SoCs. + +if DMA_MCUX_EDMA + +config DMA_TCD_QUEUE_SIZE + int "number of TCD in a queue for SG mode" + default 2 + help + number of TCD in a queue for SG mode + +config DMA_MCUX_TEST_SLOT_START + int "test slot start num" + depends on SOC_SERIES_KINETIS_K6X + default 58 + help + test slot start num + + +endif # DMA_MCUX_EDMA diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c new file mode 100644 index 0000000000..c16ae54ccd --- /dev/null +++ b/drivers/dma/dma_mcux_edma.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2020 NXP Semiconductor INC. + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Common part of DMA drivers for imx rt series. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dma_mcux_edma.h" + +#include + +#define DT_DRV_COMPAT nxp_mcux_edma + +LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL); + +struct dma_mcux_edma_config { + DMA_Type *base; + DMAMUX_Type *dmamux_base; + void (*irq_config_func)(struct device *dev); +}; + +static __aligned(32) edma_tcd_t + tcdpool[DT_INST_PROP(0, dma_channels)][CONFIG_DMA_TCD_QUEUE_SIZE]; + +struct call_back { + edma_transfer_config_t transferConfig; + edma_handle_t edma_handle; + void *callback_arg; + void (*dma_callback)(void *callback_arg, uint32_t channel, + int error_code); + enum dma_channel_direction dir; + bool busy; +}; + +struct dma_mcux_edma_data { + struct call_back data_cb[DT_INST_PROP(0, dma_channels)]; +}; + +#define DEV_CFG(dev) \ + ((const struct dma_mcux_edma_config *const)dev->config_info) +#define DEV_DATA(dev) ((struct dma_mcux_edma_data *)dev->driver_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))) + +static void nxp_edma_callback(edma_handle_t *handle, void *param, + bool transferDone, uint32_t tcds) +{ + int ret = 1; + struct call_back *data = (struct call_back *)param; + uint32_t channel = handle->channel; + + if (transferDone) { + data->busy = false; + ret = 0; + } + LOG_DBG("transfer %d", tcds); + data->dma_callback(data->callback_arg, channel, ret); +} + +static void channel_irq(edma_handle_t *handle) +{ + bool transfer_done; + + /* Clear EDMA interrupt flag */ + handle->base->CINT = handle->channel; + /* Check if transfer is already finished. */ + transfer_done = ((handle->base->TCD[handle->channel].CSR & + DMA_CSR_DONE_MASK) != 0U); + + if (handle->tcdPool == NULL) { + (handle->callback)(handle, handle->userData, transfer_done, 0); + } else { + uint32_t sga = handle->base->TCD[handle->channel].DLAST_SGA; + uint32_t sga_index; + int32_t tcds_done; + uint8_t new_header; + + sga -= (uint32_t)handle->tcdPool; + sga_index = sga / sizeof(edma_tcd_t); + /* Adjust header positions. */ + if (transfer_done) { + new_header = (uint8_t)sga_index; + } else { + new_header = sga_index != 0U ? + (uint8_t)sga_index - 1U : + (uint8_t)handle->tcdSize - 1U; + } + /* Calculate the number of finished TCDs */ + if (new_header == (uint8_t)handle->header) { + int8_t tmpTcdUsed = handle->tcdUsed; + int8_t tmpTcdSize = handle->tcdSize; + + if (tmpTcdUsed == tmpTcdSize) { + tcds_done = handle->tcdUsed; + } else { + tcds_done = 0; + } + } else { + tcds_done = (uint32_t)new_header - (uint32_t)handle->header; + if (tcds_done < 0) { + tcds_done += handle->tcdSize; + } + } + + handle->header = (int8_t)new_header; + handle->tcdUsed -= (int8_t)tcds_done; + /* Invoke callback function. */ + if (handle->callback != NULL) { + (handle->callback)(handle, handle->userData, + transfer_done, tcds_done); + } + + if (transfer_done) { + handle->base->CDNE = handle->channel; + } + } +} + +static void dma_mcux_edma_irq_handler(void *arg) +{ + struct device *dev = (struct device *)arg; + int i = 0; + + LOG_DBG("IRQ CALLED"); + for (i = 0; i < DT_INST_PROP(0, dma_channels); i++) { + if (DEV_CHANNEL_DATA(dev, i)->busy) { + uint32_t flag = + EDMA_GetChannelStatusFlags(DEV_BASE(dev), i); + if ((flag & (uint32_t)kEDMA_InterruptFlag) != 0U) { + LOG_DBG("IRQ OCCURRED"); + channel_irq(DEV_EDMA_HANDLE(dev, i)); + LOG_DBG("IRQ DONE"); +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif + } else { + LOG_DBG("flag is 0x%x", flag); + LOG_DBG("DMA ES 0x%x", DEV_BASE(dev)->ES); + LOG_DBG("channel id %d", i); + EDMA_ClearChannelStatusFlags( + DEV_BASE(dev), i, + kEDMA_ErrorFlag | kEDMA_DoneFlag); + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, i)); + } + } + } +} + +static void dma_mcux_edma_error_irq_handler(void *arg) +{ + int i = 0; + uint32_t flag = 0; + struct device *dev = (struct device *)arg; + + for (i = 0; i < DT_INST_PROP(0, dma_channels); i++) { + if (DEV_CHANNEL_DATA(dev, i)->busy) { + flag = EDMA_GetChannelStatusFlags(DEV_BASE(dev), i); + LOG_INF("channel %d error status is 0x%x", i, flag); + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), i, + 0xFFFFFFFF); + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, i)); + DEV_CHANNEL_DATA(dev, i)->busy = false; + } + } + +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} + +/* Configure a channel */ +static int dma_mcux_edma_configure(struct device *dev, uint32_t channel, + struct dma_config *config) +{ + edma_handle_t *p_handle = DEV_EDMA_HANDLE(dev, 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; + edma_transfer_type_t transfer_type; + int key; + + if (NULL == dev || NULL == config) { + return -EINVAL; + } + + if (slot > DT_INST_PROP(0, dma_requests)) { + LOG_ERR("source number is outof scope %d", slot); + return -ENOTSUP; + } + + if (channel > DT_INST_PROP(0, dma_channels)) { + LOG_ERR("out of DMA channel %d", channel); + return -EINVAL; + } + + data->dir = config->channel_direction; + switch (config->channel_direction) { + case MEMORY_TO_MEMORY: + transfer_type = kEDMA_MemoryToMemory; + break; + case MEMORY_TO_PERIPHERAL: + transfer_type = kEDMA_MemoryToPeripheral; + break; + case PERIPHERAL_TO_MEMORY: + transfer_type = kEDMA_PeripheralToMemory; + break; + case PERIPHERAL_TO_PERIPHERAL: + transfer_type = kEDMA_PeripheralToPeripheral; + break; + default: + LOG_ERR("not support transfer direction"); + return -EINVAL; + } + + /* Lock and page in the channel configuration */ + key = irq_lock(); + +#if DT_INST_PROP(0, nxp_a_on) + if (config->source_handshake || config->dest_handshake || + transfer_type == kEDMA_MemoryToMemory) { + /*software trigger make the channel always on*/ + LOG_DBG("ALWAYS ON"); + DMAMUX_EnableAlwaysOn(DEV_DMAMUX_BASE(dev), channel, true); + } else { + DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot); + } +#else + DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot); +#endif + + /* dam_imx_rt_set_channel_priority(dev, channel, config); */ + DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev), channel); + + if (data->busy) { + EDMA_AbortTransfer(p_handle); + } + EDMA_ResetChannel(DEV_BASE(dev), channel); + EDMA_CreateHandle(p_handle, DEV_BASE(dev), channel); + EDMA_SetCallback(p_handle, nxp_edma_callback, (void *)data); + + LOG_DBG("channel is %d", p_handle->channel); + + if (config->source_data_size != 4U && config->source_data_size != 2U && + config->source_data_size != 1U && config->source_data_size != 8U && + config->source_data_size != 16U && + config->source_data_size != 32U) { + LOG_ERR("Source unit size error, %d", config->source_data_size); + return -EINVAL; + } + + if (config->dest_data_size != 4U && config->dest_data_size != 2U && + config->dest_data_size != 1U && config->dest_data_size != 8U && + config->dest_data_size != 16U && config->dest_data_size != 32U) { + LOG_ERR("Dest unit size error, %d", config->dest_data_size); + return -EINVAL; + } + + EDMA_EnableChannelInterrupts(DEV_BASE(dev), channel, + kEDMA_ErrorInterruptEnable); + + if (config->source_chaining_en && config->dest_chaining_en) { + /*chaining mode only support major link*/ + LOG_DBG("link major channel %d", config->linked_channel); + EDMA_SetChannelLink(DEV_BASE(dev), channel, kEDMA_MajorLink, + config->linked_channel); + } + + if (block_config->source_gather_en || block_config->dest_scatter_en) { + if (config->block_count > CONFIG_DMA_TCD_QUEUE_SIZE) { + LOG_ERR("please config DMA_TCD_QUEUE_SIZE as %d", + config->block_count); + return -EINVAL; + } + EDMA_InstallTCDMemory(p_handle, tcdpool[channel], + CONFIG_DMA_TCD_QUEUE_SIZE); + while (block_config != NULL) { + EDMA_PrepareTransfer( + &(data->transferConfig), + (void *)block_config->source_address, + config->source_data_size, + (void *)block_config->dest_address, + config->dest_data_size, + config->source_burst_length, + block_config->block_size, transfer_type); + EDMA_SubmitTransfer(p_handle, &(data->transferConfig)); + block_config = block_config->next_block; + } + } else { + /* block_count shall be 1 */ + status_t ret; + + EDMA_PrepareTransfer(&(data->transferConfig), + (void *)block_config->source_address, + config->source_data_size, + (void *)block_config->dest_address, + config->dest_data_size, + config->source_burst_length, + block_config->block_size, transfer_type); + + ret = EDMA_SubmitTransfer(p_handle, &(data->transferConfig)); + edma_tcd_t *tcdRegs = + (edma_tcd_t *)(uint32_t)&p_handle->base->TCD[channel]; + if (ret != kStatus_Success) { + LOG_ERR("submit error 0x%x", ret); + } + LOG_DBG("data csr is 0x%x", tcdRegs->CSR); + } + + data->busy = false; + if (config->dma_callback) { + LOG_DBG("INSTALL call back on channel %d", channel); + data->callback_arg = config->callback_arg; + data->dma_callback = config->dma_callback; + } + + irq_unlock(key); + + return 0; +} + +static int dma_mcux_edma_start(struct device *dev, uint32_t channel) +{ + struct call_back *data = DEV_CHANNEL_DATA(dev, channel); + + LOG_DBG("START TRANSFER"); + LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev)->CHCFG[channel]); + LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR); + data->busy = true; + EDMA_StartTransfer(DEV_EDMA_HANDLE(dev, channel)); + return 0; +} + +static int dma_mcux_edma_stop(struct device *dev, uint32_t channel) +{ + struct dma_mcux_edma_data *data = DEV_DATA(dev); + + if (!data->data_cb[channel].busy) { + return 0; + } + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, channel)); + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, + kEDMA_DoneFlag | kEDMA_ErrorFlag | + kEDMA_InterruptFlag); + EDMA_ResetChannel(DEV_BASE(dev), channel); + data->data_cb[channel].busy = false; + return 0; +} + +static int dma_mcux_edma_reload(struct device *dev, uint32_t channel, + uint32_t src, uint32_t dst, size_t size) +{ + struct call_back *data = DEV_CHANNEL_DATA(dev, channel); + + if (data->busy) { + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, channel)); + } + return 0; +} + +static int dma_mcux_edma_get_status(struct device *dev, uint32_t channel, + struct dma_status *status) +{ + edma_tcd_t *tcdRegs; + + if (DEV_CHANNEL_DATA(dev, channel)->busy) { + status->busy = true; + status->pending_length = + EDMA_GetRemainingMajorLoopCount(DEV_BASE(dev), channel); + } else { + status->busy = false; + status->pending_length = 0; + } + status->dir = DEV_CHANNEL_DATA(dev, channel)->dir; + LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev)->CHCFG[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); + 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); + return 0; +} + +static const struct dma_driver_api dma_mcux_edma_api = { + .reload = dma_mcux_edma_reload, + .config = dma_mcux_edma_configure, + .start = dma_mcux_edma_start, + .stop = dma_mcux_edma_stop, + .get_status = dma_mcux_edma_get_status, +}; + +static int dma_mcux_edma_init(struct device *dev) +{ + edma_config_t userConfig = { 0 }; + + LOG_DBG("INIT NXP EDMA"); + DMAMUX_Init(DEV_DMAMUX_BASE(dev)); + EDMA_GetDefaultConfig(&userConfig); + EDMA_Init(DEV_BASE(dev), &userConfig); + DEV_CFG(dev)->irq_config_func(dev); + memset(DEV_DATA(dev), 0, sizeof(struct dma_mcux_edma_data)); + memset(tcdpool, 0, sizeof(tcdpool)); + return 0; +} + +static void dma_imx_config_func_0(struct device *dev); + +static const struct dma_mcux_edma_config dma_config_0 = { + .base = (DMA_Type *)DT_INST_REG_ADDR(0), + .dmamux_base = (DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(0, 1), + .irq_config_func = dma_imx_config_func_0, +}; + +struct dma_mcux_edma_data dma_data; +/* + * define the dma + */ +DEVICE_AND_API_INIT(dma_mcux_edma_0, CONFIG_DMA_0_NAME, &dma_mcux_edma_init, + &dma_data, &dma_config_0, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &dma_mcux_edma_api); + +void dma_imx_config_func_0(struct device *dev) +{ + ARG_UNUSED(dev); + + /*install the dma error handle*/ + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 0, irq), + DT_INST_IRQ_BY_IDX(0, 0, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 0, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 1, irq), + DT_INST_IRQ_BY_IDX(0, 1, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 1, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 2, irq), + DT_INST_IRQ_BY_IDX(0, 2, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 2, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 3, irq), + DT_INST_IRQ_BY_IDX(0, 3, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 3, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 4, irq), + DT_INST_IRQ_BY_IDX(0, 4, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 4, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 5, irq), + DT_INST_IRQ_BY_IDX(0, 5, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 5, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 6, irq), + DT_INST_IRQ_BY_IDX(0, 6, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 6, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 7, irq), + DT_INST_IRQ_BY_IDX(0, 7, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 7, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 8, irq), + DT_INST_IRQ_BY_IDX(0, 8, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 8, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 9, irq), + DT_INST_IRQ_BY_IDX(0, 9, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 9, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 10, irq), + DT_INST_IRQ_BY_IDX(0, 10, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 10, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 11, irq), + DT_INST_IRQ_BY_IDX(0, 11, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 11, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 12, irq), + DT_INST_IRQ_BY_IDX(0, 12, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 12, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 13, irq), + DT_INST_IRQ_BY_IDX(0, 13, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 13, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 14, irq), + DT_INST_IRQ_BY_IDX(0, 14, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 14, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 15, irq), + DT_INST_IRQ_BY_IDX(0, 15, priority), + dma_mcux_edma_irq_handler, DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 15, irq)); + + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 16, irq), + DT_INST_IRQ_BY_IDX(0, 16, priority), + dma_mcux_edma_error_irq_handler, + DEVICE_GET(dma_mcux_edma_0), 0); + irq_enable(DT_INST_IRQ_BY_IDX(0, 16, irq)); + + LOG_DBG("install irq done"); +} diff --git a/drivers/dma/dma_mcux_edma.h b/drivers/dma/dma_mcux_edma.h new file mode 100644 index 0000000000..e654af73a3 --- /dev/null +++ b/drivers/dma/dma_mcux_edma.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 NXP Semiconductor INC. + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DMA_MCUX_EDMA_H_ +#define DMA_MCUX_EDMA_H_ + +#include +#include +#include +#include +#include + +#include "fsl_edma.h" +#include "fsl_dmamux.h" + +#endif /* DMA_MCUX_EDMA_H_*/ diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 801fff55c3..780be9af34 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -194,4 +194,9 @@ config HAS_MCUX_TPM help Set if the Timer/PWM Module is present in the SoC +config HAS_MCUX_EDMA + bool + help + Set if the EDMA module is present on the SoC. + endif # HAS_MCUX diff --git a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series index a51e0693b0..08ec9f431a 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series +++ b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series @@ -136,6 +136,10 @@ config VIDEO_MCUX_CSI default y if HAS_MCUX_CSI depends on VIDEO +config DMA_MCUX_EDMA + default y if HAS_MCUX_EDMA + depends on DMA + source "soc/arm/nxp_imx/rt/Kconfig.defconfig.mimxrt*" endif # SOC_SERIES_IMX_RT diff --git a/soc/arm/nxp_imx/rt/Kconfig.soc b/soc/arm/nxp_imx/rt/Kconfig.soc index a717ad03e3..165778d9e1 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.soc +++ b/soc/arm/nxp_imx/rt/Kconfig.soc @@ -25,6 +25,7 @@ config SOC_MIMXRT1011 select HAS_MCUX_USB_EHCI select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 + select HAS_MCUX_EDMA config SOC_MIMXRT1015 bool "SOC_MIMXRT1015" @@ -45,6 +46,7 @@ config SOC_MIMXRT1015 select HAS_MCUX_USB_EHCI select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 + select HAS_MCUX_EDMA config SOC_MIMXRT1021 bool "SOC_MIMXRT1021" @@ -66,6 +68,7 @@ config SOC_MIMXRT1021 select HAS_MCUX_USB_EHCI select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 + select HAS_MCUX_EDMA config SOC_MIMXRT1051 bool "SOC_MIMXRT1051" @@ -88,6 +91,7 @@ config SOC_MIMXRT1051 select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 select HAS_MCUX_CSI + select HAS_MCUX_EDMA config SOC_MIMXRT1052 bool "SOC_MIMXRT1052" @@ -113,6 +117,7 @@ config SOC_MIMXRT1052 select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 select HAS_MCUX_CSI + select HAS_MCUX_EDMA config SOC_MIMXRT1061 bool "SOC_MIMXRT1061" @@ -134,6 +139,7 @@ config SOC_MIMXRT1061 select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 select HAS_MCUX_CSI + select HAS_MCUX_EDMA config SOC_MIMXRT1062 bool "SOC_MIMXRT1062" @@ -159,6 +165,7 @@ config SOC_MIMXRT1062 select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 select HAS_MCUX_CSI + select HAS_MCUX_EDMA config SOC_MIMXRT1064 bool "SOC_MIMXRT1064" @@ -184,6 +191,7 @@ config SOC_MIMXRT1064 select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 select HAS_MCUX_CSI + select HAS_MCUX_EDMA endchoice diff --git a/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.series b/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.series index e4f18c2885..713770eac6 100644 --- a/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.series +++ b/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.series @@ -15,6 +15,10 @@ config NUM_IRQS config CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS default y +config DMA_MCUX_EDMA + default y if HAS_MCUX_EDMA + depends on DMA + source "soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.mk*" endif # SOC_SERIES_KINETIS_K6X diff --git a/soc/arm/nxp_kinetis/k6x/Kconfig.soc b/soc/arm/nxp_kinetis/k6x/Kconfig.soc index 744c743b2b..c05fb5a3ef 100644 --- a/soc/arm/nxp_kinetis/k6x/Kconfig.soc +++ b/soc/arm/nxp_kinetis/k6x/Kconfig.soc @@ -22,6 +22,7 @@ config SOC_MK64F12 select CPU_HAS_FPU select HAS_MCUX_RTC select HAS_MCUX_DAC + select HAS_MCUX_EDMA config SOC_MK66F18 bool "SOC_MK66F18" @@ -37,6 +38,7 @@ config SOC_MK66F18 select HAS_MCG select CPU_HAS_FPU select HAS_MCUX_RTC + select HAS_MCUX_EDMA endchoice