diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-14 19:53:54 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-14 19:53:54 -0400 |
commit | 2c3165ebb641e0ff3faf1c87ed1c8fbd85871da0 (patch) | |
tree | ecf0bef4ee0b56029d0f08aed941aca78da99424 /drivers/dma/ste_dma40.c | |
parent | 0d86331b4cc9b0c52d41bbe78cb4b75f40b7381c (diff) | |
parent | 499c2bc3cc89dcbbf08aa526cd4a984b92a4d2a8 (diff) |
Merge tag 'ux500-dma40-for-arm-soc-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into next/drivers
From Linus Walleij:
Second set of DMA40 changes: refactorings and device tree
support for the DMA40. Now with MUSB and some platform
data removal.
* tag 'ux500-dma40-for-arm-soc-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson:
dmaengine: ste_dma40: Fetch disabled channels from DT
dmaengine: ste_dma40: Fetch the number of physical channels from DT
ARM: ux500: Stop passing DMA platform data though AUXDATA
dmaengine: ste_dma40: Allow memcpy channels to be configured from DT
dmaengine: ste_dma40_ll: Replace meaningless register set with comment
dmaengine: ste_dma40: Convert data_width from register bit format to value
dmaengine: ste_dma40_ll: Use the BIT macro to replace ugly '(1 << x)'s
ARM: ux500: Remove recently unused stedma40_xfer_dir enums
dmaengine: ste_dma40: Replace ST-E's home-brew DMA direction defs with generic ones
ARM: ux500: Replace ST-E's home-brew DMA direction definition with the generic one
dmaengine: ste_dma40: Use the BIT macro to replace ugly '(1 << x)'s
ARM: ux500: Remove empty function u8500_of_init_devices()
ARM: ux500: Remove ux500-musb platform registation when booting with DT
usb: musb: ux500: add device tree probing support
usb: musb: ux500: attempt to find channels by name before using pdata
usb: musb: ux500: harden checks for platform data
usb: musb: ux500: take the dma_mask from coherent_dma_mask
usb: musb: ux500: move the MUSB HDRC configuration into the driver
usb: musb: ux500: move channel number knowledge into the driver
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r-- | drivers/dma/ste_dma40.c | 199 |
1 files changed, 115 insertions, 84 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 7f23d45166c3..fa4f9a33a74d 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -54,10 +54,12 @@ | |||
54 | #define MAX_LCLA_ALLOC_ATTEMPTS 256 | 54 | #define MAX_LCLA_ALLOC_ATTEMPTS 256 |
55 | 55 | ||
56 | /* Bit markings for allocation map */ | 56 | /* Bit markings for allocation map */ |
57 | #define D40_ALLOC_FREE (1 << 31) | 57 | #define D40_ALLOC_FREE BIT(31) |
58 | #define D40_ALLOC_PHY (1 << 30) | 58 | #define D40_ALLOC_PHY BIT(30) |
59 | #define D40_ALLOC_LOG_FREE 0 | 59 | #define D40_ALLOC_LOG_FREE 0 |
60 | 60 | ||
61 | #define D40_MEMCPY_MAX_CHANS 8 | ||
62 | |||
61 | /* Reserved event lines for memcpy only. */ | 63 | /* Reserved event lines for memcpy only. */ |
62 | #define DB8500_DMA_MEMCPY_EV_0 51 | 64 | #define DB8500_DMA_MEMCPY_EV_0 51 |
63 | #define DB8500_DMA_MEMCPY_EV_1 56 | 65 | #define DB8500_DMA_MEMCPY_EV_1 56 |
@@ -78,13 +80,13 @@ static int dma40_memcpy_channels[] = { | |||
78 | /* Default configuration for physcial memcpy */ | 80 | /* Default configuration for physcial memcpy */ |
79 | struct stedma40_chan_cfg dma40_memcpy_conf_phy = { | 81 | struct stedma40_chan_cfg dma40_memcpy_conf_phy = { |
80 | .mode = STEDMA40_MODE_PHYSICAL, | 82 | .mode = STEDMA40_MODE_PHYSICAL, |
81 | .dir = STEDMA40_MEM_TO_MEM, | 83 | .dir = DMA_MEM_TO_MEM, |
82 | 84 | ||
83 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | 85 | .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, |
84 | .src_info.psize = STEDMA40_PSIZE_PHY_1, | 86 | .src_info.psize = STEDMA40_PSIZE_PHY_1, |
85 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | 87 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, |
86 | 88 | ||
87 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | 89 | .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, |
88 | .dst_info.psize = STEDMA40_PSIZE_PHY_1, | 90 | .dst_info.psize = STEDMA40_PSIZE_PHY_1, |
89 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | 91 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, |
90 | }; | 92 | }; |
@@ -92,13 +94,13 @@ struct stedma40_chan_cfg dma40_memcpy_conf_phy = { | |||
92 | /* Default configuration for logical memcpy */ | 94 | /* Default configuration for logical memcpy */ |
93 | struct stedma40_chan_cfg dma40_memcpy_conf_log = { | 95 | struct stedma40_chan_cfg dma40_memcpy_conf_log = { |
94 | .mode = STEDMA40_MODE_LOGICAL, | 96 | .mode = STEDMA40_MODE_LOGICAL, |
95 | .dir = STEDMA40_MEM_TO_MEM, | 97 | .dir = DMA_MEM_TO_MEM, |
96 | 98 | ||
97 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | 99 | .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, |
98 | .src_info.psize = STEDMA40_PSIZE_LOG_1, | 100 | .src_info.psize = STEDMA40_PSIZE_LOG_1, |
99 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | 101 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, |
100 | 102 | ||
101 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | 103 | .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, |
102 | .dst_info.psize = STEDMA40_PSIZE_LOG_1, | 104 | .dst_info.psize = STEDMA40_PSIZE_LOG_1, |
103 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | 105 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, |
104 | }; | 106 | }; |
@@ -522,6 +524,8 @@ struct d40_gen_dmac { | |||
522 | * @phy_start: Physical memory start of the DMA registers. | 524 | * @phy_start: Physical memory start of the DMA registers. |
523 | * @phy_size: Size of the DMA register map. | 525 | * @phy_size: Size of the DMA register map. |
524 | * @irq: The IRQ number. | 526 | * @irq: The IRQ number. |
527 | * @num_memcpy_chans: The number of channels used for memcpy (mem-to-mem | ||
528 | * transfers). | ||
525 | * @num_phy_chans: The number of physical channels. Read from HW. This | 529 | * @num_phy_chans: The number of physical channels. Read from HW. This |
526 | * is the number of available channels for this driver, not counting "Secure | 530 | * is the number of available channels for this driver, not counting "Secure |
527 | * mode" allocated physical channels. | 531 | * mode" allocated physical channels. |
@@ -565,6 +569,7 @@ struct d40_base { | |||
565 | phys_addr_t phy_start; | 569 | phys_addr_t phy_start; |
566 | resource_size_t phy_size; | 570 | resource_size_t phy_size; |
567 | int irq; | 571 | int irq; |
572 | int num_memcpy_chans; | ||
568 | int num_phy_chans; | 573 | int num_phy_chans; |
569 | int num_log_chans; | 574 | int num_log_chans; |
570 | struct device_dma_parameters dma_parms; | 575 | struct device_dma_parameters dma_parms; |
@@ -843,7 +848,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) | |||
843 | * that uses linked lists. | 848 | * that uses linked lists. |
844 | */ | 849 | */ |
845 | if (!(chan->phy_chan->use_soft_lli && | 850 | if (!(chan->phy_chan->use_soft_lli && |
846 | chan->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)) | 851 | chan->dma_cfg.dir == DMA_DEV_TO_MEM)) |
847 | curr_lcla = d40_lcla_alloc_one(chan, desc); | 852 | curr_lcla = d40_lcla_alloc_one(chan, desc); |
848 | 853 | ||
849 | first_lcla = curr_lcla; | 854 | first_lcla = curr_lcla; |
@@ -1005,20 +1010,21 @@ static int d40_psize_2_burst_size(bool is_log, int psize) | |||
1005 | 1010 | ||
1006 | /* | 1011 | /* |
1007 | * The dma only supports transmitting packages up to | 1012 | * The dma only supports transmitting packages up to |
1008 | * STEDMA40_MAX_SEG_SIZE << data_width. Calculate the total number of | 1013 | * STEDMA40_MAX_SEG_SIZE * data_width, where data_width is stored in Bytes. |
1009 | * dma elements required to send the entire sg list | 1014 | * |
1015 | * Calculate the total number of dma elements required to send the entire sg list. | ||
1010 | */ | 1016 | */ |
1011 | static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2) | 1017 | static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2) |
1012 | { | 1018 | { |
1013 | int dmalen; | 1019 | int dmalen; |
1014 | u32 max_w = max(data_width1, data_width2); | 1020 | u32 max_w = max(data_width1, data_width2); |
1015 | u32 min_w = min(data_width1, data_width2); | 1021 | u32 min_w = min(data_width1, data_width2); |
1016 | u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w); | 1022 | u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE * min_w, max_w); |
1017 | 1023 | ||
1018 | if (seg_max > STEDMA40_MAX_SEG_SIZE) | 1024 | if (seg_max > STEDMA40_MAX_SEG_SIZE) |
1019 | seg_max -= (1 << max_w); | 1025 | seg_max -= max_w; |
1020 | 1026 | ||
1021 | if (!IS_ALIGNED(size, 1 << max_w)) | 1027 | if (!IS_ALIGNED(size, max_w)) |
1022 | return -EINVAL; | 1028 | return -EINVAL; |
1023 | 1029 | ||
1024 | if (size <= seg_max) | 1030 | if (size <= seg_max) |
@@ -1311,12 +1317,12 @@ static void d40_config_set_event(struct d40_chan *d40c, | |||
1311 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); | 1317 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); |
1312 | 1318 | ||
1313 | /* Enable event line connected to device (or memcpy) */ | 1319 | /* Enable event line connected to device (or memcpy) */ |
1314 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || | 1320 | if ((d40c->dma_cfg.dir == DMA_DEV_TO_MEM) || |
1315 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) | 1321 | (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) |
1316 | __d40_config_set_event(d40c, event_type, event, | 1322 | __d40_config_set_event(d40c, event_type, event, |
1317 | D40_CHAN_REG_SSLNK); | 1323 | D40_CHAN_REG_SSLNK); |
1318 | 1324 | ||
1319 | if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) | 1325 | if (d40c->dma_cfg.dir != DMA_DEV_TO_MEM) |
1320 | __d40_config_set_event(d40c, event_type, event, | 1326 | __d40_config_set_event(d40c, event_type, event, |
1321 | D40_CHAN_REG_SDLNK); | 1327 | D40_CHAN_REG_SDLNK); |
1322 | } | 1328 | } |
@@ -1464,7 +1470,7 @@ static u32 d40_residue(struct d40_chan *d40c) | |||
1464 | >> D40_SREG_ELEM_PHY_ECNT_POS; | 1470 | >> D40_SREG_ELEM_PHY_ECNT_POS; |
1465 | } | 1471 | } |
1466 | 1472 | ||
1467 | return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); | 1473 | return num_elt * d40c->dma_cfg.dst_info.data_width; |
1468 | } | 1474 | } |
1469 | 1475 | ||
1470 | static bool d40_tx_is_linked(struct d40_chan *d40c) | 1476 | static bool d40_tx_is_linked(struct d40_chan *d40c) |
@@ -1740,7 +1746,7 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data) | |||
1740 | } | 1746 | } |
1741 | 1747 | ||
1742 | /* ACK interrupt */ | 1748 | /* ACK interrupt */ |
1743 | writel(1 << idx, base->virtbase + il[row].clr); | 1749 | writel(BIT(idx), base->virtbase + il[row].clr); |
1744 | 1750 | ||
1745 | spin_lock(&d40c->lock); | 1751 | spin_lock(&d40c->lock); |
1746 | 1752 | ||
@@ -1776,7 +1782,7 @@ static int d40_validate_conf(struct d40_chan *d40c, | |||
1776 | res = -EINVAL; | 1782 | res = -EINVAL; |
1777 | } | 1783 | } |
1778 | 1784 | ||
1779 | if (conf->dir == STEDMA40_PERIPH_TO_PERIPH) { | 1785 | if (conf->dir == DMA_DEV_TO_DEV) { |
1780 | /* | 1786 | /* |
1781 | * DMAC HW supports it. Will be added to this driver, | 1787 | * DMAC HW supports it. Will be added to this driver, |
1782 | * in case any dma client requires it. | 1788 | * in case any dma client requires it. |
@@ -1786,9 +1792,9 @@ static int d40_validate_conf(struct d40_chan *d40c, | |||
1786 | } | 1792 | } |
1787 | 1793 | ||
1788 | if (d40_psize_2_burst_size(is_log, conf->src_info.psize) * | 1794 | if (d40_psize_2_burst_size(is_log, conf->src_info.psize) * |
1789 | (1 << conf->src_info.data_width) != | 1795 | conf->src_info.data_width != |
1790 | d40_psize_2_burst_size(is_log, conf->dst_info.psize) * | 1796 | d40_psize_2_burst_size(is_log, conf->dst_info.psize) * |
1791 | (1 << conf->dst_info.data_width)) { | 1797 | conf->dst_info.data_width) { |
1792 | /* | 1798 | /* |
1793 | * The DMAC hardware only supports | 1799 | * The DMAC hardware only supports |
1794 | * src (burst x width) == dst (burst x width) | 1800 | * src (burst x width) == dst (burst x width) |
@@ -1830,8 +1836,8 @@ static bool d40_alloc_mask_set(struct d40_phy_res *phy, | |||
1830 | if (phy->allocated_src == D40_ALLOC_FREE) | 1836 | if (phy->allocated_src == D40_ALLOC_FREE) |
1831 | phy->allocated_src = D40_ALLOC_LOG_FREE; | 1837 | phy->allocated_src = D40_ALLOC_LOG_FREE; |
1832 | 1838 | ||
1833 | if (!(phy->allocated_src & (1 << log_event_line))) { | 1839 | if (!(phy->allocated_src & BIT(log_event_line))) { |
1834 | phy->allocated_src |= 1 << log_event_line; | 1840 | phy->allocated_src |= BIT(log_event_line); |
1835 | goto found; | 1841 | goto found; |
1836 | } else | 1842 | } else |
1837 | goto not_found; | 1843 | goto not_found; |
@@ -1842,8 +1848,8 @@ static bool d40_alloc_mask_set(struct d40_phy_res *phy, | |||
1842 | if (phy->allocated_dst == D40_ALLOC_FREE) | 1848 | if (phy->allocated_dst == D40_ALLOC_FREE) |
1843 | phy->allocated_dst = D40_ALLOC_LOG_FREE; | 1849 | phy->allocated_dst = D40_ALLOC_LOG_FREE; |
1844 | 1850 | ||
1845 | if (!(phy->allocated_dst & (1 << log_event_line))) { | 1851 | if (!(phy->allocated_dst & BIT(log_event_line))) { |
1846 | phy->allocated_dst |= 1 << log_event_line; | 1852 | phy->allocated_dst |= BIT(log_event_line); |
1847 | goto found; | 1853 | goto found; |
1848 | } else | 1854 | } else |
1849 | goto not_found; | 1855 | goto not_found; |
@@ -1873,11 +1879,11 @@ static bool d40_alloc_mask_free(struct d40_phy_res *phy, bool is_src, | |||
1873 | 1879 | ||
1874 | /* Logical channel */ | 1880 | /* Logical channel */ |
1875 | if (is_src) { | 1881 | if (is_src) { |
1876 | phy->allocated_src &= ~(1 << log_event_line); | 1882 | phy->allocated_src &= ~BIT(log_event_line); |
1877 | if (phy->allocated_src == D40_ALLOC_LOG_FREE) | 1883 | if (phy->allocated_src == D40_ALLOC_LOG_FREE) |
1878 | phy->allocated_src = D40_ALLOC_FREE; | 1884 | phy->allocated_src = D40_ALLOC_FREE; |
1879 | } else { | 1885 | } else { |
1880 | phy->allocated_dst &= ~(1 << log_event_line); | 1886 | phy->allocated_dst &= ~BIT(log_event_line); |
1881 | if (phy->allocated_dst == D40_ALLOC_LOG_FREE) | 1887 | if (phy->allocated_dst == D40_ALLOC_LOG_FREE) |
1882 | phy->allocated_dst = D40_ALLOC_FREE; | 1888 | phy->allocated_dst = D40_ALLOC_FREE; |
1883 | } | 1889 | } |
@@ -1907,11 +1913,11 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) | |||
1907 | phys = d40c->base->phy_res; | 1913 | phys = d40c->base->phy_res; |
1908 | num_phy_chans = d40c->base->num_phy_chans; | 1914 | num_phy_chans = d40c->base->num_phy_chans; |
1909 | 1915 | ||
1910 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 1916 | if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) { |
1911 | log_num = 2 * dev_type; | 1917 | log_num = 2 * dev_type; |
1912 | is_src = true; | 1918 | is_src = true; |
1913 | } else if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 1919 | } else if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || |
1914 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 1920 | d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { |
1915 | /* dst event lines are used for logical memcpy */ | 1921 | /* dst event lines are used for logical memcpy */ |
1916 | log_num = 2 * dev_type + 1; | 1922 | log_num = 2 * dev_type + 1; |
1917 | is_src = false; | 1923 | is_src = false; |
@@ -1922,7 +1928,7 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) | |||
1922 | event_line = D40_TYPE_TO_EVENT(dev_type); | 1928 | event_line = D40_TYPE_TO_EVENT(dev_type); |
1923 | 1929 | ||
1924 | if (!is_log) { | 1930 | if (!is_log) { |
1925 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 1931 | if (d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { |
1926 | /* Find physical half channel */ | 1932 | /* Find physical half channel */ |
1927 | if (d40c->dma_cfg.use_fixed_channel) { | 1933 | if (d40c->dma_cfg.use_fixed_channel) { |
1928 | i = d40c->dma_cfg.phy_channel; | 1934 | i = d40c->dma_cfg.phy_channel; |
@@ -2070,10 +2076,10 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
2070 | return -EINVAL; | 2076 | return -EINVAL; |
2071 | } | 2077 | } |
2072 | 2078 | ||
2073 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 2079 | if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || |
2074 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) | 2080 | d40c->dma_cfg.dir == DMA_MEM_TO_MEM) |
2075 | is_src = false; | 2081 | is_src = false; |
2076 | else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) | 2082 | else if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) |
2077 | is_src = true; | 2083 | is_src = true; |
2078 | else { | 2084 | else { |
2079 | chan_err(d40c, "Unknown direction\n"); | 2085 | chan_err(d40c, "Unknown direction\n"); |
@@ -2135,10 +2141,10 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
2135 | goto _exit; | 2141 | goto _exit; |
2136 | } | 2142 | } |
2137 | 2143 | ||
2138 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 2144 | if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || |
2139 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 2145 | d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { |
2140 | status = readl(chanbase + D40_CHAN_REG_SDLNK); | 2146 | status = readl(chanbase + D40_CHAN_REG_SDLNK); |
2141 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 2147 | } else if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) { |
2142 | status = readl(chanbase + D40_CHAN_REG_SSLNK); | 2148 | status = readl(chanbase + D40_CHAN_REG_SSLNK); |
2143 | } else { | 2149 | } else { |
2144 | chan_err(d40c, "Unknown direction\n"); | 2150 | chan_err(d40c, "Unknown direction\n"); |
@@ -2358,7 +2364,7 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) | |||
2358 | u32 rtreg; | 2364 | u32 rtreg; |
2359 | u32 event = D40_TYPE_TO_EVENT(dev_type); | 2365 | u32 event = D40_TYPE_TO_EVENT(dev_type); |
2360 | u32 group = D40_TYPE_TO_GROUP(dev_type); | 2366 | u32 group = D40_TYPE_TO_GROUP(dev_type); |
2361 | u32 bit = 1 << event; | 2367 | u32 bit = BIT(event); |
2362 | u32 prioreg; | 2368 | u32 prioreg; |
2363 | struct d40_gen_dmac *dmac = &d40c->base->gen_dmac; | 2369 | struct d40_gen_dmac *dmac = &d40c->base->gen_dmac; |
2364 | 2370 | ||
@@ -2389,12 +2395,12 @@ static void d40_set_prio_realtime(struct d40_chan *d40c) | |||
2389 | if (d40c->base->rev < 3) | 2395 | if (d40c->base->rev < 3) |
2390 | return; | 2396 | return; |
2391 | 2397 | ||
2392 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || | 2398 | if ((d40c->dma_cfg.dir == DMA_DEV_TO_MEM) || |
2393 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) | 2399 | (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) |
2394 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, true); | 2400 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, true); |
2395 | 2401 | ||
2396 | if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) || | 2402 | if ((d40c->dma_cfg.dir == DMA_MEM_TO_DEV) || |
2397 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) | 2403 | (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) |
2398 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false); | 2404 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false); |
2399 | } | 2405 | } |
2400 | 2406 | ||
@@ -2425,11 +2431,11 @@ static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec, | |||
2425 | 2431 | ||
2426 | switch (D40_DT_FLAGS_DIR(flags)) { | 2432 | switch (D40_DT_FLAGS_DIR(flags)) { |
2427 | case 0: | 2433 | case 0: |
2428 | cfg.dir = STEDMA40_MEM_TO_PERIPH; | 2434 | cfg.dir = DMA_MEM_TO_DEV; |
2429 | cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); | 2435 | cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); |
2430 | break; | 2436 | break; |
2431 | case 1: | 2437 | case 1: |
2432 | cfg.dir = STEDMA40_PERIPH_TO_MEM; | 2438 | cfg.dir = DMA_DEV_TO_MEM; |
2433 | cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); | 2439 | cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); |
2434 | break; | 2440 | break; |
2435 | } | 2441 | } |
@@ -2475,7 +2481,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) | |||
2475 | d40_set_prio_realtime(d40c); | 2481 | d40_set_prio_realtime(d40c); |
2476 | 2482 | ||
2477 | if (chan_is_logical(d40c)) { | 2483 | if (chan_is_logical(d40c)) { |
2478 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) | 2484 | if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) |
2479 | d40c->lcpa = d40c->base->lcpa_base + | 2485 | d40c->lcpa = d40c->base->lcpa_base + |
2480 | d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE; | 2486 | d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE; |
2481 | else | 2487 | else |
@@ -2675,33 +2681,10 @@ static void d40_terminate_all(struct dma_chan *chan) | |||
2675 | static int | 2681 | static int |
2676 | dma40_config_to_halfchannel(struct d40_chan *d40c, | 2682 | dma40_config_to_halfchannel(struct d40_chan *d40c, |
2677 | struct stedma40_half_channel_info *info, | 2683 | struct stedma40_half_channel_info *info, |
2678 | enum dma_slave_buswidth width, | ||
2679 | u32 maxburst) | 2684 | u32 maxburst) |
2680 | { | 2685 | { |
2681 | enum stedma40_periph_data_width addr_width; | ||
2682 | int psize; | 2686 | int psize; |
2683 | 2687 | ||
2684 | switch (width) { | ||
2685 | case DMA_SLAVE_BUSWIDTH_1_BYTE: | ||
2686 | addr_width = STEDMA40_BYTE_WIDTH; | ||
2687 | break; | ||
2688 | case DMA_SLAVE_BUSWIDTH_2_BYTES: | ||
2689 | addr_width = STEDMA40_HALFWORD_WIDTH; | ||
2690 | break; | ||
2691 | case DMA_SLAVE_BUSWIDTH_4_BYTES: | ||
2692 | addr_width = STEDMA40_WORD_WIDTH; | ||
2693 | break; | ||
2694 | case DMA_SLAVE_BUSWIDTH_8_BYTES: | ||
2695 | addr_width = STEDMA40_DOUBLEWORD_WIDTH; | ||
2696 | break; | ||
2697 | default: | ||
2698 | dev_err(d40c->base->dev, | ||
2699 | "illegal peripheral address width " | ||
2700 | "requested (%d)\n", | ||
2701 | width); | ||
2702 | return -EINVAL; | ||
2703 | } | ||
2704 | |||
2705 | if (chan_is_logical(d40c)) { | 2688 | if (chan_is_logical(d40c)) { |
2706 | if (maxburst >= 16) | 2689 | if (maxburst >= 16) |
2707 | psize = STEDMA40_PSIZE_LOG_16; | 2690 | psize = STEDMA40_PSIZE_LOG_16; |
@@ -2722,7 +2705,6 @@ dma40_config_to_halfchannel(struct d40_chan *d40c, | |||
2722 | psize = STEDMA40_PSIZE_PHY_1; | 2705 | psize = STEDMA40_PSIZE_PHY_1; |
2723 | } | 2706 | } |
2724 | 2707 | ||
2725 | info->data_width = addr_width; | ||
2726 | info->psize = psize; | 2708 | info->psize = psize; |
2727 | info->flow_ctrl = STEDMA40_NO_FLOW_CTRL; | 2709 | info->flow_ctrl = STEDMA40_NO_FLOW_CTRL; |
2728 | 2710 | ||
@@ -2748,12 +2730,12 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2748 | if (config->direction == DMA_DEV_TO_MEM) { | 2730 | if (config->direction == DMA_DEV_TO_MEM) { |
2749 | config_addr = config->src_addr; | 2731 | config_addr = config->src_addr; |
2750 | 2732 | ||
2751 | if (cfg->dir != STEDMA40_PERIPH_TO_MEM) | 2733 | if (cfg->dir != DMA_DEV_TO_MEM) |
2752 | dev_dbg(d40c->base->dev, | 2734 | dev_dbg(d40c->base->dev, |
2753 | "channel was not configured for peripheral " | 2735 | "channel was not configured for peripheral " |
2754 | "to memory transfer (%d) overriding\n", | 2736 | "to memory transfer (%d) overriding\n", |
2755 | cfg->dir); | 2737 | cfg->dir); |
2756 | cfg->dir = STEDMA40_PERIPH_TO_MEM; | 2738 | cfg->dir = DMA_DEV_TO_MEM; |
2757 | 2739 | ||
2758 | /* Configure the memory side */ | 2740 | /* Configure the memory side */ |
2759 | if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) | 2741 | if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) |
@@ -2764,12 +2746,12 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2764 | } else if (config->direction == DMA_MEM_TO_DEV) { | 2746 | } else if (config->direction == DMA_MEM_TO_DEV) { |
2765 | config_addr = config->dst_addr; | 2747 | config_addr = config->dst_addr; |
2766 | 2748 | ||
2767 | if (cfg->dir != STEDMA40_MEM_TO_PERIPH) | 2749 | if (cfg->dir != DMA_MEM_TO_DEV) |
2768 | dev_dbg(d40c->base->dev, | 2750 | dev_dbg(d40c->base->dev, |
2769 | "channel was not configured for memory " | 2751 | "channel was not configured for memory " |
2770 | "to peripheral transfer (%d) overriding\n", | 2752 | "to peripheral transfer (%d) overriding\n", |
2771 | cfg->dir); | 2753 | cfg->dir); |
2772 | cfg->dir = STEDMA40_MEM_TO_PERIPH; | 2754 | cfg->dir = DMA_MEM_TO_DEV; |
2773 | 2755 | ||
2774 | /* Configure the memory side */ | 2756 | /* Configure the memory side */ |
2775 | if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) | 2757 | if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) |
@@ -2806,14 +2788,24 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2806 | src_maxburst = dst_maxburst * dst_addr_width / src_addr_width; | 2788 | src_maxburst = dst_maxburst * dst_addr_width / src_addr_width; |
2807 | } | 2789 | } |
2808 | 2790 | ||
2791 | /* Only valid widths are; 1, 2, 4 and 8. */ | ||
2792 | if (src_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED || | ||
2793 | src_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || | ||
2794 | dst_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED || | ||
2795 | dst_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || | ||
2796 | ((src_addr_width > 1) && (src_addr_width & 1)) || | ||
2797 | ((dst_addr_width > 1) && (dst_addr_width & 1))) | ||
2798 | return -EINVAL; | ||
2799 | |||
2800 | cfg->src_info.data_width = src_addr_width; | ||
2801 | cfg->dst_info.data_width = dst_addr_width; | ||
2802 | |||
2809 | ret = dma40_config_to_halfchannel(d40c, &cfg->src_info, | 2803 | ret = dma40_config_to_halfchannel(d40c, &cfg->src_info, |
2810 | src_addr_width, | ||
2811 | src_maxburst); | 2804 | src_maxburst); |
2812 | if (ret) | 2805 | if (ret) |
2813 | return ret; | 2806 | return ret; |
2814 | 2807 | ||
2815 | ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info, | 2808 | ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info, |
2816 | dst_addr_width, | ||
2817 | dst_maxburst); | 2809 | dst_maxburst); |
2818 | if (ret) | 2810 | if (ret) |
2819 | return ret; | 2811 | return ret; |
@@ -2953,7 +2945,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, | |||
2953 | } | 2945 | } |
2954 | 2946 | ||
2955 | d40_chan_init(base, &base->dma_memcpy, base->log_chans, | 2947 | d40_chan_init(base, &base->dma_memcpy, base->log_chans, |
2956 | base->num_log_chans, ARRAY_SIZE(dma40_memcpy_channels)); | 2948 | base->num_log_chans, base->num_memcpy_chans); |
2957 | 2949 | ||
2958 | dma_cap_zero(base->dma_memcpy.cap_mask); | 2950 | dma_cap_zero(base->dma_memcpy.cap_mask); |
2959 | dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); | 2951 | dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); |
@@ -3154,6 +3146,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3154 | struct d40_base *base = NULL; | 3146 | struct d40_base *base = NULL; |
3155 | int num_log_chans = 0; | 3147 | int num_log_chans = 0; |
3156 | int num_phy_chans; | 3148 | int num_phy_chans; |
3149 | int num_memcpy_chans; | ||
3157 | int clk_ret = -EINVAL; | 3150 | int clk_ret = -EINVAL; |
3158 | int i; | 3151 | int i; |
3159 | u32 pid; | 3152 | u32 pid; |
@@ -3224,6 +3217,12 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3224 | else | 3217 | else |
3225 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; | 3218 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; |
3226 | 3219 | ||
3220 | /* The number of channels used for memcpy */ | ||
3221 | if (plat_data->num_of_memcpy_chans) | ||
3222 | num_memcpy_chans = plat_data->num_of_memcpy_chans; | ||
3223 | else | ||
3224 | num_memcpy_chans = ARRAY_SIZE(dma40_memcpy_channels); | ||
3225 | |||
3227 | num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY; | 3226 | num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY; |
3228 | 3227 | ||
3229 | dev_info(&pdev->dev, | 3228 | dev_info(&pdev->dev, |
@@ -3231,7 +3230,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3231 | rev, res->start, num_phy_chans, num_log_chans); | 3230 | rev, res->start, num_phy_chans, num_log_chans); |
3232 | 3231 | ||
3233 | base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + | 3232 | base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + |
3234 | (num_phy_chans + num_log_chans + ARRAY_SIZE(dma40_memcpy_channels)) * | 3233 | (num_phy_chans + num_log_chans + num_memcpy_chans) * |
3235 | sizeof(struct d40_chan), GFP_KERNEL); | 3234 | sizeof(struct d40_chan), GFP_KERNEL); |
3236 | 3235 | ||
3237 | if (base == NULL) { | 3236 | if (base == NULL) { |
@@ -3241,6 +3240,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3241 | 3240 | ||
3242 | base->rev = rev; | 3241 | base->rev = rev; |
3243 | base->clk = clk; | 3242 | base->clk = clk; |
3243 | base->num_memcpy_chans = num_memcpy_chans; | ||
3244 | base->num_phy_chans = num_phy_chans; | 3244 | base->num_phy_chans = num_phy_chans; |
3245 | base->num_log_chans = num_log_chans; | 3245 | base->num_log_chans = num_log_chans; |
3246 | base->phy_start = res->start; | 3246 | base->phy_start = res->start; |
@@ -3484,12 +3484,8 @@ static int __init d40_of_probe(struct platform_device *pdev, | |||
3484 | struct device_node *np) | 3484 | struct device_node *np) |
3485 | { | 3485 | { |
3486 | struct stedma40_platform_data *pdata; | 3486 | struct stedma40_platform_data *pdata; |
3487 | 3487 | int num_phy = 0, num_memcpy = 0, num_disabled = 0; | |
3488 | /* | 3488 | const const __be32 *list; |
3489 | * FIXME: Fill in this routine as more support is added. | ||
3490 | * First platform enabled (u8500) doens't need any extra | ||
3491 | * properties to run, so this is fairly sparce currently. | ||
3492 | */ | ||
3493 | 3489 | ||
3494 | pdata = devm_kzalloc(&pdev->dev, | 3490 | pdata = devm_kzalloc(&pdev->dev, |
3495 | sizeof(struct stedma40_platform_data), | 3491 | sizeof(struct stedma40_platform_data), |
@@ -3497,6 +3493,41 @@ static int __init d40_of_probe(struct platform_device *pdev, | |||
3497 | if (!pdata) | 3493 | if (!pdata) |
3498 | return -ENOMEM; | 3494 | return -ENOMEM; |
3499 | 3495 | ||
3496 | /* If absent this value will be obtained from h/w. */ | ||
3497 | of_property_read_u32(np, "dma-channels", &num_phy); | ||
3498 | if (num_phy > 0) | ||
3499 | pdata->num_of_phy_chans = num_phy; | ||
3500 | |||
3501 | list = of_get_property(np, "memcpy-channels", &num_memcpy); | ||
3502 | num_memcpy /= sizeof(*list); | ||
3503 | |||
3504 | if (num_memcpy > D40_MEMCPY_MAX_CHANS || num_memcpy <= 0) { | ||
3505 | d40_err(&pdev->dev, | ||
3506 | "Invalid number of memcpy channels specified (%d)\n", | ||
3507 | num_memcpy); | ||
3508 | return -EINVAL; | ||
3509 | } | ||
3510 | pdata->num_of_memcpy_chans = num_memcpy; | ||
3511 | |||
3512 | of_property_read_u32_array(np, "memcpy-channels", | ||
3513 | dma40_memcpy_channels, | ||
3514 | num_memcpy); | ||
3515 | |||
3516 | list = of_get_property(np, "disabled-channels", &num_disabled); | ||
3517 | num_disabled /= sizeof(*list); | ||
3518 | |||
3519 | if (num_disabled > STEDMA40_MAX_PHYS || num_disabled < 0) { | ||
3520 | d40_err(&pdev->dev, | ||
3521 | "Invalid number of disabled channels specified (%d)\n", | ||
3522 | num_disabled); | ||
3523 | return -EINVAL; | ||
3524 | } | ||
3525 | |||
3526 | of_property_read_u32_array(np, "disabled-channels", | ||
3527 | pdata->disabled_channels, | ||
3528 | num_disabled); | ||
3529 | pdata->disabled_channels[num_disabled] = -1; | ||
3530 | |||
3500 | pdev->dev.platform_data = pdata; | 3531 | pdev->dev.platform_data = pdata; |
3501 | 3532 | ||
3502 | return 0; | 3533 | return 0; |