aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorNarayanan G <narayanan.gopalakrishnan@stericsson.com>2011-11-30 08:50:42 -0500
committerVinod Koul <vinod.koul@linux.intel.com>2011-12-04 22:46:59 -0500
commit5cd326fd27da347925019fcc041b79bad8dd55ed (patch)
tree31a5a60de3c58367d5f5e538a6d7aa4b56055fa3 /drivers/dma
parent8f0d30f9ee333f4fb3458a9a33f7ead5269ea8f3 (diff)
dmaengine/ste_dma40: allow fixed physical channel
Allow logical channels to specify the physical channel they want to use. This is needed to avoid two peripherals operating on the same physical channel during some special use-cases. (like mmc and usb during a usb mass storage case). Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Narayanan G <narayanan.gopalakrishnan@stericsson.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/ste_dma40.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index aff128a39a4b..972dc35770f9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1545,11 +1545,16 @@ static int d40_validate_conf(struct d40_chan *d40c,
1545 return res; 1545 return res;
1546} 1546}
1547 1547
1548static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src, 1548static bool d40_alloc_mask_set(struct d40_phy_res *phy,
1549 int log_event_line, bool is_log) 1549 bool is_src, int log_event_line, bool is_log,
1550 bool *first_user)
1550{ 1551{
1551 unsigned long flags; 1552 unsigned long flags;
1552 spin_lock_irqsave(&phy->lock, flags); 1553 spin_lock_irqsave(&phy->lock, flags);
1554
1555 *first_user = ((phy->allocated_src | phy->allocated_dst)
1556 == D40_ALLOC_FREE);
1557
1553 if (!is_log) { 1558 if (!is_log) {
1554 /* Physical interrupts are masked per physical full channel */ 1559 /* Physical interrupts are masked per physical full channel */
1555 if (phy->allocated_src == D40_ALLOC_FREE && 1560 if (phy->allocated_src == D40_ALLOC_FREE &&
@@ -1630,7 +1635,7 @@ out:
1630 return is_free; 1635 return is_free;
1631} 1636}
1632 1637
1633static int d40_allocate_channel(struct d40_chan *d40c) 1638static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
1634{ 1639{
1635 int dev_type; 1640 int dev_type;
1636 int event_group; 1641 int event_group;
@@ -1666,7 +1671,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
1666 for (i = 0; i < d40c->base->num_phy_chans; i++) { 1671 for (i = 0; i < d40c->base->num_phy_chans; i++) {
1667 1672
1668 if (d40_alloc_mask_set(&phys[i], is_src, 1673 if (d40_alloc_mask_set(&phys[i], is_src,
1669 0, is_log)) 1674 0, is_log,
1675 first_phy_user))
1670 goto found_phy; 1676 goto found_phy;
1671 } 1677 }
1672 } else 1678 } else
@@ -1676,7 +1682,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
1676 if (d40_alloc_mask_set(&phys[i], 1682 if (d40_alloc_mask_set(&phys[i],
1677 is_src, 1683 is_src,
1678 0, 1684 0,
1679 is_log)) 1685 is_log,
1686 first_phy_user))
1680 goto found_phy; 1687 goto found_phy;
1681 } 1688 }
1682 } 1689 }
@@ -1692,6 +1699,25 @@ found_phy:
1692 /* Find logical channel */ 1699 /* Find logical channel */
1693 for (j = 0; j < d40c->base->num_phy_chans; j += 8) { 1700 for (j = 0; j < d40c->base->num_phy_chans; j += 8) {
1694 int phy_num = j + event_group * 2; 1701 int phy_num = j + event_group * 2;
1702
1703 if (d40c->dma_cfg.use_fixed_channel) {
1704 i = d40c->dma_cfg.phy_channel;
1705
1706 if ((i != phy_num) && (i != phy_num + 1)) {
1707 dev_err(chan2dev(d40c),
1708 "invalid fixed phy channel %d\n", i);
1709 return -EINVAL;
1710 }
1711
1712 if (d40_alloc_mask_set(&phys[i], is_src, event_line,
1713 is_log, first_phy_user))
1714 goto found_log;
1715
1716 dev_err(chan2dev(d40c),
1717 "could not allocate fixed phy channel %d\n", i);
1718 return -EINVAL;
1719 }
1720
1695 /* 1721 /*
1696 * Spread logical channels across all available physical rather 1722 * Spread logical channels across all available physical rather
1697 * than pack every logical channel at the first available phy 1723 * than pack every logical channel at the first available phy
@@ -1700,13 +1726,15 @@ found_phy:
1700 if (is_src) { 1726 if (is_src) {
1701 for (i = phy_num; i < phy_num + 2; i++) { 1727 for (i = phy_num; i < phy_num + 2; i++) {
1702 if (d40_alloc_mask_set(&phys[i], is_src, 1728 if (d40_alloc_mask_set(&phys[i], is_src,
1703 event_line, is_log)) 1729 event_line, is_log,
1730 first_phy_user))
1704 goto found_log; 1731 goto found_log;
1705 } 1732 }
1706 } else { 1733 } else {
1707 for (i = phy_num + 1; i >= phy_num; i--) { 1734 for (i = phy_num + 1; i >= phy_num; i--) {
1708 if (d40_alloc_mask_set(&phys[i], is_src, 1735 if (d40_alloc_mask_set(&phys[i], is_src,
1709 event_line, is_log)) 1736 event_line, is_log,
1737 first_phy_user))
1710 goto found_log; 1738 goto found_log;
1711 } 1739 }
1712 } 1740 }
@@ -2160,9 +2188,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
2160 goto fail; 2188 goto fail;
2161 } 2189 }
2162 } 2190 }
2163 is_free_phy = (d40c->phy_chan == NULL);
2164 2191
2165 err = d40_allocate_channel(d40c); 2192 err = d40_allocate_channel(d40c, &is_free_phy);
2166 if (err) { 2193 if (err) {
2167 chan_err(d40c, "Failed to allocate channel\n"); 2194 chan_err(d40c, "Failed to allocate channel\n");
2168 d40c->configured = false; 2195 d40c->configured = false;
@@ -2189,6 +2216,12 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
2189 D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; 2216 D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
2190 } 2217 }
2191 2218
2219 dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
2220 chan_is_logical(d40c) ? "logical" : "physical",
2221 d40c->phy_chan->num,
2222 d40c->dma_cfg.use_fixed_channel ? ", fixed" : "");
2223
2224
2192 /* 2225 /*
2193 * Only write channel configuration to the DMA if the physical 2226 * Only write channel configuration to the DMA if the physical
2194 * resource is free. In case of multiple logical channels 2227 * resource is free. In case of multiple logical channels