2626LOG_MODULE_REGISTER (dma_sam_xdmac );
2727
2828#define XDMAC_INT_ERR (XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE)
29- #define DMA_CHANNELS_NO XDMACCHID_NUMBER
29+ #define DMA_CHANNELS_MAX 31
3030
3131/* DMA channel configuration */
3232struct sam_xdmac_channel_cfg {
@@ -45,13 +45,15 @@ struct sam_xdmac_dev_cfg {
4545
4646/* Device run time data */
4747struct sam_xdmac_dev_data {
48- struct sam_xdmac_channel_cfg dma_channels [DMA_CHANNELS_NO ];
48+ struct dma_context dma_ctx ;
49+ struct sam_xdmac_channel_cfg dma_channels [DMA_CHANNELS_MAX + 1 ];
4950};
5051
5152static void sam_xdmac_isr (const struct device * dev )
5253{
5354 const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
5455 struct sam_xdmac_dev_data * const dev_data = dev -> data ;
56+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
5557
5658 Xdmac * const xdmac = dev_cfg -> regs ;
5759 struct sam_xdmac_channel_cfg * channel_cfg ;
@@ -61,7 +63,7 @@ static void sam_xdmac_isr(const struct device *dev)
6163 /* Get global interrupt status */
6264 isr_status = xdmac -> XDMAC_GIS ;
6365
64- for (int channel = 0 ; channel < DMA_CHANNELS_NO ; channel ++ ) {
66+ for (int channel = 0 ; channel < channel_num ; channel ++ ) {
6567 if (!(isr_status & (1 << channel ))) {
6668 continue ;
6769 }
@@ -83,10 +85,13 @@ int sam_xdmac_channel_configure(const struct device *dev, uint32_t channel,
8385 struct sam_xdmac_channel_config * param )
8486{
8587 const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
88+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
89+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
8690
8791 Xdmac * const xdmac = dev_cfg -> regs ;
8892
89- if (channel >= DMA_CHANNELS_NO ) {
93+ if (channel >= channel_num ) {
94+ LOG_ERR ("Channel %d out of range" , channel );
9095 return - EINVAL ;
9196 }
9297
@@ -126,10 +131,13 @@ int sam_xdmac_transfer_configure(const struct device *dev, uint32_t channel,
126131 struct sam_xdmac_transfer_config * param )
127132{
128133 const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
134+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
135+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
129136
130137 Xdmac * const xdmac = dev_cfg -> regs ;
131138
132- if (channel >= DMA_CHANNELS_NO ) {
139+ if (channel >= channel_num ) {
140+ LOG_ERR ("Channel %d out of range" , channel );
133141 return - EINVAL ;
134142 }
135143
@@ -179,13 +187,15 @@ static int sam_xdmac_config(const struct device *dev, uint32_t channel,
179187 struct dma_config * cfg )
180188{
181189 struct sam_xdmac_dev_data * const dev_data = dev -> data ;
190+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
182191 struct sam_xdmac_channel_config channel_cfg ;
183192 struct sam_xdmac_transfer_config transfer_cfg ;
184193 uint32_t burst_size ;
185194 uint32_t data_size ;
186195 int ret ;
187196
188- if (channel >= DMA_CHANNELS_NO ) {
197+ if (channel >= channel_num ) {
198+ LOG_ERR ("Channel %d out of range" , channel );
189199 return - EINVAL ;
190200 }
191201
@@ -300,11 +310,13 @@ static int sam_xdmac_transfer_reload(const struct device *dev, uint32_t channel,
300310int sam_xdmac_transfer_start (const struct device * dev , uint32_t channel )
301311{
302312 const struct sam_xdmac_dev_cfg * config = dev -> config ;
313+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
314+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
303315
304316 Xdmac * const xdmac = config -> regs ;
305317
306- if (channel >= DMA_CHANNELS_NO ) {
307- LOG_DBG ("Channel %d out of range" , channel );
318+ if (channel >= channel_num ) {
319+ LOG_ERR ("Channel %d out of range" , channel );
308320 return - EINVAL ;
309321 }
310322
@@ -325,10 +337,13 @@ int sam_xdmac_transfer_start(const struct device *dev, uint32_t channel)
325337int sam_xdmac_transfer_stop (const struct device * dev , uint32_t channel )
326338{
327339 const struct sam_xdmac_dev_cfg * config = dev -> config ;
340+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
341+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
328342
329343 Xdmac * const xdmac = config -> regs ;
330344
331- if (channel >= DMA_CHANNELS_NO ) {
345+ if (channel >= channel_num ) {
346+ LOG_ERR ("Channel %d out of range" , channel );
332347 return - EINVAL ;
333348 }
334349
@@ -352,9 +367,16 @@ int sam_xdmac_transfer_stop(const struct device *dev, uint32_t channel)
352367static int sam_xdmac_initialize (const struct device * dev )
353368{
354369 const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
370+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
355371
356372 Xdmac * const xdmac = dev_cfg -> regs ;
357373
374+ dev_data -> dma_ctx .dma_channels = FIELD_GET (XDMAC_GTYPE_NB_CH_Msk , xdmac -> XDMAC_GTYPE ) + 1 ;
375+ if (dev_data -> dma_ctx .dma_channels > DMA_CHANNELS_MAX + 1 ) {
376+ LOG_ERR ("Maximum supported channels is %d" , DMA_CHANNELS_MAX + 1 );
377+ return - EINVAL ;
378+ }
379+
358380 /* Configure interrupts */
359381 dev_cfg -> irq_config ();
360382
@@ -421,7 +443,12 @@ static DEVICE_API(dma, sam_xdmac_driver_api) = {
421443 .irq_id = DT_INST_IRQN(n), \
422444 }; \
423445 \
424- static struct sam_xdmac_dev_data dma##n##_data; \
446+ static ATOMIC_DEFINE(dma_channels_atomic_##n, DMA_CHANNELS_MAX); \
447+ \
448+ static struct sam_xdmac_dev_data dma##n##_data = { \
449+ .dma_ctx.magic = DMA_MAGIC, \
450+ .dma_ctx.atomic = dma_channels_atomic_##n, \
451+ }; \
425452 \
426453 DEVICE_DT_INST_DEFINE(n, &sam_xdmac_initialize, NULL, \
427454 &dma##n##_data, &dma##n##_config, POST_KERNEL, \
0 commit comments