Skip to content

Commit ebb69e6

Browse files
committed
dma_mcux_edma: Split configure function into helpers
There was actually three different types of configuration modes happening here, and this function was getting extremely bulky and hard to read due to the amount of nesting of conditionals. Split these into separate functions and call them appropriately depending on the type of transfer. Signed-off-by: Declan Snyder <[email protected]>
1 parent 26d57c9 commit ebb69e6

File tree

1 file changed

+174
-128
lines changed

1 file changed

+174
-128
lines changed

drivers/dma/dma_mcux_edma.c

Lines changed: 174 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,173 @@ static void dma_mcux_edma_multi_channels_irq_handler(const struct device *dev, u
272272
}
273273
#endif
274274

275+
static int dma_mcux_edma_configure_sg_loop(const struct device *dev,
276+
uint32_t channel,
277+
struct dma_config *config,
278+
edma_transfer_type_t transfer_type)
279+
{
280+
uint32_t hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
281+
edma_handle_t *p_handle = DEV_EDMA_HANDLE(dev, channel);
282+
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
283+
struct dma_block_config *block_config = config->head_block;
284+
int ret = 0;
285+
edma_tcd_t *tcd = NULL;
286+
287+
/* Loop SG mode */
288+
data->transfer_settings.write_idx = 0;
289+
data->transfer_settings.empty_tcds = CONFIG_DMA_TCD_QUEUE_SIZE;
290+
291+
EDMA_PrepareTransfer(
292+
&data->transferConfig, (void *)block_config->source_address,
293+
config->source_data_size, (void *)block_config->dest_address,
294+
config->dest_data_size, config->source_burst_length,
295+
block_config->block_size, transfer_type);
296+
297+
/* Init all TCDs with the para in transfer config and link them. */
298+
for (int i = 0; i < CONFIG_DMA_TCD_QUEUE_SIZE; i++) {
299+
#if defined(CONFIG_DMA_MCUX_EDMA_V5)
300+
EDMA_TcdSetTransferConfigExt(DEV_BASE(dev),
301+
&DEV_CFG(dev)->tcdpool[channel][i], &data->transferConfig,
302+
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
303+
CONFIG_DMA_TCD_QUEUE_SIZE]);
304+
/* Enable Major loop interrupt.*/
305+
EDMA_TcdEnableInterruptsExt(DEV_BASE(dev),
306+
&DEV_CFG(dev)->tcdpool[channel][i],
307+
kEDMA_MajorInterruptEnable);
308+
#else
309+
EDMA_TcdSetTransferConfig(&DEV_CFG(dev)->tcdpool[channel][i],
310+
&data->transferConfig,
311+
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
312+
CONFIG_DMA_TCD_QUEUE_SIZE]);
313+
EDMA_TcdEnableInterrupts(&DEV_CFG(dev)->tcdpool[channel][i],
314+
kEDMA_MajorInterruptEnable);
315+
#endif
316+
}
317+
318+
/* Load valid transfer parameters */
319+
while (block_config != NULL && data->transfer_settings.empty_tcds > 0) {
320+
tcd = &(DEV_CFG(dev)->tcdpool[channel]
321+
[data->transfer_settings.write_idx]);
322+
323+
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
324+
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
325+
MEMORY_ConvertMemoryMapAddress(
326+
(uint32_t)(block_config->source_address),
327+
kMEMORY_Local2DMA);
328+
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
329+
MEMORY_ConvertMemoryMapAddress(
330+
(uint32_t)(block_config->dest_address),
331+
kMEMORY_Local2DMA);
332+
#else
333+
334+
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
335+
block_config->source_address;
336+
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
337+
block_config->dest_address;
338+
#endif
339+
EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
340+
block_config->block_size / config->source_data_size;
341+
EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
342+
block_config->block_size / config->source_data_size;
343+
/*Enable auto stop for last transfer.*/
344+
if (block_config->next_block == NULL) {
345+
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) |=
346+
DMA_CSR_DREQ(1U);
347+
} else {
348+
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) &=
349+
~DMA_CSR_DREQ(1U);
350+
}
351+
352+
data->transfer_settings.write_idx =
353+
(data->transfer_settings.write_idx + 1) %
354+
CONFIG_DMA_TCD_QUEUE_SIZE;
355+
data->transfer_settings.empty_tcds--;
356+
block_config = block_config->next_block;
357+
}
358+
359+
if (block_config != NULL && data->transfer_settings.empty_tcds == 0) {
360+
/* User input more blocks than TCD number, return error */
361+
LOG_ERR("Too much request blocks,increase TCD buffer size!");
362+
ret = -ENOBUFS;
363+
}
364+
/* Push the 1st TCD into HW */
365+
EDMA_InstallTCD(p_handle->base, hw_channel,
366+
&DEV_CFG(dev)->tcdpool[channel][0]);
367+
368+
return ret;
369+
}
370+
371+
static int dma_mcux_edma_configure_sg_dynamic(const struct device *dev,
372+
uint32_t channel,
373+
struct dma_config *config,
374+
edma_transfer_type_t transfer_type)
375+
{
376+
edma_handle_t *p_handle = DEV_EDMA_HANDLE(dev, channel);
377+
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
378+
struct dma_block_config *block_config = config->head_block;
379+
int ret = 0;
380+
381+
/* Dynamic Scatter Gather mode */
382+
EDMA_InstallTCDMemory(p_handle, DEV_CFG(dev)->tcdpool[channel],
383+
CONFIG_DMA_TCD_QUEUE_SIZE);
384+
385+
while (block_config != NULL) {
386+
EDMA_PrepareTransfer(&(data->transferConfig),
387+
(void *)block_config->source_address,
388+
config->source_data_size,
389+
(void *)block_config->dest_address,
390+
config->dest_data_size,
391+
config->source_burst_length,
392+
block_config->block_size, transfer_type);
393+
394+
const status_t submit_status =
395+
EDMA_SubmitTransfer(p_handle, &(data->transferConfig));
396+
397+
if (submit_status != kStatus_Success) {
398+
LOG_ERR("Error submitting EDMA Transfer: 0x%x",
399+
submit_status);
400+
ret = -EFAULT;
401+
}
402+
block_config = block_config->next_block;
403+
}
404+
405+
return ret;
406+
}
407+
408+
static int dma_mcux_edma_configure_basic(const struct device *dev,
409+
uint32_t channel,
410+
struct dma_config *config,
411+
edma_transfer_type_t transfer_type)
412+
{
413+
edma_handle_t *p_handle = DEV_EDMA_HANDLE(dev, channel);
414+
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
415+
struct dma_block_config *block_config = config->head_block;
416+
uint32_t hw_channel;
417+
int ret = 0;
418+
419+
/* block_count shall be 1 */
420+
LOG_DBG("block size is: %d", block_config->block_size);
421+
EDMA_PrepareTransfer(&(data->transferConfig),
422+
(void *)block_config->source_address,
423+
config->source_data_size,
424+
(void *)block_config->dest_address,
425+
config->dest_data_size,
426+
config->source_burst_length,
427+
block_config->block_size, transfer_type);
428+
429+
const status_t submit_status = EDMA_SubmitTransfer(p_handle, &(data->transferConfig));
430+
431+
if (submit_status != kStatus_Success) {
432+
LOG_ERR("Error submitting EDMA Transfer: 0x%x", submit_status);
433+
ret = -EFAULT;
434+
}
435+
436+
LOG_DBG("DMA TCD CSR 0x%x", EDMA_HW_TCD_CSR(dev, hw_channel));
437+
438+
return ret;
439+
}
440+
441+
275442
/* Configure a channel */
276443
static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
277444
struct dma_config *config)
@@ -281,15 +448,15 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
281448
return -EINVAL;
282449
}
283450

451+
uint32_t hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
284452
edma_handle_t *p_handle = DEV_EDMA_HANDLE(dev, channel);
285453
struct call_back *data = DEV_CHANNEL_DATA(dev, channel);
286454
struct dma_block_config *block_config = config->head_block;
455+
bool sg_mode = block_config->source_gather_en || block_config->dest_scatter_en;
287456
uint32_t slot = config->dma_slot;
288-
uint32_t hw_channel;
289457
edma_transfer_type_t transfer_type;
290458
unsigned int key;
291459
int ret = 0;
292-
edma_tcd_t *tcd = NULL;
293460

294461
if (slot >= DEV_CFG(dev)->dma_requests) {
295462
LOG_ERR("source number is out of scope %d", slot);
@@ -301,7 +468,6 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
301468
return -EINVAL;
302469
}
303470

304-
hw_channel = dma_mcux_edma_add_channel_gap(dev, channel);
305471
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
306472
uint8_t dmamux_idx, dmamux_channel;
307473

@@ -399,132 +565,12 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel,
399565
sizeof(DEV_CFG(dev)->tcdpool[channel][i]));
400566
}
401567

402-
if (block_config->source_gather_en || block_config->dest_scatter_en) {
403-
if (config->cyclic) {
404-
/* Loop SG mode */
405-
data->transfer_settings.write_idx = 0;
406-
data->transfer_settings.empty_tcds = CONFIG_DMA_TCD_QUEUE_SIZE;
407-
408-
EDMA_PrepareTransfer(
409-
&data->transferConfig, (void *)block_config->source_address,
410-
config->source_data_size, (void *)block_config->dest_address,
411-
config->dest_data_size, config->source_burst_length,
412-
block_config->block_size, transfer_type);
413-
414-
/* Init all TCDs with the para in transfer config and link them. */
415-
for (int i = 0; i < CONFIG_DMA_TCD_QUEUE_SIZE; i++) {
416-
#if defined(CONFIG_DMA_MCUX_EDMA_V5)
417-
EDMA_TcdSetTransferConfigExt(DEV_BASE(dev),
418-
&DEV_CFG(dev)->tcdpool[channel][i], &data->transferConfig,
419-
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
420-
CONFIG_DMA_TCD_QUEUE_SIZE]);
421-
/* Enable Major loop interrupt.*/
422-
EDMA_TcdEnableInterruptsExt(DEV_BASE(dev),
423-
&DEV_CFG(dev)->tcdpool[channel][i],
424-
kEDMA_MajorInterruptEnable);
425-
#else
426-
EDMA_TcdSetTransferConfig(&DEV_CFG(dev)->tcdpool[channel][i],
427-
&data->transferConfig,
428-
&DEV_CFG(dev)->tcdpool[channel][(i + 1) %
429-
CONFIG_DMA_TCD_QUEUE_SIZE]);
430-
EDMA_TcdEnableInterrupts(&DEV_CFG(dev)->tcdpool[channel][i],
431-
kEDMA_MajorInterruptEnable);
432-
#endif
433-
}
434-
435-
/* Load valid transfer parameters */
436-
while (block_config != NULL && data->transfer_settings.empty_tcds > 0) {
437-
tcd = &(DEV_CFG(dev)->tcdpool[channel]
438-
[data->transfer_settings.write_idx]);
439-
440-
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
441-
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
442-
MEMORY_ConvertMemoryMapAddress(
443-
(uint32_t)(block_config->source_address),
444-
kMEMORY_Local2DMA);
445-
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
446-
MEMORY_ConvertMemoryMapAddress(
447-
(uint32_t)(block_config->dest_address),
448-
kMEMORY_Local2DMA);
449-
#else
450-
451-
EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
452-
block_config->source_address;
453-
EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
454-
block_config->dest_address;
455-
#endif
456-
EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
457-
block_config->block_size / config->source_data_size;
458-
EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) =
459-
block_config->block_size / config->source_data_size;
460-
/*Enable auto stop for last transfer.*/
461-
if (block_config->next_block == NULL) {
462-
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) |=
463-
DMA_CSR_DREQ(1U);
464-
} else {
465-
EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE((void *)DEV_BASE(dev))) &=
466-
~DMA_CSR_DREQ(1U);
467-
}
468-
469-
data->transfer_settings.write_idx =
470-
(data->transfer_settings.write_idx + 1) %
471-
CONFIG_DMA_TCD_QUEUE_SIZE;
472-
data->transfer_settings.empty_tcds--;
473-
block_config = block_config->next_block;
474-
}
475-
476-
if (block_config != NULL && data->transfer_settings.empty_tcds == 0) {
477-
/* User input more blocks than TCD number, return error */
478-
LOG_ERR("Too much request blocks,increase TCD buffer size!");
479-
ret = -ENOBUFS;
480-
}
481-
/* Push the 1st TCD into HW */
482-
EDMA_InstallTCD(p_handle->base, hw_channel,
483-
&DEV_CFG(dev)->tcdpool[channel][0]);
484-
485-
} else {
486-
/* Dynamic Scatter Gather mode */
487-
EDMA_InstallTCDMemory(p_handle, DEV_CFG(dev)->tcdpool[channel],
488-
CONFIG_DMA_TCD_QUEUE_SIZE);
489-
490-
while (block_config != NULL) {
491-
EDMA_PrepareTransfer(&(data->transferConfig),
492-
(void *)block_config->source_address,
493-
config->source_data_size,
494-
(void *)block_config->dest_address,
495-
config->dest_data_size,
496-
config->source_burst_length,
497-
block_config->block_size, transfer_type);
498-
499-
const status_t submit_status =
500-
EDMA_SubmitTransfer(p_handle, &(data->transferConfig));
501-
if (submit_status != kStatus_Success) {
502-
LOG_ERR("Error submitting EDMA Transfer: 0x%x",
503-
submit_status);
504-
ret = -EFAULT;
505-
}
506-
block_config = block_config->next_block;
507-
}
508-
}
568+
if (sg_mode && config->cyclic) {
569+
dma_mcux_edma_configure_sg_loop(dev, channel, config, transfer_type);
570+
} else if (sg_mode) {
571+
dma_mcux_edma_configure_sg_dynamic(dev, channel, config, transfer_type);
509572
} else {
510-
/* block_count shall be 1 */
511-
LOG_DBG("block size is: %d", block_config->block_size);
512-
EDMA_PrepareTransfer(&(data->transferConfig),
513-
(void *)block_config->source_address,
514-
config->source_data_size,
515-
(void *)block_config->dest_address,
516-
config->dest_data_size,
517-
config->source_burst_length,
518-
block_config->block_size, transfer_type);
519-
520-
const status_t submit_status =
521-
EDMA_SubmitTransfer(p_handle, &(data->transferConfig));
522-
if (submit_status != kStatus_Success) {
523-
LOG_ERR("Error submitting EDMA Transfer: 0x%x", submit_status);
524-
ret = -EFAULT;
525-
}
526-
527-
LOG_DBG("DMA TCD CSR 0x%x", EDMA_HW_TCD_CSR(dev, hw_channel));
573+
dma_mcux_edma_configure_basic(dev, channel, config, transfer_type);
528574
}
529575

530576
if (config->dest_chaining_en) {

0 commit comments

Comments
 (0)