Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/drivers/dw-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
#define INT_UNMASK_ALL 0xFFFF
#define CHAN_ENABLE(chan) (0x101 << chan)
#define CHAN_DISABLE(chan) (0x100 << chan)
#define CHAN_MASK(chan) (0x1 << chan)

#define DW_CFG_CH_SUSPEND 0x100
#define DW_CFG_CH_FIFO_EMPTY 0x200
Expand Down Expand Up @@ -474,6 +475,31 @@ static int dw_dma_pause(struct dma *dma, int channel)
return 0;
}

#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL
static int dw_dma_stop(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
int ret = 0;
uint32_t flags;
uint32_t val = 0;

spin_lock_irq(&dma->lock, flags);

trace_dma("DDi");

ret = poll_for_register_delay(dma_base(dma) + DW_DMA_CHAN_EN,
CHAN_MASK(channel), val,
PLATFORM_DMA_TIMEOUT);
if (ret < 0)
trace_dma_error("esp");

dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
p->chan[channel].status = COMP_STATE_PREPARE;

spin_unlock_irq(&dma->lock, flags);
return ret;
}
#else
static int dw_dma_stop(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
Expand Down Expand Up @@ -508,6 +534,7 @@ static int dw_dma_stop(struct dma *dma, int channel)
spin_unlock_irq(&dma->lock, flags);
return ret;
}
#endif

/* fill in "status" with current DMA channel state and position */
static int dw_dma_status(struct dma *dma, int channel,
Expand Down
24 changes: 24 additions & 0 deletions src/include/sof/wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <stdint.h>
#include <errno.h>
#include <arch/wait.h>
#include <sof/io.h>
#include <sof/debug.h>
#include <sof/work.h>
#include <sof/timer.h>
Expand Down Expand Up @@ -185,4 +186,27 @@ static inline int poll_for_completion_delay(completion_t *comp, uint64_t us)
return 0;
}

static inline int poll_for_register_delay(uint32_t reg,
uint32_t mask,
uint32_t val, uint64_t us)
{
uint64_t tick = clock_us_to_ticks(CLK_CPU, us);
uint32_t tries = DEFAULT_TRY_TIMES;
uint64_t delta = tick / tries;

if (!delta) {
delta = us;
tries = 1;
}

while ((io_reg_read(reg) & mask) != val) {
if (!tries--) {
trace_error(TRACE_CLASS_WAIT, "ewt");
return -EIO;
}
wait_delay(delta);
}
return 0;
}

#endif