Skip to content

Commit 9ebba68

Browse files
smalaenashif
authored andcommitted
drivers: spi: siwx91x: Add support for higher burst rates using GPDMA
Enable higher SPI burst sizes when using GPDMA to improve throughput. Bursts are only enabled when both TX and RX channels use GPDMA and the SPI clock frequency is at least 10 MHz, as DMA flow control is unreliable at lower SPI rates. Signed-off-by: Sai Santhosh Malae <Santhosh.Malae@silabs.com>
1 parent 23c8db4 commit 9ebba68

File tree

1 file changed

+67
-9
lines changed

1 file changed

+67
-9
lines changed

drivers/spi/spi_silabs_siwx91x_gspi.c

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ LOG_MODULE_REGISTER(spi_siwx91x_gspi, CONFIG_SPI_LOG_LEVEL);
2727
#define GSPI_MAX_BAUDRATE_FOR_DYNAMIC_CLOCK 110000000
2828
#define GSPI_MAX_BAUDRATE_FOR_POS_EDGE_SAMPLE 40000000
2929
#define GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE 4096
30+
#define SPI_HIGH_BURST_FREQ_THRESHOLD_HZ 10000000
3031

3132
/* Warning for unsupported configurations */
3233
#if defined(CONFIG_SPI_ASYNC) && !defined(CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA)
@@ -247,16 +248,16 @@ static void gspi_siwx91x_dma_tx_callback(const struct device *dev, void *user_da
247248

248249
static int gspi_siwx91x_dma_config(const struct device *dev,
249250
struct gspi_siwx91x_dma_channel *channel, uint32_t block_count,
250-
bool is_tx, uint8_t dfs)
251+
bool is_tx, uint8_t dfs, uint8_t burst_size)
251252
{
252253
struct dma_config cfg = {
253254
.channel_direction = is_tx ? MEMORY_TO_PERIPHERAL : PERIPHERAL_TO_MEMORY,
254255
.channel_priority = 1,
255256
.complete_callback_en = 0,
256257
.source_data_size = dfs,
257258
.dest_data_size = dfs,
258-
.source_burst_length = 1,
259-
.dest_burst_length = 1,
259+
.source_burst_length = burst_size,
260+
.dest_burst_length = burst_size,
260261
.block_count = block_count,
261262
.head_block = channel->dma_descriptors,
262263
.dma_slot = channel->dma_slot,
@@ -374,7 +375,8 @@ static void gspi_siwx91x_reset_desc(struct gspi_siwx91x_dma_channel *channel)
374375
static int gspi_siwx91x_prepare_dma_channel(const struct device *spi_dev,
375376
const struct spi_buf *buffer, size_t buffer_count,
376377
struct gspi_siwx91x_dma_channel *channel,
377-
size_t padded_transaction_size, bool is_tx)
378+
size_t padded_transaction_size, bool is_tx,
379+
uint8_t burst_size)
378380
{
379381
const struct gspi_siwx91x_config *cfg = spi_dev->config;
380382
struct gspi_siwx91x_data *data = spi_dev->data;
@@ -391,12 +393,13 @@ static int gspi_siwx91x_prepare_dma_channel(const struct device *spi_dev,
391393
}
392394

393395
ret = gspi_siwx91x_dma_config(spi_dev, channel,
394-
ARRAY_INDEX(channel->dma_descriptors, desc) + 1, is_tx, dfs);
396+
ARRAY_INDEX(channel->dma_descriptors, desc) + 1, is_tx, dfs,
397+
burst_size);
395398
return ret;
396399
}
397400

398401
static int gspi_siwx91x_prepare_dma_transaction(const struct device *dev,
399-
size_t padded_transaction_size)
402+
size_t padded_transaction_size, uint8_t burst_size)
400403
{
401404
int ret;
402405
struct gspi_siwx91x_data *data = dev->data;
@@ -406,13 +409,15 @@ static int gspi_siwx91x_prepare_dma_transaction(const struct device *dev,
406409
}
407410

408411
ret = gspi_siwx91x_prepare_dma_channel(dev, data->ctx.current_tx, data->ctx.tx_count,
409-
&data->dma_tx, padded_transaction_size, true);
412+
&data->dma_tx, padded_transaction_size, true,
413+
burst_size);
410414
if (ret) {
411415
return ret;
412416
}
413417

414418
ret = gspi_siwx91x_prepare_dma_channel(dev, data->ctx.current_rx, data->ctx.rx_count,
415-
&data->dma_rx, padded_transaction_size, false);
419+
&data->dma_rx, padded_transaction_size, false,
420+
burst_size);
416421

417422
return ret;
418423
}
@@ -425,6 +430,34 @@ static size_t gspi_siwx91x_longest_transfer_size(struct spi_context *instance_ct
425430
return MAX(tx_transfer_size, rx_transfer_size);
426431
}
427432

433+
static int gspi_siwx91x_burst_size_buf(const struct spi_buf *dma_spi_buf)
434+
{
435+
int burst_len = 4;
436+
437+
if (!dma_spi_buf->buf || !dma_spi_buf->len) {
438+
return burst_len;
439+
}
440+
441+
burst_len = MIN(burst_len, BIT(find_lsb_set((uint32_t)dma_spi_buf->buf) - 1));
442+
burst_len = MIN(burst_len, BIT(find_lsb_set(dma_spi_buf->len) - 1));
443+
444+
return burst_len;
445+
}
446+
447+
static int gspi_siwx91x_burst_size(struct spi_context *ctx)
448+
{
449+
int burst_len = 4;
450+
451+
for (int i = 0; i < ctx->tx_count; i++) {
452+
burst_len = MIN(burst_len, gspi_siwx91x_burst_size_buf(ctx->current_tx + i));
453+
}
454+
455+
for (int i = 0; i < ctx->rx_count; i++) {
456+
burst_len = MIN(burst_len, gspi_siwx91x_burst_size_buf(ctx->current_rx + i));
457+
}
458+
459+
return burst_len;
460+
}
428461
#endif /* CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA */
429462

430463
static int gspi_siwx91x_transceive_dma(const struct device *dev, const struct spi_config *config)
@@ -435,17 +468,42 @@ static int gspi_siwx91x_transceive_dma(const struct device *dev, const struct sp
435468
const struct device *dma_dev = data->dma_rx.dma_dev;
436469
struct spi_context *ctx = &data->ctx;
437470
size_t padded_transaction_size = gspi_siwx91x_longest_transfer_size(ctx);
471+
uint8_t burst_size = 1;
438472
int ret = 0;
439473

440474
if (padded_transaction_size == 0) {
441475
return -EINVAL;
442476
}
443477

478+
if (config->frequency >= SPI_HIGH_BURST_FREQ_THRESHOLD_HZ &&
479+
data->dma_rx.dma_slot != 0xFF && data->dma_tx.dma_slot != 0xFF) {
480+
/* NOTE: This condition ensures that high burst rates are only used with GPDMA.
481+
*
482+
* GPDMA (General-Purpose DMA) supports higher burst rates and operates at higher
483+
* frequencies, unlike UDMA, which does not handle such speeds reliably.
484+
* Therefore, the DMA slots are validated to ensure that the active DMA channels
485+
* belong to GPDMA before enabling higher burst rates.
486+
*
487+
* Currently, DMA flow control (DMA_FLOW_CTRL) is not functioning correctly for
488+
* memory-to-peripheral and peripheral-to-memory transfers. As a result, at lower
489+
* SPI clock frequencies, GPDMA may read/write FIFOs at a much higher rate than the
490+
* SPI peripheral, causing synchronization issues. However, at higher SPI clock
491+
* frequencies (≥ 10 MHz), this timing mismatch is negligible, and higher burst
492+
* rates operate as expected.
493+
*
494+
* In summary, high burst rates are safely enabled only for SPI transfers running
495+
* at or above 10 MHz when using GPDMA.
496+
*/
497+
burst_size = gspi_siwx91x_burst_size(ctx);
498+
}
499+
444500
cfg->reg->GSPI_FIFO_THRLD_b.RFIFO_RESET = 1;
445501
cfg->reg->GSPI_FIFO_THRLD_b.WFIFO_RESET = 1;
446502
cfg->reg->GSPI_FIFO_THRLD = 0;
503+
cfg->reg->GSPI_FIFO_THRLD_b.FIFO_AEMPTY_THRLD = burst_size - 1;
504+
cfg->reg->GSPI_FIFO_THRLD_b.FIFO_AFULL_THRLD = burst_size - 1;
447505

448-
ret = gspi_siwx91x_prepare_dma_transaction(dev, padded_transaction_size);
506+
ret = gspi_siwx91x_prepare_dma_transaction(dev, padded_transaction_size, burst_size);
449507
if (ret) {
450508
return ret;
451509
}

0 commit comments

Comments
 (0)