Skip to content

drivers: dma: silabs: modify LDMA driver to handle large dma_block_config #92960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/dma/Kconfig.silabs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if DMA_SILABS_LDMA

config DMA_MAX_DESCRIPTOR
int "Max Number of block_config (LDMA_Descriptor)"
default 8
default 16
help
Max Number of block_config (LDMA_Descriptor)

Expand Down
66 changes: 45 additions & 21 deletions drivers/dma/dma_silabs_ldma.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,12 @@ static int dma_silabs_get_blocksize(uint32_t src_blen, uint32_t dst_blen, uint32

static int dma_silabs_block_to_descriptor(struct dma_config *config,
struct dma_silabs_channel *chan_conf,
struct dma_block_config *block, LDMA_Descriptor_t *desc)
struct dma_block_config *block, LDMA_Descriptor_t *desc,
int *offset)
{
int ret, src_size, xfer_count;
int ret, src_size, xfer_count, loc_offset, mod, rem_bsize;

loc_offset = *offset;

if (block->dest_scatter_count || block->source_gather_count ||
block->source_gather_interval || block->dest_scatter_interval ||
Expand Down Expand Up @@ -123,17 +126,27 @@ static int dma_silabs_block_to_descriptor(struct dma_config *config,
src_size = config->source_data_size;
desc->xfer.size = LOG2(src_size);

if (block->block_size % config->source_data_size) {
xfer_count = block->block_size / config->source_data_size;
if (loc_offset) {
rem_bsize = block->block_size - loc_offset * config->source_data_size;
} else {
xfer_count = block->block_size / config->source_data_size - 1;
rem_bsize = block->block_size;
}

xfer_count = rem_bsize / config->source_data_size;
mod = rem_bsize % config->source_data_size;

if (xfer_count > LDMA_DESCRIPTOR_MAX_XFER_SIZE) {
return -ENOTSUP;
}
desc->xfer.xferCnt = LDMA_DESCRIPTOR_MAX_XFER_SIZE - 1;
*offset = loc_offset + LDMA_DESCRIPTOR_MAX_XFER_SIZE;

desc->xfer.xferCnt = xfer_count;
} else {
if (!mod || xfer_count == LDMA_DESCRIPTOR_MAX_XFER_SIZE) {
xfer_count--;
}

desc->xfer.xferCnt = xfer_count;
*offset = 0;
}

/* Warning : High LDMA blockSize (high burst) mean a large transfer
* without LDMA controller re-arbitration.
Expand Down Expand Up @@ -195,8 +208,8 @@ static int dma_silabs_block_to_descriptor(struct dma_config *config,
LOG_WRN("dest_buffer address is null.");
}

desc->xfer.srcAddr = block->source_address;
desc->xfer.dstAddr = block->dest_address;
desc->xfer.srcAddr = block->source_address + loc_offset * config->source_data_size;
desc->xfer.dstAddr = block->dest_address + loc_offset * config->dest_data_size;

return 0;
}
Expand Down Expand Up @@ -229,21 +242,22 @@ static int dma_silabs_configure_descriptor(struct dma_config *config, struct dma
struct dma_block_config *head_block = config->head_block;
struct dma_block_config *block = config->head_block;
LDMA_Descriptor_t *desc, *prev_desc;
int ret;
int ret, offset;

/* Descriptors configuration
* block refers to user configured block (dma_block_config structure from dma.h)
* desc refers to driver configured block (LDMA_Descriptor_t structure from silabs
* hal)
*/
prev_desc = NULL;
offset = 0;
while (block) {
ret = sys_mem_blocks_alloc(data->dma_desc_pool, 1, (void **)&desc);
if (ret) {
goto err;
}

ret = dma_silabs_block_to_descriptor(config, chan_conf, block, desc);
ret = dma_silabs_block_to_descriptor(config, chan_conf, block, desc, &offset);
if (ret) {
goto err;
}
Expand All @@ -257,13 +271,15 @@ static int dma_silabs_configure_descriptor(struct dma_config *config, struct dma
}

prev_desc = desc;
block = block->next_block;
if (block == head_block) {
block = NULL;
prev_desc->xfer.linkAddr =
LDMA_DESCRIPTOR_LINKABS_ADDR_TO_LINKADDR(chan_conf->desc);
prev_desc->xfer.linkMode = ldmaLinkModeAbs;
prev_desc->xfer.link = 1;
if (!offset) {
block = block->next_block;
if (block == head_block) {
block = NULL;
prev_desc->xfer.linkAddr =
LDMA_DESCRIPTOR_LINKABS_ADDR_TO_LINKADDR(chan_conf->desc);
prev_desc->xfer.linkMode = ldmaLinkModeAbs;
prev_desc->xfer.link = 1;
}
}
}

Expand Down Expand Up @@ -525,7 +541,9 @@ int silabs_ldma_append_block(const struct device *dev, uint32_t channel, struct
struct dma_block_config *block_config = config->head_block;
LDMA_Descriptor_t *desc = data->dma_chan_table[channel].desc;
unsigned int key;
int ret;
int ret, offset;

offset = 0;

__ASSERT(!((uintptr_t)desc & ~_LDMA_CH_LINK_LINKADDR_MASK),
"DMA Descriptor is not 32 bits aligned");
Expand All @@ -552,9 +570,15 @@ int silabs_ldma_append_block(const struct device *dev, uint32_t channel, struct
return -EINVAL;
}

ret = dma_silabs_block_to_descriptor(config, chan_conf, block_config, desc);
ret = dma_silabs_block_to_descriptor(config, chan_conf, block_config, desc, &offset);
if (ret) {
return ret;
} else if (offset) {
/* If the offset is not 0, it means that the block size is larger than the transfer
* capacity of a single hardware LDMA descriptor. It is not supported with the
* append function.
*/
return -EINVAL;
}

key = irq_lock();
Expand Down
1 change: 0 additions & 1 deletion tests/drivers/dma/loop_transfer/boards/sltb010a.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Copyright (c) 2024 Silicon Laboratories, Inc.
# SPDX-License-Identifier: Apache-2.0

CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=0
CONFIG_DMA_LOOP_TRANSFER_SIZE=2048
5 changes: 0 additions & 5 deletions tests/drivers/dma/loop_transfer/boards/slwrb4180a.conf

This file was deleted.

5 changes: 0 additions & 5 deletions tests/drivers/dma/loop_transfer/boards/xg23_rb4210a.conf

This file was deleted.

5 changes: 0 additions & 5 deletions tests/drivers/dma/loop_transfer/boards/xg24_dk2601b.conf

This file was deleted.

5 changes: 0 additions & 5 deletions tests/drivers/dma/loop_transfer/boards/xg27_dk2602a.conf

This file was deleted.

4 changes: 0 additions & 4 deletions tests/drivers/dma/loop_transfer/boards/xg29_rb4412a.conf

This file was deleted.

1 change: 0 additions & 1 deletion tests/drivers/dma/scatter_gather/boards/sltb010a.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Copyright (c) 2024 Silicon Laboratories, Inc.
# SPDX-License-Identifier: Apache-2.0

CONFIG_DMA_SG_CHANNEL_NR=0
CONFIG_DMA_SG_XFER_SIZE=4096
3 changes: 0 additions & 3 deletions tests/drivers/dma/scatter_gather/boards/slwrb4180a.conf

This file was deleted.

4 changes: 0 additions & 4 deletions tests/drivers/dma/scatter_gather/boards/xg23_rb4210a.conf

This file was deleted.

4 changes: 0 additions & 4 deletions tests/drivers/dma/scatter_gather/boards/xg24_dk2601b.conf

This file was deleted.

4 changes: 0 additions & 4 deletions tests/drivers/dma/scatter_gather/boards/xg27_dk2602a.conf

This file was deleted.