* [v1,4/5] dmaengine: dw: Reset DRAIN bit when resume the channel
@ 2018-11-30 20:36 Andy Shevchenko
0 siblings, 0 replies; only message in thread
From: Andy Shevchenko @ 2018-11-30 20:36 UTC (permalink / raw)
To: Viresh Kumar, dmaengine, Vinod Koul; +Cc: Andy Shevchenko
For Intel iDMA 32-bit the channel can be drained on a suspend.
We need to reset the bit on the resume to return a status quo.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/dma/dw/core.c | 10 +++++-----
drivers/dma/dw/dw.c | 8 ++++++++
drivers/dma/dw/idma32.c | 13 +++++++++++--
drivers/dma/dw/regs.h | 1 +
4 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 711f4d19bbf1..092d642bec83 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -846,11 +846,11 @@ static int dwc_pause(struct dma_chan *chan)
return 0;
}
-static inline void dwc_chan_resume(struct dw_dma_chan *dwc)
+static inline void dwc_chan_resume(struct dw_dma_chan *dwc, bool drain)
{
- u32 cfglo = channel_readl(dwc, CFG_LO);
+ struct dw_dma *dw = to_dw_dma(dwc->chan.device);
- channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
+ dw->resume_chan(dwc, drain);
clear_bit(DW_DMA_IS_PAUSED, &dwc->flags);
}
@@ -863,7 +863,7 @@ static int dwc_resume(struct dma_chan *chan)
spin_lock_irqsave(&dwc->lock, flags);
if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags))
- dwc_chan_resume(dwc);
+ dwc_chan_resume(dwc, false);
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -886,7 +886,7 @@ static int dwc_terminate_all(struct dma_chan *chan)
dwc_chan_disable(dw, dwc);
- dwc_chan_resume(dwc);
+ dwc_chan_resume(dwc, true);
/* active_list entries will end up before queued entries */
list_splice_init(&dwc->queue, &list);
diff --git a/drivers/dma/dw/dw.c b/drivers/dma/dw/dw.c
index 998a9eeb561d..92f1e9c7b6f6 100644
--- a/drivers/dma/dw/dw.c
+++ b/drivers/dma/dw/dw.c
@@ -32,6 +32,13 @@ static void dw_dma_suspend_chan(struct dw_dma_chan *dwc, bool drain)
channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
}
+static void dw_dma_resume_chan(struct dw_dma_chan *dwc, bool drain)
+{
+ u32 cfglo = channel_readl(dwc, CFG_LO);
+
+ channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
+}
+
static u32 dw_dma_bytes2block(struct dw_dma_chan *dwc,
size_t bytes, unsigned int width, size_t *len)
{
@@ -88,6 +95,7 @@ int dw_dma_probe(struct dw_dma_chip *chip)
/* Channel operations */
dw->initialize_chan = dw_dma_initialize_chan;
dw->suspend_chan = dw_dma_suspend_chan;
+ dw->resume_chan = dw_dma_resume_chan;
dw->encode_maxburst = dw_dma_encode_maxburst;
dw->bytes2block = dw_dma_bytes2block;
dw->block2bytes = dw_dma_block2bytes;
diff --git a/drivers/dma/dw/idma32.c b/drivers/dma/dw/idma32.c
index d06fb00fb862..7c013b257802 100644
--- a/drivers/dma/dw/idma32.c
+++ b/drivers/dma/dw/idma32.c
@@ -33,12 +33,20 @@ static void idma32_suspend_chan(struct dw_dma_chan *dwc, bool drain)
if (drain)
cfglo |= IDMA32C_CFGL_CH_DRAIN;
- else
- cfglo &= ~IDMA32C_CFGL_CH_DRAIN;
channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
}
+static void idma32_resume_chan(struct dw_dma_chan *dwc, bool drain)
+{
+ u32 cfglo = channel_readl(dwc, CFG_LO);
+
+ if (drain)
+ cfglo &= ~IDMA32C_CFGL_CH_DRAIN;
+
+ channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
+}
+
static u32 idma32_bytes2block(struct dw_dma_chan *dwc,
size_t bytes, unsigned int width, size_t *len)
{
@@ -116,6 +124,7 @@ int idma32_dma_probe(struct dw_dma_chip *chip)
/* Channel operations */
dw->initialize_chan = idma32_initialize_chan;
dw->suspend_chan = idma32_suspend_chan;
+ dw->resume_chan = idma32_resume_chan;
dw->encode_maxburst = idma32_encode_maxburst;
dw->bytes2block = idma32_bytes2block;
dw->block2bytes = idma32_block2bytes;
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h
index 90e46e69c047..bd26c492507b 100644
--- a/drivers/dma/dw/regs.h
+++ b/drivers/dma/dw/regs.h
@@ -311,6 +311,7 @@ struct dw_dma {
/* Channel operations */
void (*initialize_chan)(struct dw_dma_chan *dwc);
void (*suspend_chan)(struct dw_dma_chan *dwc, bool drain);
+ void (*resume_chan)(struct dw_dma_chan *dwc, bool drain);
void (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst);
u32 (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes,
unsigned int width, size_t *len);
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2018-11-30 20:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-30 20:36 [v1,4/5] dmaengine: dw: Reset DRAIN bit when resume the channel Andy Shevchenko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.