All of lore.kernel.org
 help / color / mirror / Atom feed
* [v3,5/7] dmaengine: dw: Reset DRAIN bit when resume the channel
@ 2019-01-07 11:07 Andy Shevchenko
  0 siblings, 0 replies; only message in thread
From: Andy Shevchenko @ 2019-01-07 11:07 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 8a581d86ea8d..6a23203e601d 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 977aa28bf81d..156088f768f2 100644
--- a/drivers/dma/dw/dw.c
+++ b/drivers/dma/dw/dw.c
@@ -35,6 +35,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)
 {
@@ -91,6 +98,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 8707830f39ad..cd23b9238333 100644
--- a/drivers/dma/dw/idma32.c
+++ b/drivers/dma/dw/idma32.c
@@ -34,12 +34,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)
 {
@@ -117,6 +125,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 66aa8b227248..6cf299facf45 100644
--- a/drivers/dma/dw/regs.h
+++ b/drivers/dma/dw/regs.h
@@ -315,6 +315,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:[~2019-01-07 11:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-07 11:07 [v3,5/7] 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.