diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index 0c15fffea6fc5..42d5c969a7e9a 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -38,7 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_DMA_RENESAS_RZ dma_renesas_rz.c) zephyr_library_sources_ifdef(CONFIG_MCUX_PXP dma_mcux_pxp.c) zephyr_library_sources_ifdef(CONFIG_DMA_MAX32 dma_max32.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_SMARTDMA dma_mcux_smartdma.c) -zephyr_library_sources_ifdef(CONFIG_DMA_ANDES_ATCDMAC300 dma_andes_atcdmac300.c) +zephyr_library_sources_ifdef(CONFIG_DMA_ANDES_ATCDMACX00 dma_andes_atcdmacx00.c) zephyr_library_sources_ifdef(CONFIG_DMA_INFINEON_CAT1 dma_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_DMA_SEDI dma_sedi.c) zephyr_library_sources_ifdef(CONFIG_DMA_SI32 dma_si32.c) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 0bba13fb04f3f..e8e3e6b306f13 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -70,7 +70,7 @@ source "drivers/dma/Kconfig.max32" source "drivers/dma/Kconfig.mcux_smartdma" -source "drivers/dma/Kconfig.andes_atcdmac300" +source "drivers/dma/Kconfig.andes_atcdmacx00" source "drivers/dma/Kconfig.sedi" diff --git a/drivers/dma/Kconfig.andes_atcdmac300 b/drivers/dma/Kconfig.andes_atcdmac300 deleted file mode 100644 index cb1133cdeb5dc..0000000000000 --- a/drivers/dma/Kconfig.andes_atcdmac300 +++ /dev/null @@ -1,12 +0,0 @@ -# Andestech ATCDMAC300 configuration options -# Copyright (c) 2023 Andes Technology Corporation. - -# SPDX-License-Identifier: Apache-2.0 - - -config DMA_ANDES_ATCDMAC300 - bool "Using Andes ATCDMAC300 DMA driver" - default y - depends on DT_HAS_ANDESTECH_ATCDMAC300_ENABLED - help - Andes ATCDMAC300 DMA driver. diff --git a/drivers/dma/Kconfig.andes_atcdmacx00 b/drivers/dma/Kconfig.andes_atcdmacx00 new file mode 100644 index 0000000000000..25c062f73ee25 --- /dev/null +++ b/drivers/dma/Kconfig.andes_atcdmacx00 @@ -0,0 +1,19 @@ +# Andestech ATCDMACx00 serial configuration options +# Copyright (c) 2025 Andes Technology Corporation. + +# SPDX-License-Identifier: Apache-2.0 + + +config DMA_ANDES_ATCDMACX00 + bool "Andes ATCDMACX00 DMA driver" + default y + depends on DT_HAS_ANDESTECH_ATCDMACX00_ENABLED + depends on !DCACHE || SOC_ANDES_V5_IOCP || NOCACHE_MEMORY + help + Andes ATCDMACX00 DMA driver. + +if DMA_ANDES_ATCDMACX00 +config DMA_64BIT + default y + depends on 64BIT +endif diff --git a/drivers/dma/dma_andes_atcdmac300.c b/drivers/dma/dma_andes_atcdmacx00.c similarity index 53% rename from drivers/dma/dma_andes_atcdmac300.c rename to drivers/dma/dma_andes_atcdmacx00.c index 73c653710650e..5069f4dc1b39e 100644 --- a/drivers/dma/dma_andes_atcdmac300.c +++ b/drivers/dma/dma_andes_atcdmacx00.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Andes Technology Corporation. + * Copyright (c) 2025 Andes Technology Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,41 +12,43 @@ #include #include -#ifdef CONFIG_DCACHE -#ifdef CONFIG_CACHE_MANAGEMENT +#if defined(CONFIG_DCACHE) && defined(CONFIG_CACHE_MANAGEMENT) && !defined(CONFIG_NOCACHE_MEMORY) #include #endif -#endif - -#define DT_DRV_COMPAT andestech_atcdmac300 +#define DT_DRV_COMPAT andestech_atcdmacx00 #define LOG_LEVEL CONFIG_DMA_LOG_LEVEL #include -LOG_MODULE_REGISTER(dma_andes_atcdmac300); - -#define ATCDMAC100_MAX_CHAN 8 - -#define DMA_ABORT(dev) (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x24) -#define DMA_INT_STATUS(dev) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x30) - -#define DMA_CH_OFFSET(ch) (ch * 0x20) -#define DMA_CH_CTRL(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x40 + DMA_CH_OFFSET(ch)) -#define DMA_CH_TRANSIZE(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x44 + DMA_CH_OFFSET(ch)) -#define DMA_CH_SRC_ADDR_L(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x48 + DMA_CH_OFFSET(ch)) -#define DMA_CH_SRC_ADDR_H(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x4C + DMA_CH_OFFSET(ch)) -#define DMA_CH_DST_ADDR_L(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x50 + DMA_CH_OFFSET(ch)) -#define DMA_CH_DST_ADDR_H(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x54 + DMA_CH_OFFSET(ch)) -#define DMA_CH_LL_PTR_L(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x58 + DMA_CH_OFFSET(ch)) -#define DMA_CH_LL_PTR_H(dev, ch) \ - (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x5C + DMA_CH_OFFSET(ch)) +LOG_MODULE_REGISTER(dma_andes_atcdmacx00); + +#define ATCDMACx00_MAX_CHAN 8 +#define ATCDMAC300_VERSION 0x10230 +#define ATCDMAC100_VERSION 0x1021 + +#define DMA_INT_IDREV(dev) (((struct dma_atcdmacx00_cfg *)dev->config)->base + 0x00) +#define DMA_INT_STATUS(dev) (((struct dma_atcdmacx00_cfg *)dev->config)->base + 0x30) + +#define OFFSET_TABLE(dev) (((struct dma_atcdmacx00_data *)dev->data)->table) +#define DMA_CH_OFFSET(ch) (ch * (OFFSET_TABLE(dev).ch_offset)) + +#define DMA_ABORT(dev) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).abort) +#define DMA_CH_CTRL(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).ctrl + DMA_CH_OFFSET(ch)) +#define DMA_CH_TRANSIZE(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).transize + DMA_CH_OFFSET(ch)) +#define DMA_CH_SRC_ADDR(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).srcaddr + DMA_CH_OFFSET(ch)) +#define DMA_CH_SRC_ADDR_H(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).srcaddrh + DMA_CH_OFFSET(ch)) +#define DMA_CH_DST_ADDR(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).dstaddr + DMA_CH_OFFSET(ch)) +#define DMA_CH_DST_ADDR_H(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).dstaddrh + DMA_CH_OFFSET(ch)) +#define DMA_CH_LL_PTR(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).llpointer + DMA_CH_OFFSET(ch)) +#define DMA_CH_LL_PTR_H(dev, ch) (((struct dma_atcdmacx00_cfg *)dev->config)->base \ + + OFFSET_TABLE(dev).llpointerh + DMA_CH_OFFSET(ch)) /* Source burst size options */ #define DMA_BSIZE_1 (0) @@ -111,21 +113,15 @@ LOG_MODULE_REGISTER(dma_andes_atcdmac300); #define DMA_INT_STATUS_ERROR_VAL(x) FIELD_GET(DMA_INT_STATUS_ERROR_MASK, (x)) #define DMA_INT_STATUS_CH_MSK(ch) (0x111 << ch) -typedef void (*atcdmac300_cfg_func_t)(void); +typedef void (*atcdmacx00_cfg_func_t)(void); +/* + * The chain block is now an array to support multi-serial. + * It accommodates various block layouts and is sized to the + * largest possible size within the series. + */ struct chain_block { - uint32_t ctrl; - uint32_t transize; - uint32_t srcaddrl; - uint32_t srcaddrh; - uint32_t dstaddrl; - uint32_t dstaddrh; - uint32_t llpointerl; - uint32_t llpointerh; -#if __riscv_xlen == 32 - uint32_t reserved; -#endif - struct chain_block *next_block; + uint32_t __aligned(64) array[8]; }; /* data for each DMA channel */ @@ -136,26 +132,52 @@ struct dma_chan_data { struct dma_status status; }; +/* + * The register offsets vary slightly across different series. + * To handle this, using a struct to set the offset values on init time. + */ +struct offset_table { + uint32_t ch_offset; + uint32_t abort; + uint32_t ctrl; + uint32_t transize; + uint32_t srcaddr; + uint32_t srcaddrh; + uint32_t dstaddr; + uint32_t dstaddrh; + uint32_t llpointer; + uint32_t llpointerh; +}; + /* Device run time data */ -struct dma_atcdmac300_data { - struct dma_chan_data chan[ATCDMAC100_MAX_CHAN]; +struct dma_atcdmacx00_data { + struct dma_context dma_ctx; + atomic_t channel_flags; + struct dma_chan_data chan[ATCDMACx00_MAX_CHAN]; + uint32_t version; + struct offset_table table; struct k_spinlock lock; }; /* Device constant configuration parameters */ -struct dma_atcdmac300_cfg { - atcdmac300_cfg_func_t irq_config; +struct dma_atcdmacx00_cfg { + atcdmacx00_cfg_func_t irq_config; uint32_t base; uint32_t irq_num; }; -static struct __aligned(64) - chain_block dma_chain[ATCDMAC100_MAX_CHAN][sizeof(struct chain_block) * 16]; +#if CONFIG_NOCACHE_MEMORY +static struct chain_block __nocache __aligned(64) + dma_chain[ATCDMACx00_MAX_CHAN][16]; +#else /* CONFIG_NOCACHE_MEMORY */ +static struct chain_block __aligned(64) + dma_chain[ATCDMACx00_MAX_CHAN][16]; +#endif /* CONFIG_NOCACHE_MEMORY */ -static void dma_atcdmac300_isr(const struct device *dev) +static void dma_atcdmacx00_isr(const struct device *dev) { uint32_t int_status, int_ch_status, channel; - struct dma_atcdmac300_data *const data = dev->data; + struct dma_atcdmacx00_data *const data = dev->data; struct dma_chan_data *ch_data; k_spinlock_key_t key; @@ -192,24 +214,28 @@ static void dma_atcdmac300_isr(const struct device *dev) } } -static int dma_atcdmac300_config(const struct device *dev, uint32_t channel, +static int dma_atcdmacx00_config(const struct device *dev, uint32_t channel, struct dma_config *cfg) { - struct dma_atcdmac300_data *const data = dev->data; + struct dma_atcdmacx00_data *const data = dev->data; uint32_t src_width, dst_width, src_burst_size, ch_ctrl, tfr_size; int32_t ret = 0; struct dma_block_config *cfg_blocks; k_spinlock_key_t key; - if (channel >= ATCDMAC100_MAX_CHAN) { + if (channel >= ATCDMACx00_MAX_CHAN) { return -EINVAL; } __ASSERT_NO_MSG(cfg->source_data_size == cfg->dest_data_size); __ASSERT_NO_MSG(cfg->source_burst_length == cfg->dest_burst_length); - if (cfg->source_data_size != 1 && cfg->source_data_size != 2 && - cfg->source_data_size != 4) { + if ((data->version == ATCDMAC100_VERSION && + cfg->source_data_size != 1 && cfg->source_data_size != 2 && + cfg->source_data_size != 4) || + (cfg->source_data_size != 1 && cfg->source_data_size != 2 && + cfg->source_data_size != 4 && cfg->source_data_size != 8 && + cfg->source_data_size != 16 && cfg->source_data_size != 32)) { LOG_ERR("Invalid 'source_data_size' value"); ret = -EINVAL; goto end; @@ -245,7 +271,6 @@ static int dma_atcdmac300_config(const struct device *dev, uint32_t channel, goto end; } - switch (cfg_blocks->source_addr_adj) { case DMA_ADDR_ADJ_INCREMENT: ch_ctrl |= DMA_CH_CTRL_SRCADDR_INC; @@ -317,19 +342,31 @@ static int dma_atcdmac300_config(const struct device *dev, uint32_t channel, sys_write32(ch_ctrl, DMA_CH_CTRL(dev, channel)); /* Set source and destination address */ - sys_write32(cfg_blocks->source_address, - DMA_CH_SRC_ADDR_L(dev, channel)); - sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel)); - sys_write32(cfg_blocks->dest_address, - DMA_CH_DST_ADDR_L(dev, channel)); - sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel)); - - if (cfg->dest_chaining_en == 1 && cfg_blocks->next_block) { + sys_write32((uint32_t)FIELD_GET(GENMASK(31, 0), (cfg_blocks->source_address)), + DMA_CH_SRC_ADDR(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK(31, 0), (cfg_blocks->dest_address)), + DMA_CH_DST_ADDR(dev, channel)); + + if (data->version == ATCDMAC300_VERSION) { + sys_write32((uint32_t)FIELD_GET(GENMASK64(63, 32), (cfg_blocks->source_address)), + DMA_CH_SRC_ADDR_H(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK64(63, 32), (cfg_blocks->dest_address)), + DMA_CH_DST_ADDR_H(dev, channel)); + } + + if ((cfg->block_count > 1) && cfg_blocks->next_block) { + uint32_t current_block_idx = 0; - sys_write32((uint32_t)((long)&dma_chain[channel][current_block_idx]), - DMA_CH_LL_PTR_L(dev, channel)); - sys_write32(0, DMA_CH_LL_PTR_H(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK(31, 0), + ((long)&dma_chain[channel][current_block_idx])), + DMA_CH_LL_PTR(dev, channel)); + + if (data->version == ATCDMAC300_VERSION) { + sys_write32((uint32_t)FIELD_GET(GENMASK64(63, 32), + ((long)&dma_chain[channel][current_block_idx])), + DMA_CH_LL_PTR_H(dev, channel)); + } for (cfg_blocks = cfg_blocks->next_block; cfg_blocks != NULL; cfg_blocks = cfg_blocks->next_block) { @@ -366,66 +403,90 @@ static int dma_atcdmac300_config(const struct device *dev, uint32_t channel, ret = -EINVAL; goto end; } - dma_chain[channel][current_block_idx].ctrl = ch_ctrl; - dma_chain[channel][current_block_idx].transize = + + uint32_t index = 0; + + dma_chain[channel][current_block_idx].array[index++] = ch_ctrl; + dma_chain[channel][current_block_idx].array[index++] = cfg_blocks->block_size/cfg->source_data_size; - dma_chain[channel][current_block_idx].srcaddrl = - (uint32_t)cfg_blocks->source_address; - dma_chain[channel][current_block_idx].srcaddrh = 0x0; + dma_chain[channel][current_block_idx].array[index++] = + (uint32_t)FIELD_GET(GENMASK(31, 0), (cfg_blocks->source_address)); + if (data->version == ATCDMAC300_VERSION) { + dma_chain[channel][current_block_idx].array[index++] = + (uint32_t)FIELD_GET(GENMASK64(63, 32), + (cfg_blocks->source_address)); + } - dma_chain[channel][current_block_idx].dstaddrl = - (uint32_t)((long)cfg_blocks->dest_address); - dma_chain[channel][current_block_idx].dstaddrh = 0x0; + dma_chain[channel][current_block_idx].array[index++] = + (uint32_t)FIELD_GET(GENMASK(31, 0), (cfg_blocks->dest_address)); + if (data->version == ATCDMAC300_VERSION) { + dma_chain[channel][current_block_idx].array[index++] = + (uint32_t)FIELD_GET(GENMASK64(63, 32), + (cfg_blocks->dest_address)); + } if (cfg_blocks->next_block) { - dma_chain[channel][current_block_idx].llpointerl = - (uint32_t)&dma_chain[channel][current_block_idx + 1]; - dma_chain[channel][current_block_idx].llpointerh = 0x0; + dma_chain[channel][current_block_idx].array[index++] = + (uint32_t)FIELD_GET(GENMASK(31, 0), + ((long)&dma_chain[channel][current_block_idx + 1])); + dma_chain[channel][current_block_idx].array[index] = + (uint32_t)FIELD_GET(GENMASK64(63, 32), + ((long)&dma_chain[channel][current_block_idx + 1])); current_block_idx = current_block_idx + 1; } else { - dma_chain[channel][current_block_idx].llpointerl = 0x0; - dma_chain[channel][current_block_idx].llpointerh = 0x0; - dma_chain[channel][current_block_idx].next_block = NULL; + dma_chain[channel][current_block_idx].array[index++] = 0x0; + dma_chain[channel][current_block_idx].array[index] = 0x0; } } } else { /* Single transfer is supported, but Chain transfer is still * not supported. Therefore, set LLPointer to zero */ - sys_write32(0, DMA_CH_LL_PTR_L(dev, channel)); - sys_write32(0, DMA_CH_LL_PTR_H(dev, channel)); + sys_write32(0, DMA_CH_LL_PTR(dev, channel)); + if (data->version == ATCDMAC300_VERSION) { + sys_write32(0, DMA_CH_LL_PTR_H(dev, channel)); + } } -#ifdef CONFIG_DCACHE -#ifdef CONFIG_CACHE_MANAGEMENT +#if defined(CONFIG_DCACHE) && defined(CONFIG_CACHE_MANAGEMENT) && !defined(CONFIG_NOCACHE_MEMORY) cache_data_flush_range((void *)&dma_chain, sizeof(dma_chain)); -#else +#elif defined(CONFIG_DCACHE) && !defined(CONFIG_CACHE_MANAGEMENT) && !defined(CONFIG_NOCACHE_MEMORY) #error "Data cache is enabled; please flush the cache after \ -setting dma_chain to ensure memory coherence." -#endif + setting dma_chain to ensure memory coherence." #endif end: return ret; } -static int dma_atcdmac300_reload(const struct device *dev, uint32_t channel, +#ifdef CONFIG_DMA_64BIT +static int dma_atcdmacx00_reload(const struct device *dev, uint32_t channel, + uint64_t src, uint64_t dst, size_t size) +#else +static int dma_atcdmacx00_reload(const struct device *dev, uint32_t channel, uint32_t src, uint32_t dst, size_t size) +#endif { + struct dma_atcdmacx00_data *const data = dev->data; uint32_t src_width; - if (channel >= ATCDMAC100_MAX_CHAN) { + if (channel >= ATCDMACx00_MAX_CHAN) { return -EINVAL; } /* Set source and destination address */ - sys_write32(src, DMA_CH_SRC_ADDR_L(dev, channel)); - sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel)); - sys_write32(dst, DMA_CH_DST_ADDR_L(dev, channel)); - sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK(31, 0), (src)), DMA_CH_SRC_ADDR(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK(31, 0), (dst)), DMA_CH_DST_ADDR(dev, channel)); + + if (data->version == ATCDMAC300_VERSION) { + sys_write32((uint32_t)FIELD_GET(GENMASK64(63, 32), (src)), + DMA_CH_SRC_ADDR_H(dev, channel)); + sys_write32((uint32_t)FIELD_GET(GENMASK64(63, 32), (dst)), + DMA_CH_DST_ADDR_H(dev, channel)); + } src_width = FIELD_GET(DMA_CH_CTRL_SWIDTH_MASK, sys_read32(DMA_CH_CTRL(dev, channel))); src_width = BIT(src_width); @@ -436,12 +497,12 @@ static int dma_atcdmac300_reload(const struct device *dev, uint32_t channel, return 0; } -static int dma_atcdmac300_transfer_start(const struct device *dev, +static int dma_atcdmacx00_transfer_start(const struct device *dev, uint32_t channel) { - struct dma_atcdmac300_data *const data = dev->data; + struct dma_atcdmacx00_data *const data = dev->data; - if (channel >= ATCDMAC100_MAX_CHAN) { + if (channel >= ATCDMACx00_MAX_CHAN) { return -EINVAL; } @@ -453,13 +514,13 @@ static int dma_atcdmac300_transfer_start(const struct device *dev, return 0; } -static int dma_atcdmac300_transfer_stop(const struct device *dev, +static int dma_atcdmacx00_transfer_stop(const struct device *dev, uint32_t channel) { - struct dma_atcdmac300_data *const data = dev->data; + struct dma_atcdmacx00_data *const data = dev->data; k_spinlock_key_t key; - if (channel >= ATCDMAC100_MAX_CHAN) { + if (channel >= ATCDMACx00_MAX_CHAN) { return -EINVAL; } @@ -475,13 +536,44 @@ static int dma_atcdmac300_transfer_stop(const struct device *dev, return 0; } -static int dma_atcdmac300_init(const struct device *dev) +static int dma_atcdmacx00_init(const struct device *dev) { - const struct dma_atcdmac300_cfg *const config = (struct dma_atcdmac300_cfg *)dev->config; + struct dma_atcdmacx00_data *const data = dev->data; + const struct dma_atcdmacx00_cfg *const config = (struct dma_atcdmacx00_cfg *)dev->config; uint32_t ch_num; + if (FIELD_GET(GENMASK(31, 8), sys_read32(DMA_INT_IDREV(dev))) == ATCDMAC300_VERSION) { + data->version = ATCDMAC300_VERSION; + data->table.ch_offset = 0x20; + data->table.abort = 0x24; + data->table.ctrl = 0x40; + data->table.transize = 0x44; + data->table.srcaddr = 0x48; + data->table.srcaddrh = 0x4c; + data->table.dstaddr = 0x50; + data->table.dstaddrh = 0x54; + data->table.llpointer = 0x58; + data->table.llpointerh = 0x5c; + } else { +#ifndef CONFIG_DMA_64BIT + data->version = ATCDMAC100_VERSION; + data->table.ch_offset = 0x14; + data->table.abort = 0x40; + data->table.ctrl = 0x44; + data->table.transize = 0x50; + data->table.srcaddr = 0x48; + data->table.dstaddr = 0x4c; + data->table.llpointer = 0x54; +#else + LOG_ERR("ATCDMAC100 doesn't support 64bit dma.\n"); +#endif + } + + data->channel_flags = ATOMIC_INIT(0); + data->dma_ctx.atomic = &data->channel_flags; + /* Disable all channels and Channel interrupts */ - for (ch_num = 0; ch_num < ATCDMAC100_MAX_CHAN; ch_num++) { + for (ch_num = 0; ch_num < ATCDMACx00_MAX_CHAN; ch_num++) { sys_write32(0, DMA_CH_CTRL(dev, ch_num)); } @@ -495,11 +587,11 @@ static int dma_atcdmac300_init(const struct device *dev) return 0; } -static int dma_atcdmac300_get_status(const struct device *dev, +static int dma_atcdmacx00_get_status(const struct device *dev, uint32_t channel, struct dma_status *stat) { - struct dma_atcdmac300_data *const data = dev->data; + struct dma_atcdmacx00_data *const data = dev->data; stat->busy = data->chan[channel].status.busy; stat->dir = data->chan[channel].status.dir; @@ -508,43 +600,44 @@ static int dma_atcdmac300_get_status(const struct device *dev, return 0; } -static DEVICE_API(dma, dma_atcdmac300_api) = { - .config = dma_atcdmac300_config, - .reload = dma_atcdmac300_reload, - .start = dma_atcdmac300_transfer_start, - .stop = dma_atcdmac300_transfer_stop, - .get_status = dma_atcdmac300_get_status +static const struct dma_driver_api dma_atcdmacx00_api = { + .config = dma_atcdmacx00_config, + .reload = dma_atcdmacx00_reload, + .start = dma_atcdmacx00_transfer_start, + .stop = dma_atcdmacx00_transfer_stop, + .get_status = dma_atcdmacx00_get_status }; -#define ATCDMAC300_INIT(n) \ - \ - static void dma_atcdmac300_irq_config_##n(void); \ +#define ATCDMACx00_INIT(n) \ \ - static const struct dma_atcdmac300_cfg dma_config_##n = { \ - .irq_config = dma_atcdmac300_irq_config_##n, \ + static struct dma_atcdmacx00_data dma_data_##n = { \ + .dma_ctx.magic = DMA_MAGIC, \ + .dma_ctx.dma_channels = DT_INST_PROP(n, dma_channels), \ + .dma_ctx.atomic = ATOMIC_INIT(0), \ + }; \ + static void dma_atcdmacx00_irq_config_##n(void); \ + static const struct dma_atcdmacx00_cfg dma_config_##n = { \ + .irq_config = dma_atcdmacx00_irq_config_##n, \ .base = DT_INST_REG_ADDR(n), \ .irq_num = DT_INST_IRQN(n), \ }; \ \ - static struct dma_atcdmac300_data dma_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(0, \ - dma_atcdmac300_init, \ + DEVICE_DT_INST_DEFINE(n, \ + dma_atcdmacx00_init, \ NULL, \ &dma_data_##n, \ &dma_config_##n, \ POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ - &dma_atcdmac300_api); \ + &dma_atcdmacx00_api); \ \ - static void dma_atcdmac300_irq_config_##n(void) \ + static void dma_atcdmacx00_irq_config_##n(void) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), \ 1, \ - dma_atcdmac300_isr, \ + dma_atcdmacx00_isr, \ DEVICE_DT_INST_GET(n), \ 0); \ } - -DT_INST_FOREACH_STATUS_OKAY(ATCDMAC300_INIT) +DT_INST_FOREACH_STATUS_OKAY(ATCDMACx00_INIT) diff --git a/dts/bindings/dma/andestech,atcdmac300.yaml b/dts/bindings/dma/andestech,atcdmac300.yaml deleted file mode 100644 index 4c0020dd69d77..0000000000000 --- a/dts/bindings/dma/andestech,atcdmac300.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright (c) 2023 Andes Technology Corporation. -# -# SPDX-License-Identifier: Apache-2.0 - -compatible: "andestech,atcdmac300" - -include: dma-controller.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - chain-transfer: - type: int - - "#dma-cells": - const: 3 - -dma-cells: - - channel - - slot - - channel-config - -description: | - Andes DMA controller - channel: a phandle to the DMA controller plus the following four integer cells: - 1. channel: the dma channel - 2. slot: DMA peripheral request ID - 3. channel-config: A 32bit mask specifying the DMA channel configuration - which is device dependent: - -bit 0-1 : Direction (see dma.h) - 0x0: MEM to MEM - 0x1: MEM to PERIPH - 0x2: PERIPH to MEM - 0x3: reserved for PERIPH to PERIPH - -bit 2 : Peripheral Increment Address - 0x0: no address increment between transfers - 0x1: increment address between transfers - -bit 3 : Memory Increment Address - 0x0: no address increment between transfers - 0x1: increment address between transfers - -bit 4-6 : Peripheral data size - 0x0: Byte (8 bits) - 0x1: Half-word (16 bits) - 0x2: Word (32 bits) - 0x3: Double word (64 bits) - 0x4: Quad word (128 bits) - 0x5: Eight word (256 bits) - 0x6-0x7: reserved - -bit 7-9 : Memory data size - 0x0: Byte (8 bits) - 0x1: Half-word (16 bits) - 0x2: Word (32 bits) - 0x3: Double word (64 bits) - 0x4: Quad word (128 bits) - 0x5: Eight word (256 bits) - 0x6-0x7: reserved - -bit 10 : Priority level - 0x0: lower priority - 0x1: higher priority - - examples for andes_v5_ae350 DMA instance - dma0: dma0@f0c00000 { - compatible = "andestech,atcdmac300"; - ... - dma-channels = <8>; - dma-requests = <16>; - status = "disabled"; - label = "DMA_0"; - }; - - For the client part, example for andes_ae350 DMA instance - Tx using channel 2, slot 0 - Rx using channel 3, slot 1 - spi1: spi@f0f00000 { - compatible = "andestech,atcspi200" - dmas = <&dma0 2 0 0x0129>, - <&dma0 3 1 0x012A>; - dma-names = "tx", "rx"; - }; diff --git a/dts/bindings/dma/andestech,atcdmacx00.yaml b/dts/bindings/dma/andestech,atcdmacx00.yaml new file mode 100644 index 0000000000000..10ffa00291f57 --- /dev/null +++ b/dts/bindings/dma/andestech,atcdmacx00.yaml @@ -0,0 +1,87 @@ +# +# Copyright (c) 2021 Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 + +compatible: "andestech,atcdmacx00" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + chain-transfer: + type: int + + max-data-width: + type: int + + "#dma-cells": + const: 3 + +dma-cells: + - channel + - slot + - channel-config + +description: | + Andes DMA controller + channel: a phandle to the DMA controller plus the following four integer cells: + 1. channel: the dma channel + 2. slot: DMA peripheral request ID + 3. channel-config: A 32bit mask specifying the DMA channel configuration + which is device dependent: + -bit 0-1 : Direction (see dma.h) + 0x0: MEM to MEM + 0x1: MEM to PERIPH + 0x2: PERIPH to MEM + 0x3: reserved for PERIPH to PERIPH + -bit 2 : Peripheral Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 3 : Memory Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 4-6 : Peripheral data size + 0x0: Byte (8 bits) + 0x1: Half-word (16 bits) + 0x2: Word (32 bits) + 0x3: Double word (64 bits) + 0x4: Quad word (128 bits) + 0x5: Eight word (256 bits) + 0x6-0x7: reserved + -bit 7-9 : Memory data size + 0x0: Byte (8 bits) + 0x1: Half-word (16 bits) + 0x2: Word (32 bits) + 0x3: Double word (64 bits) + 0x4: Quad word (128 bits) + 0x5: Eight word (256 bits) + 0x6-0x7: reserved + -bit 10 : Priority level + 0x0: lower priority + 0x1: higher priority + + examples for andes_v5_ae350 DMA instance + dma0: dma0@f0c00000 { + compatible = "andestech,atcdmac300"; + ... + dma-channels = <8>; + dma-requests = <16>; + status = "disabled"; + label = "DMA_0"; + }; + + For the client part, example for andes_ae350 DMA instance + Tx using channel 2, slot 0 + Rx using channel 3, slot 1 + spi1: spi@f0f00000 { + compatible = "andestech,atcspi200" + dmas = <&dma0 2 0 0x0129>, + <&dma0 3 1 0x012A>; + dma-names = "tx", "rx"; + }; diff --git a/dts/riscv/andes/andes_v5_ae350.dtsi b/dts/riscv/andes/andes_v5_ae350.dtsi index e787d7d55bfda..40cee165c04c9 100644 --- a/dts/riscv/andes/andes_v5_ae350.dtsi +++ b/dts/riscv/andes/andes_v5_ae350.dtsi @@ -326,13 +326,14 @@ }; dma0: dma@f0c00000 { - compatible = "andestech,atcdmac300"; + compatible = "andestech,atcdmacx00"; reg = <0xf0c00000 0x1000>; interrupts = <10 1>; interrupt-parent = <&plic0>; dma-channels = <8>; dma-requests = <16>; chain-transfer = <1>; + max-data-width = <4>; #dma-cells = <3>; status = "disabled"; }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf index c448e14811f7b..24be02d577c41 100644 --- a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf +++ b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf @@ -1 +1 @@ -CONFIG_NOCACHE_MEMORY=y +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350_clic.conf b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350_clic.conf index c448e14811f7b..24be02d577c41 100644 --- a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350_clic.conf +++ b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350_clic.conf @@ -1 +1 @@ -CONFIG_NOCACHE_MEMORY=y +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf index c448e14811f7b..24be02d577c41 100644 --- a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf +++ b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf @@ -1 +1 @@ -CONFIG_NOCACHE_MEMORY=y +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350_clic.conf b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350_clic.conf index c448e14811f7b..24be02d577c41 100644 --- a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350_clic.conf +++ b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350_clic.conf @@ -1 +1 @@ -CONFIG_NOCACHE_MEMORY=y +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.conf b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.conf new file mode 100644 index 0000000000000..24be02d577c41 --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.conf @@ -0,0 +1 @@ +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.overlay b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.overlay new file mode 100644 index 0000000000000..519877d2d3493 --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dma0 = &dma0; + }; +}; diff --git a/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.conf b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.conf new file mode 100644 index 0000000000000..24be02d577c41 --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.conf @@ -0,0 +1 @@ +CONFIG_DCACHE=n diff --git a/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.overlay b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.overlay new file mode 100644 index 0000000000000..519877d2d3493 --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/adp_xc7k_ae350_clic.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dma0 = &dma0; + }; +}; diff --git a/tests/drivers/dma/scatter_gather/testcase.yaml b/tests/drivers/dma/scatter_gather/testcase.yaml index 774fec68ccdc4..00b6d86450814 100644 --- a/tests/drivers/dma/scatter_gather/testcase.yaml +++ b/tests/drivers/dma/scatter_gather/testcase.yaml @@ -18,6 +18,8 @@ tests: - siwx917_rb4338a - siwx917_rb4342a - siwx917_dk2605a + - adp_xc7k/ae350 + - adp_xc7k/ae350/clic filter: dt_alias_exists("dma0") integration_platforms: - intel_adsp/cavs25