Skip to content

Commit b4236c3

Browse files
committed
drivers: dma: sam: support different num of channels for each instance
As the number of DMA channels could be different between DMA instances, get the number from "XDMAC Global Type Register" and validate the channel used. Signed-off-by: Tony Han <tony.han@microchip.com>
1 parent 7611429 commit b4236c3

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

drivers/dma/dma_sam_xdmac.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
LOG_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 */
3232
struct sam_xdmac_channel_cfg {
@@ -45,13 +45,15 @@ struct sam_xdmac_dev_cfg {
4545

4646
/* Device run time data */
4747
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];
4950
};
5051

5152
static 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,
300310
int 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)
325337
int 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)
352367
static 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

Comments
 (0)