Skip to content

Commit 2ad5a5a

Browse files
committed
dma: nxp: sdma: Introduce SDMA channel states
In order to validate DMA operations introduce channel states. This is done to catch situations where some operations are called in an invalid context. e.g starting a channel before configuring it. Signed-off-by: Daniel Baluta <[email protected]>
1 parent 438ed6d commit 2ad5a5a

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

drivers/dma/dma_nxp_sdma.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ LOG_MODULE_REGISTER(nxp_sdma);
2020
AT_NONCACHEABLE_SECTION_ALIGN(static sdma_context_data_t
2121
sdma_contexts[FSL_FEATURE_SDMA_MODULE_CHANNEL], 4);
2222

23+
enum sdma_channel_state {
24+
SDMA_CHAN_STATE_INIT = 0,
25+
SDMA_CHAN_STATE_CONFIGURED,
26+
SDMA_CHAN_STATE_STARTED,
27+
SDMA_CHAN_STATE_STOPPED,
28+
SDMA_CHAN_STATE_SUSPENDED,
29+
SDMA_CHAN_STATE_RELEASING,
30+
};
31+
2332
struct sdma_dev_cfg {
2433
SDMAARM_Type *base;
2534
void (*irq_config)(void);
@@ -32,6 +41,7 @@ struct sdma_channel_data {
3241
uint32_t direction;
3342
uint32_t index;
3443
const struct device *dev;
44+
enum sdma_channel_state state;
3545
sdma_buffer_descriptor_t *bd_pool; /*pre-allocated list of BD used for transfer */
3646
uint32_t bd_count; /* number of bd */
3747
uint32_t capacity; /* total transfer capacity for this channel */
@@ -281,9 +291,14 @@ static int dma_nxp_sdma_config(const struct device *dev, uint32_t channel,
281291
return -EINVAL;
282292
}
283293

284-
dma_nxp_sdma_channel_init(dev, channel);
285-
286294
chan_data = &dev_data->chan[channel];
295+
296+
if (chan_data->state == SDMA_CHAN_STATE_STARTED) {
297+
LOG_ERR("sdma_config() cannot configure channel while active");
298+
return -EINVAL;
299+
}
300+
301+
dma_nxp_sdma_channel_init(dev, channel);
287302
chan_data->dev = dev;
288303
chan_data->direction = config->channel_direction;
289304

@@ -330,6 +345,7 @@ static int dma_nxp_sdma_config(const struct device *dev, uint32_t channel,
330345
chan_data->transfer_cfg.isEventIgnore = false;
331346
chan_data->transfer_cfg.isSoftTriggerIgnore = false;
332347
SDMA_SubmitTransfer(&chan_data->handle, &chan_data->transfer_cfg);
348+
chan_data->state = SDMA_CHAN_STATE_CONFIGURED;
333349

334350
return 0;
335351
}
@@ -347,8 +363,15 @@ static int dma_nxp_sdma_start(const struct device *dev, uint32_t channel)
347363

348364
chan_data = &dev_data->chan[channel];
349365

366+
if (chan_data->state != SDMA_CHAN_STATE_STOPPED &&
367+
chan_data->state != SDMA_CHAN_STATE_CONFIGURED) {
368+
LOG_ERR("%s: invalid state %d", __func__, chan_data->state);
369+
return -EINVAL;
370+
}
371+
350372
SDMA_SetChannelPriority(dev_cfg->base, channel, DMA_NXP_SDMA_CHAN_DEFAULT_PRIO);
351373
SDMA_StartChannelSoftware(dev_cfg->base, channel);
374+
chan_data->state = SDMA_CHAN_STATE_STARTED;
352375

353376
return 0;
354377
}
@@ -366,6 +389,9 @@ static int dma_nxp_sdma_stop(const struct device *dev, uint32_t channel)
366389
chan_data = &dev_data->chan[channel];
367390

368391
SDMA_StopTransfer(&chan_data->handle);
392+
393+
chan_data->state = SDMA_CHAN_STATE_STOPPED;
394+
369395
return 0;
370396
}
371397

@@ -395,6 +421,12 @@ static int dma_nxp_sdma_reload(const struct device *dev, uint32_t channel, uint3
395421
return 0;
396422
}
397423

424+
/* allow reload only for active channels */
425+
if (chan_data->state != SDMA_CHAN_STATE_STARTED) {
426+
LOG_ERR("%s: invalid state %d", __func__, chan_data->state);
427+
return -EINVAL;
428+
}
429+
398430
if (chan_data->direction == MEMORY_TO_PERIPHERAL) {
399431
dma_nxp_sdma_produce(chan_data, size);
400432
} else {
@@ -439,6 +471,7 @@ static bool sdma_channel_filter(const struct device *dev, int chan_id, void *par
439471
dev_data->chan[chan_id].event_source = *((int *)param);
440472
dev_data->chan[chan_id].index = chan_id;
441473
dev_data->chan[chan_id].capacity = 0;
474+
dev_data->chan[chan_id].state = SDMA_CHAN_STATE_INIT;
442475

443476
return true;
444477
}

0 commit comments

Comments
 (0)