dma: dw_dmac: add dwc_chan_pause and dwc_chan_resume
PATCH v2 1/2 dma: dw_dmac: add dwc_chan_pause and dwc_chan_resume
We will use at least the dwc_chan_resume() later.
Signed-off-by Andy Shevchenko <[email protected]>
Acked-by Viresh Kumar <[email protected]>
--- drivers/dma/dw_dmac.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
drivers/dma/dw_dmac.c +22 -9
@@ -1008,6 +1008,26 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)return 0 ; } +static inline void dwc_chan_pause (struct dw_dma_chan *dwc) +{ +u32 cfglo =channel_readl (dwc,CFG_LO ); + +channel_writel (dwc,CFG_LO , cfglo |DWC_CFGL_CH_SUSP ); +while (!(channel_readl (dwc,CFG_LO ) &DWC_CFGL_FIFO_EMPTY )) +cpu_relax (); + + dwc->paused = true; +} + +static inline void dwc_chan_resume (struct dw_dma_chan *dwc) +{ +u32 cfglo =channel_readl (dwc,CFG_LO ); + +channel_writel (dwc,CFG_LO , cfglo & ~DWC_CFGL_CH_SUSP ); + + dwc->paused = false; +} +static int dwc_control (struct dma_chan *chan,enum dma_ctrl_cmd cmd,unsigned long arg) {
@@ -1015,18 +1035,13 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,struct dw_dma *dw =to_dw_dma (chan->device);struct dw_desc *desc, *_desc;unsigned long flags; -u32 cfglo;LIST_HEAD (list);if (cmd ==DMA_PAUSE ) {spin_lock_irqsave (&dwc->lock, flags); - cfglo =channel_readl (dwc,CFG_LO ); -channel_writel (dwc,CFG_LO , cfglo |DWC_CFGL_CH_SUSP ); -while (!(channel_readl (dwc,CFG_LO ) &DWC_CFGL_FIFO_EMPTY )) -cpu_relax (); +dwc_chan_pause (dwc); - dwc->paused = true;spin_unlock_irqrestore (&dwc->lock, flags); }else if (cmd ==DMA_RESUME ) {if (!dwc->paused)
@@ -1034,9 +1049,7 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,spin_lock_irqsave (&dwc->lock, flags); - cfglo =channel_readl (dwc,CFG_LO ); -channel_writel (dwc,CFG_LO , cfglo & ~DWC_CFGL_CH_SUSP ); - dwc->paused = false; +dwc_chan_resume (dwc);spin_unlock_irqrestore (&dwc->lock, flags); }else if (cmd ==DMA_TERMINATE_ALL ) {
Signature · 1 line
1.7.10.4
PATCH v2 2/2 dma: dw_dmac: clear suspend bit during termination
From: Heikki Krogerus <[email protected]>
The DMA transfer could not be established if previously it was paused and terminated. In that case the channel's suspend bit remains set that prevents to transfer anything until channel is resumed.
The patch adds a code that clears the DWC_CFGL_CH_SUSP bit during termination.
Signed-off-by Heikki Krogerus <[email protected]>
Signed-off-by Andy Shevchenko <[email protected]>
Acked-by Viresh Kumar <[email protected]>
--- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/dw_dmac.c +1 -1
@@ -1059,7 +1059,7 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,dwc_chan_disable (dw, dwc); - dwc->paused = false; +dwc_chan_resume (dwc);/* active_list entries will end up before queued entries */ list_splice_init (&dwc->queue, &list);
Signature · 1 line
1.7.10.4