aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Song <Baohua.Song@csr.com>2012-12-14 05:59:22 -0500
committerVinod Koul <vinod.koul@intel.com>2013-01-28 04:44:40 -0500
commit2518d1d1fc0ba7ef781bac97132bcfd6d7466c4b (patch)
tree7c38d76cbf4f92fc81dea18073f66f53027ce946
parent6c5e6a3990ce64192b56ffafa5ffa5af129751d5 (diff)
DMAEngine: sirf: add DMA pause/resume support
pause/resume are important for users like ALSA sound drivers, this patches make the sirf prima2/marco support DMA commands DMA_PAUSE and DMA_RESUME. Signed-off-by: Barry Song <Baohua.Song@csr.com> Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/sirf-dma.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 3c210ba9f938..7d78cf7bb7f1 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -313,6 +313,48 @@ static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan)
313 return 0; 313 return 0;
314} 314}
315 315
316static int sirfsoc_dma_pause_chan(struct sirfsoc_dma_chan *schan)
317{
318 struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
319 int cid = schan->chan.chan_id;
320 unsigned long flags;
321
322 spin_lock_irqsave(&schan->lock, flags);
323
324 if (!sdma->is_marco)
325 writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
326 & ~((1 << cid) | 1 << (cid + 16)),
327 sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
328 else
329 writel_relaxed((1 << cid) | 1 << (cid + 16),
330 sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
331
332 spin_unlock_irqrestore(&schan->lock, flags);
333
334 return 0;
335}
336
337static int sirfsoc_dma_resume_chan(struct sirfsoc_dma_chan *schan)
338{
339 struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
340 int cid = schan->chan.chan_id;
341 unsigned long flags;
342
343 spin_lock_irqsave(&schan->lock, flags);
344
345 if (!sdma->is_marco)
346 writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
347 | ((1 << cid) | 1 << (cid + 16)),
348 sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
349 else
350 writel_relaxed((1 << cid) | 1 << (cid + 16),
351 sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
352
353 spin_unlock_irqrestore(&schan->lock, flags);
354
355 return 0;
356}
357
316static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 358static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
317 unsigned long arg) 359 unsigned long arg)
318{ 360{
@@ -320,6 +362,10 @@ static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
320 struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); 362 struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
321 363
322 switch (cmd) { 364 switch (cmd) {
365 case DMA_PAUSE:
366 return sirfsoc_dma_pause_chan(schan);
367 case DMA_RESUME:
368 return sirfsoc_dma_resume_chan(schan);
323 case DMA_TERMINATE_ALL: 369 case DMA_TERMINATE_ALL:
324 return sirfsoc_dma_terminate_all(schan); 370 return sirfsoc_dma_terminate_all(schan);
325 case DMA_SLAVE_CONFIG: 371 case DMA_SLAVE_CONFIG: