Skip to content

Commit

Permalink
drivers: dma: siwx917: Review comment changes
Browse files Browse the repository at this point in the history
Addressing the review comments (version 1).
This commit will be squashed before merging. It has been added to
facilitate the review process of the recent changes.

Signed-off-by: Sai Santhosh Malae <[email protected]>
  • Loading branch information
smalae committed Jan 9, 2025
1 parent 99c06c1 commit 3f3c34e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 73 deletions.
12 changes: 6 additions & 6 deletions drivers/dma/Kconfig.siwx917
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ menuconfig DMA_SILABS_SIWX917
Enable the High Power(HP)/Ultra Low Power(ULP) DMA driver for the Silabs SiWx917 SoC series.

if DMA_SILABS_SIWX917
config DMA_SILABS_SIWX917_COMMON_INIT_PRIORITY
int "Common initialization priority"
default 42
config DMA_SILABS_SIWX917_COMMON_INIT_PRIORITY
int "Common initialization priority"
default 42

config DMA_SILABS_SIWX917_SG_BUFFER_COUNT
int "The maximum allowable number of buffers for scatter-gather transfers"
default 10
config DMA_SILABS_SIWX917_SG_BUFFER_COUNT
int "The maximum allowable number of buffers for scatter-gather transfers"
default 10
endif
144 changes: 77 additions & 67 deletions drivers/dma/dma_silabs_siwx917.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <errno.h>
#include <zephyr/irq.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/sys_io.h>
#include <zephyr/device.h>
#include <zephyr/drivers/dma.h>
#include <zephyr/logging/log.h>
Expand All @@ -30,8 +31,9 @@ LOG_MODULE_REGISTER(si91x_dma, CONFIG_DMA_LOG_LEVEL);
struct dma_sg_descriptor_allocator {
/* DMA descriptors in contiguous memory */
RSI_UDMA_DESC_T sg_transfer_desc_table[CONFIG_DMA_SILABS_SIWX917_SG_BUFFER_COUNT];
/* Pointer to bitmap representing the allocation status of descriptors */
/* with each bit indicating the status of a single descriptor */
/* Pointer to bitmap representing the allocation status of descriptors
* with each bit indicating the status of a single descriptor
*/
sys_bitarray_t *free_desc;
};

Expand All @@ -49,8 +51,9 @@ struct dma_siwx917_data {
void *cb_data; /* User callback data */
struct dma_sg_descriptor_allocator
*sg_transfer_desc_block; /* Pointer to scatter-gather descriptors block */
RSI_UDMA_DATACONTEXT_T dma_rom_buff; /* Buffer to store UDMA handle */
/* related information */
RSI_UDMA_DATACONTEXT_T dma_rom_buff; /* Buffer to store UDMA handle
* related information
*/
};

static inline int siwx917_dma_is_peripheral_request(uint32_t dir)
Expand Down Expand Up @@ -102,91 +105,86 @@ static inline int siwx917_dma_addr_adjustment(uint32_t adjustment)

/* Releases a range of scatter-gather descriptors */
static inline void release_sg_desc_blocks(sys_bitarray_t *desc_alloc, uint32_t start_index,
uint32_t count)
uint32_t block_count)
{
sys_bitarray_clear_region(desc_alloc, count, start_index);
sys_bitarray_clear_region(desc_alloc, block_count, start_index);
}

/* Requests the index of contiguous memory for scatter-gather descriptor table */
static int request_sg_desc_base_addr(sys_bitarray_t *desc_alloc, uint32_t block_count)
{
uint32_t index;
uint32_t i;

/* Find contiguous free blocks */
for (index = 0; index <= CONFIG_DMA_SILABS_SIWX917_SG_BUFFER_COUNT - block_count; index++) {
if (sys_bitarray_is_region_cleared(desc_alloc, block_count, index)) {
for (i = 0; i <= CONFIG_DMA_SILABS_SIWX917_SG_BUFFER_COUNT - block_count; i++) {
if (sys_bitarray_is_region_cleared(desc_alloc, block_count, i)) {
break;
}
}
if (index > CONFIG_DMA_SILABS_SIWX917_SG_BUFFER_COUNT - block_count) {
if (i > CONFIG_DMA_SILABS_SIWX917_SG_BUFFER_COUNT - block_count) {
/* No contiguous free blocks present */
return -EINVAL;
}
/* Mark the blocks as allocated */
if (sys_bitarray_set_region(desc_alloc, block_count, index) < 0) {
if (sys_bitarray_set_region(desc_alloc, block_count, i) < 0) {
return -EINVAL;
}
return index;
return i;
}

/* Sets up the scatter-gather descriptor table for a DMA transfer */
static int set_scatter_gather_desc(RSI_UDMA_DESC_T *sg_desc_base_addr, struct dma_config *config,
uint8_t *transfer_type)
static int set_scatter_gather_desc(RSI_UDMA_DESC_T *descs, const struct dma_config *config)
{
int peripheral_request = siwx917_dma_is_peripheral_request(config->channel_direction);
struct dma_block_config *block_addr = config->head_block;
volatile RSI_UDMA_CHA_CONFIG_DATA_T *cfg;

if (peripheral_request < 0) {
return -EINVAL;
} else if (peripheral_request) {
*transfer_type = UDMA_MODE_PER_SCATTER_GATHER;
}
for (int index = 0; index < config->block_count; index++) {
for (int i = 0; i < config->block_count; i++) {
cfg = &descs[i].vsUDMAChaConfigData1;
/* Set the source and destination end addresses */
sg_desc_base_addr[index].pSrcEndAddr =
descs[i].pSrcEndAddr =
(uint32_t *)(block_addr->source_address +
(block_addr->block_size - config->source_data_size));
sg_desc_base_addr[index].pDstEndAddr =
descs[i].pDstEndAddr =
(uint32_t *)(block_addr->dest_address +
(block_addr->block_size - config->dest_data_size));
/* Set the source and destination data sizes */
sg_desc_base_addr[index].vsUDMAChaConfigData1.srcSize =
siwx917_dma_data_width(config->source_data_size);
sg_desc_base_addr[index].vsUDMAChaConfigData1.dstSize =
siwx917_dma_data_width(config->dest_data_size);
cfg->srcSize = siwx917_dma_data_width(config->source_data_size);
cfg->dstSize = siwx917_dma_data_width(config->dest_data_size);
/* Calculate the number of DMA transfers required */
block_addr->block_size /= config->source_data_size;
if (block_addr->block_size > DMA_MAX_TRANSFER_COUNT) {
return -EINVAL;
}
/* Set the total number of DMA transfers */
sg_desc_base_addr[index].vsUDMAChaConfigData1.totalNumOfDMATrans =
block_addr->block_size - 1;
cfg->totalNumOfDMATrans = block_addr->block_size - 1;
/* Set the transfer type based on whether it is a peripheral request */
sg_desc_base_addr[index].vsUDMAChaConfigData1.transferType =
peripheral_request ? UDMA_MODE_PER_ALT_SCATTER_GATHER
: UDMA_MODE_MEM_ALT_SCATTER_GATHER;
cfg->transferType = siwx917_dma_is_peripheral_request(config->channel_direction)
? UDMA_MODE_PER_ALT_SCATTER_GATHER
: UDMA_MODE_MEM_ALT_SCATTER_GATHER;
/* Set the arbitration size */
sg_desc_base_addr[index].vsUDMAChaConfigData1.rPower = ARBSIZE_1;
cfg->rPower = ARBSIZE_1;
if (siwx917_dma_addr_adjustment(block_addr->source_addr_adj) < 0 ||
siwx917_dma_addr_adjustment(block_addr->dest_addr_adj) < 0) {
return -EINVAL;
}
/* Set source and destination address increments */
sg_desc_base_addr[index].vsUDMAChaConfigData1.srcInc =
siwx917_dma_addr_adjustment(block_addr->source_addr_adj)
? UDMA_SRC_INC_NONE
: siwx917_dma_data_width(config->source_data_size);
sg_desc_base_addr[index].vsUDMAChaConfigData1.dstInc =
siwx917_dma_addr_adjustment(block_addr->dest_addr_adj)
? UDMA_DST_INC_NONE
: siwx917_dma_data_width(config->dest_data_size);
cfg->srcInc = siwx917_dma_addr_adjustment(block_addr->source_addr_adj)
? UDMA_SRC_INC_NONE
: siwx917_dma_data_width(config->source_data_size);
cfg->dstInc = siwx917_dma_addr_adjustment(block_addr->dest_addr_adj)
? UDMA_DST_INC_NONE
: siwx917_dma_data_width(config->dest_data_size);
/* Move to the next block */
block_addr = block_addr->next_block;
}
if (block_addr != NULL) {
/* next_block address for last block must be null */
return -EINVAL;
}
/* Set the transfer type for the last descriptor */
sg_desc_base_addr[config->block_count - 1].vsUDMAChaConfigData1.transferType =
peripheral_request ? UDMA_MODE_BASIC : UDMA_MODE_AUTO;
descs[config->block_count - 1].vsUDMAChaConfigData1.transferType =
siwx917_dma_is_peripheral_request(config->channel_direction) ? UDMA_MODE_BASIC
: UDMA_MODE_AUTO;
return 0;
}

Expand All @@ -200,6 +198,11 @@ static int dma_scatter_gather_config(const struct device *dev, RSI_UDMA_HANDLE_T
RSI_UDMA_DESC_T *sg_desc_base_addr = NULL;
int block_alloc_start_index;

if (siwx917_dma_is_peripheral_request(config->channel_direction) == 1) {
transfer_type = UDMA_MODE_PER_SCATTER_GATHER;
} else if (siwx917_dma_is_peripheral_request(config->channel_direction) < 0) {
return -EINVAL;
}
if (siwx917_dma_data_width(config->source_data_size) < 0 ||
siwx917_dma_data_width(config->dest_data_size) < 0) {
return -EINVAL;
Expand All @@ -215,24 +218,26 @@ static int dma_scatter_gather_config(const struct device *dev, RSI_UDMA_HANDLE_T
}
sg_desc_base_addr =
&data->sg_transfer_desc_block->sg_transfer_desc_table[block_alloc_start_index];
if (set_scatter_gather_desc(sg_desc_base_addr, config, &transfer_type)) {
if (set_scatter_gather_desc(sg_desc_base_addr, config)) {
return -EINVAL;
}
/* This channel information is used to distinguish scatter-gather transfers and */
/* free the allocated descriptors in sg_transfer_desc_block */
/* This channel information is used to distinguish scatter-gather transfers and
* free the allocated descriptors in sg_transfer_desc_block
*/
data->chan_info[channel].SrcAddr = 0;
data->chan_info[channel].DestAddr = 0;
data->chan_info[channel].Cnt = config->block_count;
data->chan_info[channel].Size = block_alloc_start_index;
RSI_UDMA_InterruptClear(udma_handle, channel);
RSI_UDMA_ErrorStatusClear(udma_handle);
if (cfg->reg == UDMA0) {
M4SS_UDMA_INTR_SEL |= BIT(channel);
sys_write32((BIT(channel) | M4SS_UDMA_INTR_SEL), (mem_addr_t)&M4SS_UDMA_INTR_SEL);
} else {
cfg->reg->UDMA_INTR_MASK_REG |= BIT(channel);
sys_write32((BIT(channel) | cfg->reg->UDMA_INTR_MASK_REG),
(mem_addr_t)&cfg->reg->UDMA_INTR_MASK_REG);
}
cfg->reg->CHNL_PRI_ALT_SET = BIT(channel);
cfg->reg->CHNL_REQ_MASK_CLR = BIT(channel);
sys_write32(BIT(channel), (mem_addr_t)&cfg->reg->CHNL_PRI_ALT_SET);
sys_write32(BIT(channel), (mem_addr_t)&cfg->reg->CHNL_REQ_MASK_CLR);
RSI_UDMA_SetChannelScatterGatherTransfer(udma_handle, channel, config->block_count,
sg_desc_base_addr, transfer_type);
return 0;
Expand Down Expand Up @@ -300,10 +305,11 @@ static int dma_channel_config(const struct device *dev, RSI_UDMA_HANDLE_T udma_h
} else {
channel_control.dstInc = UDMA_DST_INC_NONE;
}
status = UDMAx_ChannelConfigure(
&udma_resources, (uint8_t)channel, config->head_block->source_address,
config->head_block->dest_address, config->head_block->block_size, channel_control,
&channel_config, NULL, channel_info, udma_handle);
status = UDMAx_ChannelConfigure(&udma_resources, (uint8_t)channel,
config->head_block->source_address,
config->head_block->dest_address,
config->head_block->block_size, channel_control,
&channel_config, NULL, channel_info, udma_handle);
if (status) {
return -EIO;
}
Expand Down Expand Up @@ -334,7 +340,8 @@ static int dma_siwx917_configure(const struct device *dev, uint32_t channel,
return -EINVAL;
}

if (config->head_block->source_gather_en || config->head_block->dest_scatter_en) {
if (config->head_block->source_gather_en || config->head_block->dest_scatter_en ||
config->cyclic) {
/* Configure DMA for a Scatter-Gather transfer */
status = dma_scatter_gather_config(dev, udma_handle, channel, config);
} else {
Expand Down Expand Up @@ -420,7 +427,8 @@ static int dma_siwx917_start(const struct device *dev, uint32_t channel)
if (udma_table[channel].vsUDMAChaConfigData1.srcInc != UDMA_SRC_INC_NONE &&
udma_table[channel].vsUDMAChaConfigData1.dstInc != UDMA_DST_INC_NONE) {
/* Apply software trigger to start transfer */
cfg->reg->CHNL_SW_REQUEST |= BIT(channel);
sys_write32((BIT(channel) | cfg->reg->CHNL_SW_REQUEST),
(mem_addr_t)&cfg->reg->CHNL_SW_REQUEST);
}
return 0;
}
Expand Down Expand Up @@ -454,7 +462,7 @@ static int dma_siwx917_get_status(const struct device *dev, uint32_t channel,
return -EINVAL;
}
/* Read the channel status register */
if (cfg->reg->CHANNEL_STATUS_REG & BIT(channel)) {
if (sys_read32((mem_addr_t)&cfg->reg->CHANNEL_STATUS_REG) & BIT(channel)) {
stat->busy = 1;
} else {
stat->busy = 0;
Expand Down Expand Up @@ -519,8 +527,9 @@ static void dma_siwx917_isr(const struct device *dev)
};
uint8_t channel;

/* Disable the IRQ to prevent the ISR from being triggered by */
/* interrupts from other DMA channels */
/* 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 */
Expand All @@ -533,10 +542,15 @@ static void dma_siwx917_isr(const struct device *dev)
/* A Scatter-Gather transfer is completed, free the allocated descriptors */
release_sg_desc_blocks(data->sg_transfer_desc_block->free_desc,
data->chan_info[channel].Size, data->chan_info[channel].Cnt);
goto out;
data->chan_info[channel].Cnt = 0;
data->chan_info[channel].Size = 0;
}
if (data->chan_info[channel].Cnt == data->chan_info[channel].Size) {
goto out;
if (data->dma_callback) {
/* Transfer complete, call user callback */
data->dma_callback(dev, data->cb_data, channel, 0);
}
sys_write32(BIT(channel), (mem_addr_t)&cfg->reg->UDMA_DONE_STATUS_REG);
} else {
/* Call UDMA ROM IRQ handler. */
ROMAPI_UDMA_WRAPPER_API->uDMAx_IRQHandler(&udma_resources, udma_resources.desc,
Expand All @@ -545,15 +559,11 @@ static void dma_siwx917_isr(const struct device *dev)
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);
sys_write32((BIT(channel) | cfg->reg->CHNL_SW_REQUEST),
(mem_addr_t)&cfg->reg->CHNL_SW_REQUEST);
}
}
out:
if (data->dma_callback) {
/* Transfer complete, call user callback */
data->dma_callback(dev, data->cb_data, channel, 0);
}
cfg->reg->UDMA_DONE_STATUS_REG = BIT(channel);
/* Enable the IRQ to restore interrupt functionality for other DMA channels */
irq_enable(cfg->irq_number);
}
Expand Down

0 comments on commit 3f3c34e

Please sign in to comment.