diff --git a/drivers/dma/dma_silabs_siwx91x_gpdma.c b/drivers/dma/dma_silabs_siwx91x_gpdma.c index dc9170b1d4c71..cce5367d89dbe 100644 --- a/drivers/dma/dma_silabs_siwx91x_gpdma.c +++ b/drivers/dma/dma_silabs_siwx91x_gpdma.c @@ -132,7 +132,7 @@ static int siwx91x_gpdma_desc_config(struct siwx19x_gpdma_data *data, const struct dma_config *config, const RSI_GPDMA_DESC_T *xfer_cfg, uint32_t channel) { - uint16_t max_xfer_size = GPDMA_DESC_MAX_TRANSFER_SIZE - config->source_data_size; + int operation_width = config->source_data_size * config->source_burst_length; const struct dma_block_config *block_addr = config->head_block; RSI_GPDMA_DESC_T *cur_desc = NULL; RSI_GPDMA_DESC_T *prev_desc = NULL; @@ -140,8 +140,14 @@ static int siwx91x_gpdma_desc_config(struct siwx19x_gpdma_data *data, int ret; for (int i = 0; i < config->block_count; i++) { - if (block_addr->block_size > max_xfer_size) { - LOG_ERR("Maximum xfer size should be <= %d\n", max_xfer_size); + if (!IS_ALIGNED(block_addr->source_address, config->source_burst_length) || + !IS_ALIGNED(block_addr->dest_address, config->dest_burst_length) || + !IS_ALIGNED(block_addr->block_size, operation_width)) { + LOG_ERR("Buffer not aligned\n"); + goto free_desc; + } + if (block_addr->block_size >= GPDMA_DESC_MAX_TRANSFER_SIZE) { + LOG_ERR("Buffer too large (%d bytes)\n", block_addr->block_size); goto free_desc; } diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index 2fb7e06dd549f..ff9e6fded2fc6 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(spi_siwx91x_gspi, CONFIG_SPI_LOG_LEVEL); #define GSPI_MAX_BAUDRATE_FOR_DYNAMIC_CLOCK 110000000 #define GSPI_MAX_BAUDRATE_FOR_POS_EDGE_SAMPLE 40000000 -#define GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE 1024 +#define GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE 4096 /* Warning for unsupported configurations */ #if defined(CONFIG_SPI_ASYNC) && !defined(CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA) @@ -34,6 +34,7 @@ LOG_MODULE_REGISTER(spi_siwx91x_gspi, CONFIG_SPI_LOG_LEVEL); /* Structure for DMA configuration */ struct gspi_siwx91x_dma_channel { const struct device *dma_dev; + uint8_t dma_slot; int chan_nb; #ifdef CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA struct dma_block_config dma_descriptors[CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA_MAX_BLOCKS]; @@ -45,7 +46,7 @@ struct gspi_siwx91x_config { const struct device *clock_dev; clock_control_subsys_t clock_subsys; const struct pinctrl_dev_config *pcfg; - uint8_t mosi_overrun; + uint8_t mosi_overrun __aligned(4); }; struct gspi_siwx91x_data { @@ -56,7 +57,7 @@ struct gspi_siwx91x_data { #ifdef CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA /* Placeholder buffer for unused RX data */ -static volatile uint8_t empty_buffer; +static volatile uint8_t empty_buffer __aligned(4); #endif static bool spi_siwx91x_is_dma_enabled_instance(const struct device *dev) @@ -217,13 +218,15 @@ static int gspi_siwx91x_dma_config(const struct device *dev, { struct dma_config cfg = { .channel_direction = is_tx ? MEMORY_TO_PERIPHERAL : PERIPHERAL_TO_MEMORY, + .channel_priority = 1, .complete_callback_en = 0, .source_data_size = dfs, .dest_data_size = dfs, - .source_burst_length = dfs, - .dest_burst_length = dfs, + .source_burst_length = 1, + .dest_burst_length = 1, .block_count = block_count, .head_block = channel->dma_descriptors, + .dma_slot = channel->dma_slot, .dma_callback = !is_tx ? &gspi_siwx91x_dma_rx_callback : NULL, .user_data = (void *)dev, }; @@ -233,7 +236,7 @@ static int gspi_siwx91x_dma_config(const struct device *dev, static uint32_t gspi_siwx91x_fill_desc(const struct gspi_siwx91x_config *cfg, struct dma_block_config *new_blk_cfg, uint8_t *buffer, - size_t requested_transaction_size, bool is_tx, uint8_t dfs) + size_t requested_transaction_size, bool is_tx) { /* Set-up source and destination address with increment behavior */ @@ -261,11 +264,11 @@ static uint32_t gspi_siwx91x_fill_desc(const struct gspi_siwx91x_config *cfg, } } - /* Setup max transfer according to requested transaction size. - * Will top if bigger than the maximum transfer size. + /* The underlying DMA can sent a bit less than 4k of data depending of the data size of and + * the burst length. We avoid complex computation, 32 bytes fits all the cases. */ - new_blk_cfg->block_size = - MIN(requested_transaction_size, GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE * dfs); + new_blk_cfg->block_size = MIN(requested_transaction_size, + GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE - 32); return new_blk_cfg->block_size; } @@ -273,7 +276,7 @@ struct dma_block_config *gspi_siwx91x_fill_data_desc(const struct gspi_siwx91x_c struct dma_block_config *desc, const struct spi_buf buffers[], int buffer_count, size_t transaction_len, - bool is_tx, uint8_t dfs) + bool is_tx) { __ASSERT(transaction_len > 0, "Not supported"); @@ -294,8 +297,7 @@ struct dma_block_config *gspi_siwx91x_fill_data_desc(const struct gspi_siwx91x_c /* Calculate the buffer pointer with the current offset */ buffer = buffers[i].buf ? (uint8_t *)buffers[i].buf + offset : NULL; /* Fill the descriptor with the buffer data and update the offset */ - offset += gspi_siwx91x_fill_desc(cfg, desc, buffer, buffers[i].len - offset, is_tx, - dfs); + offset += gspi_siwx91x_fill_desc(cfg, desc, buffer, buffers[i].len - offset, is_tx); /* If the end of the current buffer is reached, move to the next buffer */ if (offset == buffers[i].len) { transaction_len -= offset; @@ -314,8 +316,7 @@ struct dma_block_config *gspi_siwx91x_fill_data_desc(const struct gspi_siwx91x_c return NULL; } - transaction_len -= gspi_siwx91x_fill_desc(cfg, desc, NULL, - transaction_len, is_tx, dfs); + transaction_len -= gspi_siwx91x_fill_desc(cfg, desc, NULL, transaction_len, is_tx); if (transaction_len) { desc = desc->next_block; } @@ -351,7 +352,7 @@ static int gspi_siwx91x_prepare_dma_channel(const struct device *spi_dev, gspi_siwx91x_reset_desc(channel); desc = gspi_siwx91x_fill_data_desc(cfg, channel->dma_descriptors, buffer, buffer_count, - padded_transaction_size, is_tx, dfs); + padded_transaction_size, is_tx); if (!desc) { return -ENOMEM; } @@ -407,7 +408,8 @@ static int gspi_siwx91x_transceive_dma(const struct device *dev, const struct sp return -EINVAL; } - /* Reset the Rx and Tx FIFO register */ + cfg->reg->GSPI_FIFO_THRLD_b.RFIFO_RESET = 1; + cfg->reg->GSPI_FIFO_THRLD_b.WFIFO_RESET = 1; cfg->reg->GSPI_FIFO_THRLD = 0; ret = gspi_siwx91x_prepare_dma_transaction(dev, padded_transaction_size); @@ -637,8 +639,8 @@ static DEVICE_API(spi, gspi_siwx91x_driver_api) = { .dma_##dir = { \ .chan_nb = DT_INST_DMAS_CELL_BY_NAME(index, dir, channel), \ .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(index, dir)), \ + .dma_slot = DT_DMAS_CELL_BY_NAME_OR(index, dir, slot, 0), \ }, - #define SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL(index, dir) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(index, dmas), \ (SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL_INIT(index, dir)), ()) @@ -652,9 +654,9 @@ static DEVICE_API(spi, gspi_siwx91x_driver_api) = { SPI_CONTEXT_INIT_LOCK(gspi_data_##inst, ctx), \ SPI_CONTEXT_INIT_SYNC(gspi_data_##inst, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx) \ - SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL(inst, rx) \ - SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL(inst, tx) \ - }; \ + SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL(inst, rx) \ + SPI_SILABS_SIWX91X_GSPI_DMA_CHANNEL(inst, tx) \ + }; \ static const struct gspi_siwx91x_config gspi_config_##inst = { \ .reg = (GSPI0_Type *)DT_INST_REG_ADDR(inst), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \ diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index 1ccb7ee235094..58e22f1ceaf90 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -294,6 +294,20 @@ status = "disabled"; }; + ulpdma: dma@24078000 { + compatible = "silabs,siwx91x-dma"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x24078000 0x82C>; + interrupts = <10 0>; + interrupt-names = "ulpdma"; + clocks = <&clock0 SIWX91X_CLK_ULP_DMA>; + silabs,sram-region = <&sram_dma1>; + #dma-cells = <1>; + dma-channels = <12>; + status = "disabled"; + }; + dma0: dma@44030000 { compatible = "silabs,siwx91x-dma"; #address-cells = <1>; @@ -307,17 +321,17 @@ status = "disabled"; }; - ulpdma: dma@24078000 { - compatible = "silabs,siwx91x-dma"; + gpdma: gpdma@21080000 { + compatible = "silabs,gpdma"; #address-cells = <1>; #size-cells = <0>; - reg = <0x24078000 0x82C>; - interrupts = <10 0>; - interrupt-names = "ulpdma"; - clocks = <&clock0 SIWX91X_CLK_ULP_DMA>; - silabs,sram-region = <&sram_dma1>; - #dma-cells = <1>; - dma-channels = <12>; + reg = <0x21080000 0x1720>; + interrupts = <31 0>; + interrupt-names = "gpdma"; + clocks = <&clock0 SIWX91X_CLK_GPDMA0>; + silabs,channel-reg-base = <0x21081004>; + silabs,dma-channel-count = <8>; + #dma-cells = <2>; status = "disabled"; }; @@ -414,20 +428,6 @@ #io-channel-cells = <1>; status = "disabled"; }; - - gpdma0: gpdma@21080000 { - compatible = "silabs,gpdma"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x21080000 0x1720>; - interrupts = <31 0>; - interrupt-names = "gpdma0"; - clocks = <&clock0 SIWX91X_CLK_GPDMA0>; - silabs,channel-reg-base = <0x21081004>; - silabs,dma-channel-count = <8>; - #dma-cells = <2>; - status = "disabled"; - }; }; }; diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_dk2605a.overlay b/tests/drivers/spi/spi_loopback/boards/siwx917_dk2605a.overlay index 0ff4ed58edd01..4582430b59f69 100644 --- a/tests/drivers/spi/spi_loopback/boards/siwx917_dk2605a.overlay +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_dk2605a.overlay @@ -21,7 +21,7 @@ pinctrl-0 = <&spi0_default>; pinctrl-names = "default"; - dmas = <&dma0 11>, <&dma0 10>; + dmas = <&dma1 0 11>, <&dma1 1 10>; dma-names = "tx", "rx"; slow@0 { @@ -36,6 +36,6 @@ }; }; -&dma0 { +&dma1 { status = "okay"; }; diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.overlay b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.overlay index e1502cb3f135d..e5200624ec9cb 100644 --- a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.overlay +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.overlay @@ -21,7 +21,7 @@ pinctrl-0 = <&spi0_default>; pinctrl-names = "default"; - dmas = <&dma0 11>, <&dma0 10>; + dmas = <&gpdma 0 11>, <&gpdma 1 10>; dma-names = "tx", "rx"; slow@0 { @@ -36,6 +36,6 @@ }; }; -&dma0 { +&gpdma { status = "okay"; };