Skip to content

Commit 9f158bf

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 9f158bf

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,13 @@ 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_PREPARED,
26+
SDMA_CHAN_STATE_ACTIVE,
27+
SDMA_CHAN_STATE_READY,
28+
};
29+
2330
struct sdma_dev_cfg {
2431
SDMAARM_Type *base;
2532
void (*irq_config)(void);
@@ -32,6 +39,7 @@ struct sdma_channel_data {
3239
uint32_t direction;
3340
uint32_t index;
3441
const struct device *dev;
42+
enum sdma_channel_state state;
3543
sdma_buffer_descriptor_t *bd_pool; /*pre-allocated list of BD used for transfer */
3644
uint32_t bd_count; /* number of bd */
3745
uint32_t capacity; /* total transfer capacity for this channel */
@@ -281,9 +289,14 @@ static int dma_nxp_sdma_config(const struct device *dev, uint32_t channel,
281289
return -EINVAL;
282290
}
283291

284-
dma_nxp_sdma_channel_init(dev, channel);
285-
286292
chan_data = &dev_data->chan[channel];
293+
294+
if (chan_data->state == SDMA_CHAN_STATE_ACTIVE) {
295+
LOG_ERR("sdma_config() cannot configure channel while active");
296+
return -EINVAL;
297+
}
298+
299+
dma_nxp_sdma_channel_init(dev, channel);
287300
chan_data->dev = dev;
288301
chan_data->direction = config->channel_direction;
289302

@@ -330,6 +343,7 @@ static int dma_nxp_sdma_config(const struct device *dev, uint32_t channel,
330343
chan_data->transfer_cfg.isEventIgnore = false;
331344
chan_data->transfer_cfg.isSoftTriggerIgnore = false;
332345
SDMA_SubmitTransfer(&chan_data->handle, &chan_data->transfer_cfg);
346+
chan_data->state = SDMA_CHAN_STATE_PREPARED;
333347

334348
return 0;
335349
}
@@ -347,8 +361,16 @@ static int dma_nxp_sdma_start(const struct device *dev, uint32_t channel)
347361

348362
chan_data = &dev_data->chan[channel];
349363

364+
if (chan_data->state != SDMA_CHAN_STATE_READY &&
365+
chan_data->state != SDMA_CHAN_STATE_PREPARED) {
366+
LOG_ERR("%s: invalid state %d", __func__, chan_data->state);
367+
return -EINVAL;
368+
}
369+
370+
350371
SDMA_SetChannelPriority(dev_cfg->base, channel, DMA_NXP_SDMA_CHAN_DEFAULT_PRIO);
351372
SDMA_StartChannelSoftware(dev_cfg->base, channel);
373+
chan_data->state = SDMA_CHAN_STATE_ACTIVE;
352374

353375
return 0;
354376
}
@@ -366,6 +388,10 @@ static int dma_nxp_sdma_stop(const struct device *dev, uint32_t channel)
366388
chan_data = &dev_data->chan[channel];
367389

368390
SDMA_StopTransfer(&chan_data->handle);
391+
392+
/* channel is ready, but not active anymore */
393+
chan_data->state = SDMA_CHAN_STATE_READY;
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_ACTIVE) {
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)