From e3105fb5290e1c942ef6ee7b33a49b8bf43fa85e Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Tue, 19 Nov 2024 20:48:21 +0530 Subject: [PATCH] drivers: dma: siwx917: Add DMA driver Implement DMA driver for siwx917 using UDMA peripheral. Following Zephyr DMA APIs are supported as part of this implementation, 1. dma_api_config 2. dma_api_reload 3. dma_api_start 4. dma_api_stop 5. dma_api_get_status Signed-off-by: Sai Santhosh Malae --- .github/workflows/build.yml | 6 + .github/workflows/upstream-build.yml | 6 + .../siwx917_rb4338a/siwx917_rb4338a.yaml | 1 + drivers/CMakeLists.txt | 1 + drivers/dma/CMakeLists.txt | 4 + drivers/dma/Kconfig | 8 + drivers/dma/Kconfig.siwx917 | 14 + drivers/dma/dma_silabs_siwx917.c | 422 ++++++++++++++++++ dts/arm/silabs/siwg917.dtsi | 26 ++ dts/bindings/dma/silabs,siwx917-dma.yaml | 26 ++ modules/hal_silabs/wiseconnect/CMakeLists.txt | 8 + soc/silabs/silabs_siwx917/siwg917/linker.ld | 19 + soc/silabs/silabs_siwx917/siwg917/soc.c | 8 + .../boards/siwx917_rb4338a.conf | 4 + .../boards/siwx917_rb4338a.overlay | 13 + west.yml | 2 +- 16 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/CMakeLists.txt create mode 100644 drivers/dma/Kconfig create mode 100644 drivers/dma/Kconfig.siwx917 create mode 100644 drivers/dma/dma_silabs_siwx917.c create mode 100644 dts/bindings/dma/silabs,siwx917-dma.yaml create mode 100644 tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf create mode 100644 tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 399254a..50343bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,6 +50,12 @@ jobs: run: | west twister -s drivers.flash.common.default -p siwx917_rb4338a -x DTC_OVERLAY_FILE=$(pwd)/tests/drivers/flash/common/boards/siwx917_rb4338a.overlay -v --inline-logs + - name: Build DMA test + working-directory: zephyr-silabs + shell: bash + run: | + west twister -s drivers.dma.chan_blen_transfer -p siwx917_rb4338a -- -DTC_OVERLAY_FILE=$(pwd)/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay -DEXTRA_CONF_FILE=$(pwd)/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf -v --inline-logs + - name: Build Bluetooth samples working-directory: zephyr-silabs shell: bash diff --git a/.github/workflows/upstream-build.yml b/.github/workflows/upstream-build.yml index 8bea405..c55cdaa 100644 --- a/.github/workflows/upstream-build.yml +++ b/.github/workflows/upstream-build.yml @@ -55,6 +55,12 @@ jobs: run: | west twister -s drivers.flash.common.default -p siwx917_rb4338a -x DTC_OVERLAY_FILE=$(pwd)/tests/drivers/flash/common/boards/siwx917_rb4338a.overlay -v --inline-logs + - name: Build DMA test + working-directory: zephyr-silabs + shell: bash + run: | + west twister -s drivers.dma.chan_blen_transfer -p siwx917_rb4338a -- -DTC_OVERLAY_FILE=$(pwd)/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay -DEXTRA_CONF_FILE=$(pwd)/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf -v --inline-logs + - name: Build Bluetooth samples working-directory: zephyr-silabs shell: bash diff --git a/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a.yaml b/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a.yaml index b34b0f2..6cbf587 100644 --- a/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a.yaml +++ b/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a.yaml @@ -11,6 +11,7 @@ toolchain: supported: - gpio - i2c + - dma - wifi - bluetooth - flash diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index fd47aaf..5cbf42f 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(entropy) add_subdirectory(flash) add_subdirectory(gpio) add_subdirectory(pinctrl) +add_subdirectory(dma) add_subdirectory(wifi) diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt new file mode 100644 index 0000000..5a12b31 --- /dev/null +++ b/drivers/dma/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources_ifdef(CONFIG_DMA_SILABS_SIWX917 dma_silabs_siwx917.c) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig new file mode 100644 index 0000000..a1dd45a --- /dev/null +++ b/drivers/dma/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +if DMA + +rsource "Kconfig.siwx917" + +endif diff --git a/drivers/dma/Kconfig.siwx917 b/drivers/dma/Kconfig.siwx917 new file mode 100644 index 0000000..112787d --- /dev/null +++ b/drivers/dma/Kconfig.siwx917 @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig DMA_SILABS_SIWX917 + bool "Silabs SiWx917 DMA driver" + default y + depends on DT_HAS_SILABS_SIWX917_DMA_ENABLED + help + Enable the High Power(HP)/Ultra Low Power(ULP) DMA driver for the Silabs SiWx917 SoC series. + +config DMA_SILABS_SIWX917_COMMON_INIT_PRIORITY + int "Common initialization priority" + depends on DMA_SILABS_SIWX917 + default 42 diff --git a/drivers/dma/dma_silabs_siwx917.c b/drivers/dma/dma_silabs_siwx917.c new file mode 100644 index 0000000..67fa697 --- /dev/null +++ b/drivers/dma/dma_silabs_siwx917.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2024 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "rsi_rom_udma_wrapper.h" +#include "rsi_udma.h" +#include "sl_status.h" + +#define DT_DRV_COMPAT silabs_siwx917_dma +#define DMA_MAX_TRANSFER_COUNT 1024 +#define DMA_CH_PRIORITY_HIGH 1 +#define DMA_CH_PRIORITY_LOW 0 +#define UDMA0_INSTANCE 0 +#define ULP_UDMA_INSTANCE 1 +#define VALID_BURST_LENGTH 0 +#define UDMA_ADDR_INC_NONE 0X03 + +LOG_MODULE_REGISTER(si91x_dma, CONFIG_DMA_LOG_LEVEL); + +struct dma_siwx917_config { + UDMA0_Type *reg; /* UDMA register base address */ + uint8_t channels; /* UDMA channel count */ + uint8_t irq_number; /* IRQ number */ + uint32_t sram_desc_addr; /* SRAM Address for UDMA Descriptor Storage */ + void (*irq_configure)(void); /* IRQ configure function */ +}; + +struct dma_siwx917_data { + UDMA_Channel_Info *udma_channel_info; + dma_callback_t dma_callback; /* User callback */ + void *cb_data; /* User callback data */ + uint32_t dma_rom_buff[6]; /* Buffers which stores UDMA handle*/ + /* related information */ +}; + +static inline int siwx917_dma_is_peripheral_request(uint32_t dir) +{ + if (dir == MEMORY_TO_MEMORY) { + return 0; + } + if ((dir == MEMORY_TO_PERIPHERAL) || (dir == PERIPHERAL_TO_MEMORY)) { + return 1; + } + return -1; +} + +static inline int siwx917_dma_data_width(uint32_t data_width) +{ + switch (data_width) { + case 1: + return SRC_SIZE_8; + case 2: + return SRC_SIZE_16; + case 4: + return SRC_SIZE_32; + default: + return -EINVAL; + } +} + +static inline int siwx917_dma_burst_length(uint32_t blen) +{ + switch ((blen / 8)) { + case 1: + return VALID_BURST_LENGTH; /* 8-bit burst */ + default: + return -EINVAL; + } +} + +static inline int siwx917_dma_addr_adjustment(uint32_t adjustment) +{ + switch (adjustment) { + case 0: + return 0; /* Addr Increment */ + case 2: + return UDMA_ADDR_INC_NONE; /* No Address increment */ + default: + return -EINVAL; + } +} + +static int dma_channel_config(const struct device *dev, RSI_UDMA_HANDLE_T udma_handle, + uint32_t rsi_channel, struct dma_config *config, + UDMA_Channel_Info *channel_info) +{ + const struct dma_siwx917_config *cfg = dev->config; + UDMA_RESOURCES UDMA_Resources = { + .reg = cfg->reg, + .udma_irq_num = cfg->irq_number, + /* SRAM address where UDMA descriptor is stored */ + .desc = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr, + }; + RSI_UDMA_CHA_CONFIG_DATA_T channel_control = { + .transferType = UDMA_MODE_BASIC, + }; + RSI_UDMA_CHA_CFG_T channel_config = {}; + int status; + + channel_config.channelPrioHigh = config->channel_priority; + channel_config.periphReq = siwx917_dma_is_peripheral_request(config->channel_direction); + if (channel_config.periphReq < 0) { + return -EINVAL; + } + channel_config.dmaCh = rsi_channel; + if (channel_config.periphReq) { + /* Arbitration power for peripheral<->memory transfers */ + channel_control.rPower = ARBSIZE_1; + } else { + /* Arbitration power for mem-mem transfers */ + channel_control.rPower = ARBSIZE_1024; + } + /* Obtain the number of transfers */ + config->head_block->block_size /= config->source_data_size; + if (config->head_block->block_size >= DMA_MAX_TRANSFER_COUNT) { + /* Maximum number of transfers is 1024 */ + channel_control.totalNumOfDMATrans = (DMA_MAX_TRANSFER_COUNT - 1); + } else { + channel_control.totalNumOfDMATrans = config->head_block->block_size; + } + if ((siwx917_dma_data_width(config->source_data_size) < 0) || + (siwx917_dma_data_width(config->dest_data_size) < 0)) { + return -EINVAL; + } + if ((siwx917_dma_burst_length(config->source_burst_length) < 0) || + (siwx917_dma_burst_length(config->dest_burst_length) < 0)) { + return -EINVAL; + } + channel_control.srcSize = siwx917_dma_data_width(config->source_data_size); + channel_control.dstSize = siwx917_dma_data_width(config->dest_data_size); + if ((siwx917_dma_addr_adjustment(config->head_block->source_addr_adj) < 0) || + (siwx917_dma_addr_adjustment(config->head_block->dest_addr_adj) < 0)) { + return -EINVAL; + } + if (siwx917_dma_addr_adjustment(config->head_block->source_addr_adj) == 0) { + channel_control.srcInc = channel_control.srcSize; + } else { + channel_control.srcInc = UDMA_SRC_INC_NONE; + } + if (siwx917_dma_addr_adjustment(config->head_block->dest_addr_adj) == 0) { + channel_control.dstInc = channel_control.dstSize; + } else { + channel_control.dstInc = UDMA_DST_INC_NONE; + } + status = UDMAx_ChannelConfigure(&UDMA_Resources, (uint8_t)rsi_channel, + (uint32_t)(config->head_block->source_address), + (uint32_t)(config->head_block->dest_address), + config->head_block->block_size, channel_control, + &channel_config, NULL, channel_info, udma_handle); + return status; +} + +/* Function to configure UDMA channel for transfer */ +static int dma_siwx917_configure(const struct device *dev, uint32_t channel, + struct dma_config *config) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + uint32_t rsi_channel = channel - 1; + int status; + RSI_UDMA_HANDLE_T udma_handle = data->dma_rom_buff; + + /* Expecting a fixed channel number between 1-32 for udma0 and 1-12 for udma1 */ + if (channel > cfg->channels || channel == 0) { + return -EINVAL; + } + + /* Disable the channel before configuring */ + if (RSI_UDMA_ChannelDisable(udma_handle, rsi_channel) != 0) { + return -EIO; + } + + if ((config->channel_priority != DMA_CH_PRIORITY_LOW) && + (config->channel_priority != DMA_CH_PRIORITY_HIGH)) { + return -EINVAL; + } + + /* Configure dma channel for transfer */ + status = dma_channel_config(dev, udma_handle, rsi_channel, config, data->udma_channel_info); + if (status != 0) { + return -EINVAL; + } + return 0; +} + +/* Function to reload UDMA channel for new transfer */ +static int dma_siwx917_reload(const struct device *dev, uint32_t channel, uint32_t src, + uint32_t dst, size_t size) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + uint32_t rsi_channel = channel - 1; + uint32_t desc_src_addr; + uint32_t desc_dst_addr; + uint32_t length; + RSI_UDMA_HANDLE_T udma_handle = data->dma_rom_buff; + RSI_UDMA_DESC_T *UDMA_Table = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr; + + /* Expecting a fixed channel number between 1-32 for udma0 and 1-12 for udma1 */ + if (channel > cfg->channels || channel == 0) { + return -EINVAL; + } + + /* Disable the channel before reloading transfer */ + if (RSI_UDMA_ChannelDisable(udma_handle, rsi_channel) != 0) { + return -EIO; + } + + /* Update new channel info to dev->data structure */ + data->udma_channel_info[rsi_channel].SrcAddr = src; + data->udma_channel_info[rsi_channel].DestAddr = dst; + data->udma_channel_info[rsi_channel].Size = size; + + /* Update new transfer size to dev->data structure */ + if (size >= DMA_MAX_TRANSFER_COUNT) { + data->udma_channel_info[rsi_channel].Cnt = (DMA_MAX_TRANSFER_COUNT - 1); + } else { + data->udma_channel_info[rsi_channel].Cnt = size; + } + /* Program the DMA descriptors with new transfer data information. */ + if (UDMA_Table[rsi_channel].vsUDMAChaConfigData1.srcInc != UDMA_SRC_INC_NONE) { + length = (data->udma_channel_info[rsi_channel].Cnt) + << UDMA_Table[rsi_channel].vsUDMAChaConfigData1.srcInc; + desc_src_addr = (uint32_t)src + (length - 1); + UDMA_Table[rsi_channel].pSrcEndAddr = (void *)(desc_src_addr); + } + if (UDMA_Table[rsi_channel].vsUDMAChaConfigData1.dstInc != UDMA_SRC_INC_NONE) { + length = (data->udma_channel_info[rsi_channel].Cnt) + << UDMA_Table[rsi_channel].vsUDMAChaConfigData1.dstInc; + desc_dst_addr = (uint32_t)dst + (length - 1); + UDMA_Table[rsi_channel].pDstEndAddr = (void *)(desc_dst_addr); + } + UDMA_Table[rsi_channel].vsUDMAChaConfigData1.totalNumOfDMATrans = + data->udma_channel_info[rsi_channel].Cnt; + UDMA_Table[rsi_channel].vsUDMAChaConfigData1.transferType = UDMA_MODE_BASIC; + + return 0; +} + +/* Function to start a DMA transfer */ +static int dma_siwx917_start(const struct device *dev, uint32_t channel) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + uint32_t rsi_channel = channel - 1; + RSI_UDMA_HANDLE_T udma_handle = data->dma_rom_buff; + RSI_UDMA_DESC_T *UDMA_Table = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr; + + /* Expecting a fixed channel number between 1-32 for udma0 and 1-12 for udma1 */ + if (channel > cfg->channels || channel == 0) { + return -EINVAL; + } + if (RSI_UDMA_ChannelEnable(udma_handle, rsi_channel) != 0) { + return -EINVAL; + } + + /* Check if the transfer type is memory-memory */ + if ((UDMA_Table[rsi_channel].vsUDMAChaConfigData1.srcInc != UDMA_SRC_INC_NONE) && + (UDMA_Table[rsi_channel].vsUDMAChaConfigData1.dstInc != UDMA_DST_INC_NONE)) { + /* Apply software trigger to start transfer */ + cfg->reg->CHNL_SW_REQUEST |= SET_BIT(rsi_channel); + } + return 0; +} + +/* Function to stop a DMA transfer */ +static int dma_siwx917_stop(const struct device *dev, uint32_t channel) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + RSI_UDMA_HANDLE_T udma_handle = data->dma_rom_buff; + + /* Expecting a fixed channel number between 1-32 for udma0 and 1-12 for udma1 */ + if (channel > cfg->channels || channel == 0) { + return -EINVAL; + } + if (RSI_UDMA_ChannelDisable(udma_handle, (channel - 1)) != 0) { + return -EIO; + } + return 0; +} + +/* Function to fetch DMA channel status */ +static int dma_siwx917_get_status(const struct device *dev, uint32_t channel, + struct dma_status *stat) +{ + const struct dma_siwx917_config *cfg = dev->config; + uint32_t rsi_channel = channel - 1; + RSI_UDMA_DESC_T *UDMA_Table = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr; + + /* Expecting a fixed channel number between 1-32 for udma0 and 1-12 for udma1 */ + if (channel > cfg->channels || channel == 0) { + return -EINVAL; + } + /* Read the channel status register */ + if ((cfg->reg->CHANNEL_STATUS_REG >> rsi_channel) & 0x01) { + stat->busy = 1; + } else { + stat->busy = 0; + } + + /* Obtain the transfer direction from channel descriptors */ + if (UDMA_Table[rsi_channel].vsUDMAChaConfigData1.srcInc == UDMA_SRC_INC_NONE) { + stat->dir = PERIPHERAL_TO_MEMORY; + } else if (UDMA_Table[rsi_channel].vsUDMAChaConfigData1.dstInc == UDMA_DST_INC_NONE) { + stat->dir = MEMORY_TO_PERIPHERAL; + } else { + stat->dir = MEMORY_TO_MEMORY; + } + return 0; +} + +/* Function to initialize DMA peripheral */ +static int dma_siwx917_init(const struct device *dev) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + RSI_UDMA_HANDLE_T udma_handle = NULL; + UDMA_RESOURCES UDMA_Resources = { + .reg = cfg->reg, /* UDMA register base address */ + .udma_irq_num = cfg->irq_number, + .desc = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr, + }; + + udma_handle = + UDMAx_Initialize(&UDMA_Resources, UDMA_Resources.desc, NULL, data->dma_rom_buff); + if (udma_handle != data->dma_rom_buff) { + return -EINVAL; + } + + /* Connect the DMA interrupt */ + cfg->irq_configure(); + + if (UDMAx_DMAEnable(&UDMA_Resources, udma_handle) != 0) { + return -EBUSY; + } + return 0; +} + +static void dma_siwx917_isr(const struct device *dev) +{ + const struct dma_siwx917_config *cfg = dev->config; + struct dma_siwx917_data *data = dev->data; + UDMA_RESOURCES UDMA_Resources = { + .reg = cfg->reg, + .udma_irq_num = cfg->irq_number, + .desc = (RSI_UDMA_DESC_T *)cfg->sram_desc_addr, + }; + uint8_t channel; + + /* Disable the IRQ to prevent the ISR from being triggered by */ + /* interrupts from other DMA channels */ + irq_disable(cfg->irq_number); + channel = find_lsb_set(cfg->reg->UDMA_DONE_STATUS_REG); + /* Identify the interrupt channel */ + if (!channel || channel > cfg->channels) { + goto out; + } + /* find_lsb_set() returns 1 indexed value */ + channel -= 1; + if (data->udma_channel_info[channel].Cnt == data->udma_channel_info[channel].Size) { + if (data->dma_callback) { + /* Transfer complete, call user callback */ + data->dma_callback(dev, data->cb_data, channel + 1, 0); + } + cfg->reg->UDMA_DONE_STATUS_REG = BIT(channel); + } else { + /* Call UDMA ROM IRQ handler. */ + ROMAPI_UDMA_WRAPPER_API->uDMAx_IRQHandler(&UDMA_Resources, UDMA_Resources.desc, + data->udma_channel_info); + /* Is a Memory-to-memory Transfer */ + if (UDMA_Resources.desc[channel].vsUDMAChaConfigData1.srcInc != UDMA_SRC_INC_NONE && + UDMA_Resources.desc[channel].vsUDMAChaConfigData1.dstInc != UDMA_DST_INC_NONE) { + /* Set the software trigger bit for starting next transfer */ + cfg->reg->CHNL_SW_REQUEST |= BIT(channel); + } + } +out: + /* Enable the IRQ to restore interrupt functionality for other DMA channels */ + irq_enable(cfg->irq_number); +} + +/* Store the Si91x DMA APIs */ +static const struct dma_driver_api siwx917_dma_driver_api = { + .config = dma_siwx917_configure, + .reload = dma_siwx917_reload, + .start = dma_siwx917_start, + .stop = dma_siwx917_stop, + .get_status = dma_siwx917_get_status, +}; + +#define SIWX917_DMA_INIT(inst) \ + static UDMA_Channel_Info dma##inst##_channel_info[DT_INST_PROP(inst, dma_channels)]; \ + static struct dma_siwx917_data dma##inst##_data = { \ + .udma_channel_info = dma##inst##_channel_info, \ + }; \ + static void siwx917_dma##inst##_irq_configure(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQ(inst, irq), DT_INST_IRQ(inst, priority), dma_siwx917_isr, \ + DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQ(inst, irq)); \ + } \ + static const struct dma_siwx917_config dma##inst##_cfg = { \ + .reg = (UDMA0_Type *)DT_INST_REG_ADDR(inst), \ + .channels = DT_INST_PROP(inst, dma_channels), \ + .irq_number = DT_INST_PROP_BY_IDX(inst, interrupts, 0), \ + .sram_desc_addr = DT_INST_PROP(inst, silabs_sram_desc_addr), \ + .irq_configure = siwx917_dma##inst##_irq_configure, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &dma_siwx917_init, NULL, &dma##inst##_data, &dma##inst##_cfg, \ + PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, &siwx917_dma_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SIWX917_DMA_INIT) diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index ccdace2..4dec4e8 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -221,6 +221,32 @@ compatible = "silabs,siwx917-rng"; reg = <0x45090000 0x8>; }; + + udma0: dma@44030000 { + compatible = "silabs,siwx917-dma"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x44030000 0x82C>; + interrupts = <33 0>; + interrupt-names = "udma0"; + silabs,sram-desc-addr = <0x2fc00>; + #dma-cells = < 1>; + dma-channels = <32>; + status = "disabled"; + }; + + udma1: dma@24078000 { + compatible = "silabs,siwx917-dma"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x24078000 0x82C>; + interrupts = <10 0>; + interrupt-names = "udma1"; + silabs,sram-desc-addr = <0x24061c00>; + #dma-cells = < 1>; + dma-channels = <12>; + status = "disabled"; + }; }; }; diff --git a/dts/bindings/dma/silabs,siwx917-dma.yaml b/dts/bindings/dma/silabs,siwx917-dma.yaml new file mode 100644 index 0000000..37251b3 --- /dev/null +++ b/dts/bindings/dma/silabs,siwx917-dma.yaml @@ -0,0 +1,26 @@ +description: Silabs SiWx917 DMA node + +compatible: "silabs,siwx917-dma" + +include: dma-controller.yaml + +properties: + reg: + required: true + + silabs,sram-desc-addr: + type: int + required: true + description: | + SRAM Address for UDMA Descriptor Storage. This address must correspond to the location + of the udma_addr0 section in the linker script for the udma0 node, and the udma_addr1 + section for the udma1 node. Ensure that the value specified for the SRAM address matches + the respective section defined in the linker file for each UDMA node, as this alignment + is critical for proper descriptor management and data transfer. + + "#dma-cells": + const: 1 + +# Parameter syntax +dma-cells: + - channel diff --git a/modules/hal_silabs/wiseconnect/CMakeLists.txt b/modules/hal_silabs/wiseconnect/CMakeLists.txt index 90dae8a..45bfef0 100644 --- a/modules/hal_silabs/wiseconnect/CMakeLists.txt +++ b/modules/hal_silabs/wiseconnect/CMakeLists.txt @@ -58,6 +58,14 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_SILABS_SIWX917 ${DEVICE_DIR}/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_rng.c ) +zephyr_library_sources_ifdef(CONFIG_DMA_SILABS_SIWX917 + ${DEVICE_DIR}/silabs/si91x/mcu/drivers/rom_driver/src/rsi_rom_table_si91x.c +) + +zephyr_compile_definitions_ifdef(CONFIG_DMA_SILABS_SIWX917 + UDMA_ROMDRIVER_PRESENT +) + if(CONFIG_WIFI_SIWX917) zephyr_compile_definitions_ifdef(CONFIG_NET_IPV6 diff --git a/soc/silabs/silabs_siwx917/siwg917/linker.ld b/soc/silabs/silabs_siwx917/siwg917/linker.ld index 0b37a04..24f6b42 100644 --- a/soc/silabs/silabs_siwx917/siwg917/linker.ld +++ b/soc/silabs/silabs_siwx917/siwg917/linker.ld @@ -5,10 +5,29 @@ */ #include +MEMORY +{ + udma0 (rwx) : ORIGIN = 0x0002fc00, LENGTH = 0x00000400 + udma1 (rwx) : ORIGIN = 0x24061c00, LENGTH = 0x00000400 +} + SECTIONS { .common_tcm_code : { *(.common_tcm_code*) } > FLASH + + /* These regions of SRAM is where the UDMA descriptors are stored. The corresponding + section must be properly declared in the linker script to ensure correct data transfer + and proper functioning of the UDMA module */ + .udma_addr0 : + { + *(.udma_addr0*) + } > udma0 AT> FLASH + + .udma_addr1 : + { + *(.udma_addr1*) + } > udma1 AT> FLASH } diff --git a/soc/silabs/silabs_siwx917/siwg917/soc.c b/soc/silabs/silabs_siwx917/siwg917/soc.c index dcac51d..3d58bef 100644 --- a/soc/silabs/silabs_siwx917/siwg917/soc.c +++ b/soc/silabs/silabs_siwx917/siwg917/soc.c @@ -48,6 +48,14 @@ int silabs_siwx917_init(void) RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_I2C); RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_I2C_CLK, ENABLE_STATIC_CLK); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(udma0), okay) + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + RSI_CLK_PeripheralClkEnable(M4CLK, UDMA_CLK, ENABLE_STATIC_CLK); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(udma1), okay) + RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_UDMA); + RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_UDMA_CLK, ENABLE_STATIC_CLK); +#endif return 0; } diff --git a/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf b/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf new file mode 100644 index 0000000..542bad6 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.conf @@ -0,0 +1,4 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=1 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=2 +CONFIG_DMA_LOOP_TRANSFER_NUMBER_OF_DMAS=2 +CONFIG_DMA_TRANSFER_BURST16=n diff --git a/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay b/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay new file mode 100644 index 0000000..c1de2ed --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/siwx917_rb4338a.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +tst_dma0: &udma0 { + status = "okay"; +}; + +tst_dma1: &udma1 { + status = "okay"; +}; diff --git a/west.yml b/west.yml index 1ff7f5d..e8f67ce 100644 --- a/west.yml +++ b/west.yml @@ -11,7 +11,7 @@ manifest: projects: - name: hal_silabs remote: silabs - revision: 72fb0e677fb0ab09981c1217e38c4246ad4b5dcd + revision: pull/11/head path: modules/hal/silabs - name: zephyr remote: zephyrproject-rtos