26
26
LOG_MODULE_REGISTER (dma_sam_xdmac );
27
27
28
28
#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
30
30
31
31
/* DMA channel configuration */
32
32
struct sam_xdmac_channel_cfg {
@@ -45,13 +45,15 @@ struct sam_xdmac_dev_cfg {
45
45
46
46
/* Device run time data */
47
47
struct 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 ];
49
50
};
50
51
51
52
static void sam_xdmac_isr (const struct device * dev )
52
53
{
53
54
const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
54
55
struct sam_xdmac_dev_data * const dev_data = dev -> data ;
56
+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
55
57
56
58
Xdmac * const xdmac = dev_cfg -> regs ;
57
59
struct sam_xdmac_channel_cfg * channel_cfg ;
@@ -61,7 +63,7 @@ static void sam_xdmac_isr(const struct device *dev)
61
63
/* Get global interrupt status */
62
64
isr_status = xdmac -> XDMAC_GIS ;
63
65
64
- for (int channel = 0 ; channel < DMA_CHANNELS_NO ; channel ++ ) {
66
+ for (int channel = 0 ; channel < channel_num ; channel ++ ) {
65
67
if (!(isr_status & (1 << channel ))) {
66
68
continue ;
67
69
}
@@ -83,10 +85,13 @@ int sam_xdmac_channel_configure(const struct device *dev, uint32_t channel,
83
85
struct sam_xdmac_channel_config * param )
84
86
{
85
87
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 ;
86
90
87
91
Xdmac * const xdmac = dev_cfg -> regs ;
88
92
89
- if (channel >= DMA_CHANNELS_NO ) {
93
+ if (channel >= channel_num ) {
94
+ LOG_ERR ("Channel %d out of range" , channel );
90
95
return - EINVAL ;
91
96
}
92
97
@@ -126,10 +131,13 @@ int sam_xdmac_transfer_configure(const struct device *dev, uint32_t channel,
126
131
struct sam_xdmac_transfer_config * param )
127
132
{
128
133
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 ;
129
136
130
137
Xdmac * const xdmac = dev_cfg -> regs ;
131
138
132
- if (channel >= DMA_CHANNELS_NO ) {
139
+ if (channel >= channel_num ) {
140
+ LOG_ERR ("Channel %d out of range" , channel );
133
141
return - EINVAL ;
134
142
}
135
143
@@ -179,13 +187,15 @@ static int sam_xdmac_config(const struct device *dev, uint32_t channel,
179
187
struct dma_config * cfg )
180
188
{
181
189
struct sam_xdmac_dev_data * const dev_data = dev -> data ;
190
+ uint32_t channel_num = dev_data -> dma_ctx .dma_channels ;
182
191
struct sam_xdmac_channel_config channel_cfg ;
183
192
struct sam_xdmac_transfer_config transfer_cfg ;
184
193
uint32_t burst_size ;
185
194
uint32_t data_size ;
186
195
int ret ;
187
196
188
- if (channel >= DMA_CHANNELS_NO ) {
197
+ if (channel >= channel_num ) {
198
+ LOG_ERR ("Channel %d out of range" , channel );
189
199
return - EINVAL ;
190
200
}
191
201
@@ -300,11 +310,13 @@ static int sam_xdmac_transfer_reload(const struct device *dev, uint32_t channel,
300
310
int sam_xdmac_transfer_start (const struct device * dev , uint32_t channel )
301
311
{
302
312
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 ;
303
315
304
316
Xdmac * const xdmac = config -> regs ;
305
317
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 );
308
320
return - EINVAL ;
309
321
}
310
322
@@ -325,10 +337,13 @@ int sam_xdmac_transfer_start(const struct device *dev, uint32_t channel)
325
337
int sam_xdmac_transfer_stop (const struct device * dev , uint32_t channel )
326
338
{
327
339
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 ;
328
342
329
343
Xdmac * const xdmac = config -> regs ;
330
344
331
- if (channel >= DMA_CHANNELS_NO ) {
345
+ if (channel >= channel_num ) {
346
+ LOG_ERR ("Channel %d out of range" , channel );
332
347
return - EINVAL ;
333
348
}
334
349
@@ -352,9 +367,16 @@ int sam_xdmac_transfer_stop(const struct device *dev, uint32_t channel)
352
367
static int sam_xdmac_initialize (const struct device * dev )
353
368
{
354
369
const struct sam_xdmac_dev_cfg * const dev_cfg = dev -> config ;
370
+ struct sam_xdmac_dev_data * const dev_data = dev -> data ;
355
371
356
372
Xdmac * const xdmac = dev_cfg -> regs ;
357
373
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
+
358
380
/* Configure interrupts */
359
381
dev_cfg -> irq_config ();
360
382
@@ -421,7 +443,12 @@ static DEVICE_API(dma, sam_xdmac_driver_api) = {
421
443
.irq_id = DT_INST_IRQN(n), \
422
444
}; \
423
445
\
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
+ }; \
425
452
\
426
453
DEVICE_DT_INST_DEFINE(n, &sam_xdmac_initialize, NULL, \
427
454
&dma##n##_data, &dma##n##_config, POST_KERNEL, \
0 commit comments