diff options
author | Narayanan G <narayanan.gopalakrishnan@stericsson.com> | 2011-11-30 08:50:42 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2011-12-04 22:46:59 -0500 |
commit | 5cd326fd27da347925019fcc041b79bad8dd55ed (patch) | |
tree | 31a5a60de3c58367d5f5e538a6d7aa4b56055fa3 | |
parent | 8f0d30f9ee333f4fb3458a9a33f7ead5269ea8f3 (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>
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ste_dma40.h | 6 | ||||
-rw-r--r-- | drivers/dma/ste_dma40.c | 51 |
2 files changed, 47 insertions, 10 deletions
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 3177bed253df..fd0ee84c45d1 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h | |||
@@ -113,7 +113,8 @@ struct stedma40_half_channel_info { | |||
113 | * @dst_dev_type: Dst device type | 113 | * @dst_dev_type: Dst device type |
114 | * @src_info: Parameters for dst half channel | 114 | * @src_info: Parameters for dst half channel |
115 | * @dst_info: Parameters for dst half channel | 115 | * @dst_info: Parameters for dst half channel |
116 | * | 116 | * @use_fixed_channel: if true, use physical channel specified by phy_channel |
117 | * @phy_channel: physical channel to use, only if use_fixed_channel is true | ||
117 | * | 118 | * |
118 | * This structure has to be filled by the client drivers. | 119 | * This structure has to be filled by the client drivers. |
119 | * It is recommended to do all dma configurations for clients in the machine. | 120 | * It is recommended to do all dma configurations for clients in the machine. |
@@ -129,6 +130,9 @@ struct stedma40_chan_cfg { | |||
129 | int dst_dev_type; | 130 | int dst_dev_type; |
130 | struct stedma40_half_channel_info src_info; | 131 | struct stedma40_half_channel_info src_info; |
131 | struct stedma40_half_channel_info dst_info; | 132 | struct stedma40_half_channel_info dst_info; |
133 | |||
134 | bool use_fixed_channel; | ||
135 | int phy_channel; | ||
132 | }; | 136 | }; |
133 | 137 | ||
134 | /** | 138 | /** |
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 | ||
1548 | static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src, | 1548 | static 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 | ||
1633 | static int d40_allocate_channel(struct d40_chan *d40c) | 1638 | static 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 |