@@ -28,11 +28,19 @@ LOG_MODULE_REGISTER(dma_sam_xdmac);
2828#define XDMAC_INT_ERR (XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE)
2929#define DMA_CHANNELS_MAX 31
3030
31+ enum dma_state {
32+ DMA_STATE_INIT = 0 ,
33+ DMA_STATE_CONFIGURED ,
34+ DMA_STATE_RUNNING ,
35+ DMA_STATE_SUSPENDED ,
36+ };
37+
3138/* DMA channel configuration */
3239struct sam_xdmac_channel_cfg {
3340 void * user_data ;
3441 dma_callback_t callback ;
3542 uint32_t data_size ;
43+ enum dma_state state ;
3644};
3745
3846/* Device constant configuration parameters */
@@ -68,6 +76,7 @@ static void sam_xdmac_isr(const struct device *dev)
6876 continue ;
6977 }
7078
79+ dev_data -> dma_channels [channel ].state = DMA_STATE_CONFIGURED ;
7180 channel_cfg = & dev_data -> dma_channels [channel ];
7281
7382 /* Get channel errors */
@@ -180,6 +189,8 @@ int sam_xdmac_transfer_configure(const struct device *dev, uint32_t channel,
180189 /* Set next descriptor configuration */
181190 xdmac -> XDMAC_CHID [channel ].XDMAC_CNDC = param -> ndc ;
182191
192+ dev_data -> dma_channels [channel ].state = DMA_STATE_CONFIGURED ;
193+
183194 return 0 ;
184195}
185196
@@ -199,6 +210,12 @@ static int sam_xdmac_config(const struct device *dev, uint32_t channel,
199210 return - EINVAL ;
200211 }
201212
213+ if (dev_data -> dma_channels [channel ].state != DMA_STATE_INIT &&
214+ dev_data -> dma_channels [channel ].state != DMA_STATE_CONFIGURED ) {
215+ LOG_ERR ("Config Channel %d at invalidate state" , channel );
216+ return - EINVAL ;
217+ }
218+
202219 __ASSERT_NO_MSG (cfg -> source_data_size == cfg -> dest_data_size );
203220 __ASSERT_NO_MSG (cfg -> source_burst_length == cfg -> dest_burst_length );
204221
@@ -327,6 +344,12 @@ int sam_xdmac_transfer_start(const struct device *dev, uint32_t channel)
327344 return - EINVAL ;
328345 }
329346
347+ if (dev_data -> dma_channels [channel ].state != DMA_STATE_CONFIGURED &&
348+ dev_data -> dma_channels [channel ].state != DMA_STATE_RUNNING ) {
349+ LOG_ERR ("Start Channel %d at invalidate state" , channel );
350+ return - EINVAL ;
351+ }
352+
330353 /* Check if the channel is enabled */
331354 if (xdmac -> XDMAC_GS & (XDMAC_GS_ST0 << channel )) {
332355 LOG_DBG ("Channel %d already enabled" , channel );
@@ -338,6 +361,8 @@ int sam_xdmac_transfer_start(const struct device *dev, uint32_t channel)
338361 /* Enable channel */
339362 xdmac -> XDMAC_GE = XDMAC_GE_EN0 << channel ;
340363
364+ dev_data -> dma_channels [channel ].state = DMA_STATE_RUNNING ;
365+
341366 return 0 ;
342367}
343368
@@ -354,6 +379,11 @@ int sam_xdmac_transfer_stop(const struct device *dev, uint32_t channel)
354379 return - EINVAL ;
355380 }
356381
382+ if (dev_data -> dma_channels [channel ].state == DMA_STATE_INIT ) {
383+ LOG_ERR ("Channel %d not configured" , channel );
384+ return - EINVAL ;
385+ }
386+
357387 /* Check if the channel is enabled */
358388 if (!(xdmac -> XDMAC_GS & (XDMAC_GS_ST0 << channel ))) {
359389 return 0 ;
@@ -368,6 +398,8 @@ int sam_xdmac_transfer_stop(const struct device *dev, uint32_t channel)
368398 /* Clear the pending Interrupt Status bit(s) */
369399 (void )xdmac -> XDMAC_CHID [channel ].XDMAC_CIS ;
370400
401+ dev_data -> dma_channels [channel ].state = DMA_STATE_CONFIGURED ;
402+
371403 return 0 ;
372404}
373405
@@ -417,6 +449,16 @@ static int xdmac_suspend(const struct device *dev, uint32_t channel)
417449 return - EINVAL ;
418450 }
419451
452+ switch (dev_data -> dma_channels [channel ].state ) {
453+ case DMA_STATE_RUNNING :
454+ break ;
455+ case DMA_STATE_SUSPENDED :
456+ return 0 ;
457+ default :
458+ LOG_ERR ("Suspend Channel %d at invalidate state" , channel );
459+ return - EINVAL ;
460+ }
461+
420462 if (!(xdmac -> XDMAC_GS & BIT (channel ))) {
421463 LOG_DBG ("Channel %d not enabled" , channel );
422464 return - EINVAL ;
@@ -435,6 +477,8 @@ static int xdmac_suspend(const struct device *dev, uint32_t channel)
435477
436478 xdmac -> XDMAC_GRWS |= BIT (channel );
437479
480+ dev_data -> dma_channels [channel ].state = DMA_STATE_SUSPENDED ;
481+
438482 return 0 ;
439483}
440484
@@ -451,6 +495,16 @@ static int xdmac_resume(const struct device *dev, uint32_t channel)
451495 return - EINVAL ;
452496 }
453497
498+ switch (dev_data -> dma_channels [channel ].state ) {
499+ case DMA_STATE_SUSPENDED :
500+ break ;
501+ case DMA_STATE_RUNNING :
502+ return 0 ;
503+ default :
504+ LOG_ERR ("Resume Channel %d at invalidate state" , channel );
505+ return - EINVAL ;
506+ }
507+
454508 if (!(xdmac -> XDMAC_GS & BIT (channel ))) {
455509 LOG_DBG ("Channel %d not enabled" , channel );
456510 return - EINVAL ;
@@ -469,6 +523,8 @@ static int xdmac_resume(const struct device *dev, uint32_t channel)
469523
470524 xdmac -> XDMAC_GRWR |= BIT (channel );
471525
526+ dev_data -> dma_channels [channel ].state = DMA_STATE_RUNNING ;
527+
472528 return 0 ;
473529}
474530
0 commit comments