aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2010-05-17 18:41:09 -0400
committerDan Williams <dan.j.williams@intel.com>2010-05-17 18:45:03 -0400
commita5ebca4769f28ceade28ff59fcbffb8e184e599c (patch)
treecc951614a700e0139d8d786a854eb74c2a05075d /drivers/dma
parent8381fc35244dbdf58cfc49e04e0d7c3498c8aa03 (diff)
DMAENGINE: DMA40 support paused channel status
Support determining whether a channel is paused or not using the status function. Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/ste_dma40.c75
1 files changed, 67 insertions, 8 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index e4295a27672b..16a7d2b605ed 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -659,7 +659,7 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
659 spin_unlock_irqrestore(&d40c->phy_chan->lock, flags); 659 spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
660} 660}
661 661
662static bool d40_chan_has_events(struct d40_chan *d40c) 662static u32 d40_chan_has_events(struct d40_chan *d40c)
663{ 663{
664 u32 val = 0; 664 u32 val = 0;
665 665
@@ -674,7 +674,7 @@ static bool d40_chan_has_events(struct d40_chan *d40c)
674 val = readl(d40c->base->virtbase + D40_DREG_PCBASE + 674 val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
675 d40c->phy_chan->num * D40_DREG_PCDELTA + 675 d40c->phy_chan->num * D40_DREG_PCDELTA +
676 D40_CHAN_REG_SDLNK); 676 D40_CHAN_REG_SDLNK);
677 return (bool) val; 677 return val;
678} 678}
679 679
680static void d40_config_enable_lidx(struct d40_chan *d40c) 680static void d40_config_enable_lidx(struct d40_chan *d40c)
@@ -1389,6 +1389,65 @@ static int d40_pause(struct dma_chan *chan)
1389 return res; 1389 return res;
1390} 1390}
1391 1391
1392static bool d40_is_paused(struct d40_chan *d40c)
1393{
1394 bool is_paused = false;
1395 unsigned long flags;
1396 void __iomem *active_reg;
1397 u32 status;
1398 u32 event;
1399 int res;
1400
1401 spin_lock_irqsave(&d40c->lock, flags);
1402
1403 if (d40c->log_num == D40_PHY_CHAN) {
1404 if (d40c->phy_chan->num % 2 == 0)
1405 active_reg = d40c->base->virtbase + D40_DREG_ACTIVE;
1406 else
1407 active_reg = d40c->base->virtbase + D40_DREG_ACTIVO;
1408
1409 status = (readl(active_reg) &
1410 D40_CHAN_POS_MASK(d40c->phy_chan->num)) >>
1411 D40_CHAN_POS(d40c->phy_chan->num);
1412 if (status == D40_DMA_SUSPENDED || status == D40_DMA_STOP)
1413 is_paused = true;
1414
1415 goto _exit;
1416 }
1417
1418 res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
1419 if (res != 0)
1420 goto _exit;
1421
1422 if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
1423 d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM)
1424 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
1425 else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)
1426 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
1427 else {
1428 dev_err(&d40c->chan.dev->device,
1429 "[%s] Unknown direction\n", __func__);
1430 goto _exit;
1431 }
1432 status = d40_chan_has_events(d40c);
1433 status = (status & D40_EVENTLINE_MASK(event)) >>
1434 D40_EVENTLINE_POS(event);
1435
1436 if (status != D40_DMA_RUN)
1437 is_paused = true;
1438
1439 /* Resume the other logical channels if any */
1440 if (d40_chan_has_events(d40c))
1441 res = d40_channel_execute_command(d40c,
1442 D40_DMA_RUN);
1443
1444_exit:
1445 spin_unlock_irqrestore(&d40c->lock, flags);
1446 return is_paused;
1447
1448}
1449
1450
1392static bool d40_tx_is_linked(struct d40_chan *d40c) 1451static bool d40_tx_is_linked(struct d40_chan *d40c)
1393{ 1452{
1394 bool is_link; 1453 bool is_link;
@@ -1980,13 +2039,13 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
1980 last_complete = d40c->completed; 2039 last_complete = d40c->completed;
1981 last_used = chan->cookie; 2040 last_used = chan->cookie;
1982 2041
1983 ret = dma_async_is_complete(cookie, last_complete, last_used); 2042 if (d40_is_paused(d40c))
2043 ret = DMA_PAUSED;
2044 else
2045 ret = dma_async_is_complete(cookie, last_complete, last_used);
1984 2046
1985 if (txstate) { 2047 dma_set_tx_state(txstate, last_complete, last_used,
1986 txstate->last = last_complete; 2048 stedma40_residue(chan));
1987 txstate->used = last_used;
1988 txstate->residue = stedma40_residue(chan);
1989 }
1990 2049
1991 return ret; 2050 return ret;
1992} 2051}