Skip to content

Commit

Permalink
dma: dma_nxp_edma: make sure channel is inactive when releasing
Browse files Browse the repository at this point in the history
Make sure that channels are inactive before releasing them.
This way, there won't be any leftover interrupts needed to be
handled when disabling IRQs.

This patch introduces a new state: CHAN_STATE_RELEASING. This is mostly
useful for the per-channel PD support in which the ISR needs to check
that the channel PD is enabled before attempting to access its register
space.

Signed-off-by: Laurentiu Mihalcea <[email protected]>
  • Loading branch information
LaurentiuM1234 committed Dec 2, 2024
1 parent 6b23ea7 commit 01390c3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
29 changes: 28 additions & 1 deletion drivers/dma/dma_nxp_edma.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "dma_nxp_edma.h"

#define EDMA_ACTIVE_TIMEOUT 50

/* TODO list:
* 1) Support for requesting a specific channel.
* 2) Support for checking if DMA transfer is pending when attempting config. (?)
Expand Down Expand Up @@ -600,14 +602,39 @@ static bool edma_channel_filter(const struct device *dev, int chan_id, void *par

static void edma_channel_release(const struct device *dev, uint32_t chan_id)
{
struct edma_channel *chan = lookup_channel(dev, chan_id);
struct edma_channel *chan;
struct edma_data *data;

chan = lookup_channel(dev, chan_id);
if (!chan) {
return;
}

data = dev->data;

if (!channel_allows_transition(chan, CHAN_STATE_RELEASING)) {
LOG_ERR("chan %d transition from %d to RELEASING not allowed",
chan_id, chan->state);
return;
}

/* channel needs to be INACTIVE before transitioning */
if (!WAIT_FOR(!EDMA_CHAN_IS_ACTIVE(data, chan),
EDMA_ACTIVE_TIMEOUT, k_busy_wait(1))) {
LOG_ERR("timed out while waiting for chan %d to become inactive",
chan->id);
return;
}

/* start the process of disabling IRQ */
chan->state = CHAN_STATE_RELEASING;

#ifdef CONFIG_NXP_IRQSTEER
irq_disable(chan->irq);
#endif /* CONFIG_NXP_IRQSTEER */

/* done, proceed with next state */
chan->state = CHAN_STATE_INIT;
}

static const struct dma_driver_api edma_api = {
Expand Down
11 changes: 9 additions & 2 deletions drivers/dma/dma_nxp_edma.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ LOG_MODULE_REGISTER(nxp_edma);
edma_chan_cyclic_produce(chan, size) :\
edma_chan_cyclic_consume(chan, size))

#define EDMA_CHAN_IS_ACTIVE(data, chan)\
(EDMA_ChannelRegRead((data)->hal_cfg, (chan)->id, EDMA_TCD_CH_CSR) &\
EDMA_TCD_CH_CSR_ACTIVE_MASK)

enum channel_type {
CHAN_TYPE_CONSUMER = 0,
CHAN_TYPE_PRODUCER,
Expand All @@ -171,6 +175,7 @@ enum channel_state {
CHAN_STATE_STARTED,
CHAN_STATE_STOPPED,
CHAN_STATE_SUSPENDED,
CHAN_STATE_RELEASING,
};

struct edma_channel {
Expand Down Expand Up @@ -235,7 +240,8 @@ static inline bool channel_allows_transition(struct edma_channel *chan,
break;
case CHAN_STATE_CONFIGURED:
if (next != CHAN_STATE_STARTED &&
next != CHAN_STATE_CONFIGURED) {
next != CHAN_STATE_CONFIGURED &&
next != CHAN_STATE_RELEASING) {
return false;
}
break;
Expand All @@ -246,7 +252,8 @@ static inline bool channel_allows_transition(struct edma_channel *chan,
}
break;
case CHAN_STATE_STOPPED:
if (next != CHAN_STATE_CONFIGURED) {
if (next != CHAN_STATE_CONFIGURED &&
next != CHAN_STATE_RELEASING) {
return false;
}
break;
Expand Down

0 comments on commit 01390c3

Please sign in to comment.