summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-02-27 16:36:03 -0500
committerVinod Koul <vinod.koul@intel.com>2013-02-27 23:23:21 -0500
commitf9c6a655a94042f94c0adb30d07d93cfd8915e95 (patch)
tree527fa9aa65510c3ad96e4bb93fbdb6abd46b9f37
parent864ef69b2d9b34e7c85baa9c5c601d5e735b208a (diff)
dmaengine: dw_dmac: move to generic DMA binding
The original device tree binding for this driver, from Viresh Kumar unfortunately conflicted with the generic DMA binding, and did not allow to completely seperate slave device configuration from the controller. This is an attempt to replace it with an implementation of the generic binding, but it is currently completely untested, because I do not have any hardware with this particular controller. The patch applies on top of the slave-dma tree, which contains both the base support for the generic DMA binding, as well as the earlier attempt from Viresh. Both of these are currently not merged upstream however. This version incorporates feedback from Viresh Kumar, Andy Shevchenko and Russell King. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Vinod Koul <vinod.koul@linux.intel.com> Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--Documentation/devicetree/bindings/dma/snps-dma.txt70
-rw-r--r--drivers/dma/dw_dmac.c145
-rw-r--r--drivers/dma/dw_dmac_regs.h7
-rw-r--r--include/linux/dw_dmac.h5
4 files changed, 111 insertions, 116 deletions
diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb6f1d8..d58675ea1abf 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
3Required properties: 3Required properties:
4- compatible: "snps,dma-spear1340" 4- compatible: "snps,dma-spear1340"
5- reg: Address range of the DMAC registers 5- reg: Address range of the DMAC registers
6- interrupt-parent: Should be the phandle for the interrupt controller
7 that services interrupts for this device
8- interrupt: Should contain the DMAC interrupt number 6- interrupt: Should contain the DMAC interrupt number
9- nr_channels: Number of channels supported by hardware 7- dma-channels: Number of channels supported by hardware
10- is_private: The device channels should be marked as private and not for by the 8- dma-requests: Number of DMA request lines supported, up to 16
11 general purpose DMA channel allocator. False if not passed. 9- dma-masters: Number of AHB masters supported by the controller
10- #dma-cells: must be <3>
12- chan_allocation_order: order of allocation of channel, 0 (default): ascending, 11- chan_allocation_order: order of allocation of channel, 0 (default): ascending,
13 1: descending 12 1: descending
14- chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1: 13- chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
15 increase from chan n->0 14 increase from chan n->0
16- block_size: Maximum block size supported by the controller 15- block_size: Maximum block size supported by the controller
17- nr_masters: Number of AHB masters supported by the controller
18- data_width: Maximum data width supported by hardware per AHB master 16- data_width: Maximum data width supported by hardware per AHB master
19 (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) 17 (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
20- slave_info: 18
21 - bus_id: name of this device channel, not just a device name since 19
22 devices may have more than one channel e.g. "foo_tx". For using the 20Optional properties:
23 dw_generic_filter(), slave drivers must pass exactly this string as 21- interrupt-parent: Should be the phandle for the interrupt controller
24 param to filter function. 22 that services interrupts for this device
25 - cfg_hi: Platform-specific initializer for the CFG_HI register 23- is_private: The device channels should be marked as private and not for by the
26 - cfg_lo: Platform-specific initializer for the CFG_LO register 24 general purpose DMA channel allocator. False if not passed.
27 - src_master: src master for transfers on allocated channel.
28 - dst_master: dest master for transfers on allocated channel.
29 25
30Example: 26Example:
31 27
32 dma@fc000000 { 28 dmahost: dma@fc000000 {
33 compatible = "snps,dma-spear1340"; 29 compatible = "snps,dma-spear1340";
34 reg = <0xfc000000 0x1000>; 30 reg = <0xfc000000 0x1000>;
35 interrupt-parent = <&vic1>; 31 interrupt-parent = <&vic1>;
36 interrupts = <12>; 32 interrupts = <12>;
37 33
38 nr_channels = <8>; 34 dma-channels = <8>;
35 dma-requests = <16>;
36 dma-masters = <2>;
37 #dma-cells = <3>;
39 chan_allocation_order = <1>; 38 chan_allocation_order = <1>;
40 chan_priority = <1>; 39 chan_priority = <1>;
41 block_size = <0xfff>; 40 block_size = <0xfff>;
42 nr_masters = <2>;
43 data_width = <3 3 0 0>; 41 data_width = <3 3 0 0>;
42 };
44 43
45 slave_info { 44DMA clients connected to the Designware DMA controller must use the format
46 uart0-tx { 45described in the dma.txt file, using a four-cell specifier for each channel.
47 bus_id = "uart0-tx"; 46The four cells in order are:
48 cfg_hi = <0x4000>; /* 0x8 << 11 */ 47
49 cfg_lo = <0>; 481. A phandle pointing to the DMA controller
50 src_master = <0>; 492. The DMA request line number
51 dst_master = <1>; 503. Source master for transfers on allocated channel
52 }; 514. Destination master for transfers on allocated channel
53 spi0-tx { 52
54 bus_id = "spi0-tx"; 53Example:
55 cfg_hi = <0x2000>; /* 0x4 << 11 */ 54
56 cfg_lo = <0>; 55 serial@e0000000 {
57 src_master = <0>; 56 compatible = "arm,pl011", "arm,primecell";
58 dst_master = <0>; 57 reg = <0xe0000000 0x1000>;
59 }; 58 interrupts = <0 35 0x4>;
60 }; 59 status = "disabled";
60 dmas = <&dmahost 12 0 1>,
61 <&dmahost 13 0 1 0>;
62 dma-names = "rx", "rx";
61 }; 63 };
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18803f1..c3159abf9ac1 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_dma.h>
22#include <linux/mm.h> 23#include <linux/mm.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
170 if (dwc->initialized == true) 171 if (dwc->initialized == true)
171 return; 172 return;
172 173
173 if (dws) { 174 if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
175 /* autoconfigure based on request line from DT */
176 if (dwc->direction == DMA_MEM_TO_DEV)
177 cfghi = DWC_CFGH_DST_PER(dwc->request_line);
178 else if (dwc->direction == DMA_DEV_TO_MEM)
179 cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
180 } else if (dws) {
174 /* 181 /*
175 * We need controller-specific data to set up slave 182 * We need controller-specific data to set up slave
176 * transfers. 183 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
1225 dev_vdbg(chan2dev(chan), "%s: done\n", __func__); 1232 dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
1226} 1233}
1227 1234
1228bool dw_dma_generic_filter(struct dma_chan *chan, void *param) 1235struct dw_dma_filter_args {
1236 struct dw_dma *dw;
1237 unsigned int req;
1238 unsigned int src;
1239 unsigned int dst;
1240};
1241
1242static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
1229{ 1243{
1244 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
1230 struct dw_dma *dw = to_dw_dma(chan->device); 1245 struct dw_dma *dw = to_dw_dma(chan->device);
1231 static struct dw_dma *last_dw; 1246 struct dw_dma_filter_args *fargs = param;
1232 static char *last_bus_id; 1247 struct dw_dma_slave *dws = &dwc->slave;
1233 int i = -1;
1234 1248
1235 /* 1249 /* ensure the device matches our channel */
1236 * dmaengine framework calls this routine for all channels of all dma 1250 if (chan->device != &fargs->dw->dma)
1237 * controller, until true is returned. If 'param' bus_id is not 1251 return false;
1238 * registered with a dma controller (dw), then there is no need of
1239 * running below function for all channels of dw.
1240 *
1241 * This block of code does this by saving the parameters of last
1242 * failure. If dw and param are same, i.e. trying on same dw with
1243 * different channel, return false.
1244 */
1245 if ((last_dw == dw) && (last_bus_id == param))
1246 return false;
1247 /*
1248 * Return true:
1249 * - If dw_dma's platform data is not filled with slave info, then all
1250 * dma controllers are fine for transfer.
1251 * - Or if param is NULL
1252 */
1253 if (!dw->sd || !param)
1254 return true;
1255 1252
1256 while (++i < dw->sd_count) { 1253 dws->dma_dev = dw->dma.dev;
1257 if (!strcmp(dw->sd[i].bus_id, param)) { 1254 dws->cfg_hi = ~0;
1258 chan->private = &dw->sd[i]; 1255 dws->cfg_lo = ~0;
1259 last_dw = NULL; 1256 dws->src_master = fargs->src;
1260 last_bus_id = NULL; 1257 dws->dst_master = fargs->dst;
1261 1258
1262 return true; 1259 dwc->request_line = fargs->req;
1263 }
1264 }
1265 1260
1266 last_dw = dw; 1261 chan->private = dws;
1267 last_bus_id = param; 1262
1268 return false; 1263 return true;
1264}
1265
1266static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
1267 struct of_dma *ofdma)
1268{
1269 struct dw_dma *dw = ofdma->of_dma_data;
1270 struct dw_dma_filter_args fargs = {
1271 .dw = dw,
1272 };
1273 dma_cap_mask_t cap;
1274
1275 if (dma_spec->args_count != 3)
1276 return NULL;
1277
1278 fargs.req = be32_to_cpup(dma_spec->args+0);
1279 fargs.src = be32_to_cpup(dma_spec->args+1);
1280 fargs.dst = be32_to_cpup(dma_spec->args+2);
1281
1282 if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
1283 fargs.src >= dw->nr_masters ||
1284 fargs.dst >= dw->nr_masters))
1285 return NULL;
1286
1287 dma_cap_zero(cap);
1288 dma_cap_set(DMA_SLAVE, cap);
1289
1290 /* TODO: there should be a simpler way to do this */
1291 return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
1269} 1292}
1270EXPORT_SYMBOL(dw_dma_generic_filter);
1271 1293
1272/* --------------------- Cyclic DMA API extensions -------------------- */ 1294/* --------------------- Cyclic DMA API extensions -------------------- */
1273 1295
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
1553static struct dw_dma_platform_data * 1575static struct dw_dma_platform_data *
1554dw_dma_parse_dt(struct platform_device *pdev) 1576dw_dma_parse_dt(struct platform_device *pdev)
1555{ 1577{
1556 struct device_node *sn, *cn, *np = pdev->dev.of_node; 1578 struct device_node *np = pdev->dev.of_node;
1557 struct dw_dma_platform_data *pdata; 1579 struct dw_dma_platform_data *pdata;
1558 struct dw_dma_slave *sd;
1559 u32 tmp, arr[4]; 1580 u32 tmp, arr[4];
1560 1581
1561 if (!np) { 1582 if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
1567 if (!pdata) 1588 if (!pdata)
1568 return NULL; 1589 return NULL;
1569 1590
1570 if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels)) 1591 if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
1571 return NULL; 1592 return NULL;
1572 1593
1573 if (of_property_read_bool(np, "is_private")) 1594 if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
1582 if (!of_property_read_u32(np, "block_size", &tmp)) 1603 if (!of_property_read_u32(np, "block_size", &tmp))
1583 pdata->block_size = tmp; 1604 pdata->block_size = tmp;
1584 1605
1585 if (!of_property_read_u32(np, "nr_masters", &tmp)) { 1606 if (!of_property_read_u32(np, "dma-masters", &tmp)) {
1586 if (tmp > 4) 1607 if (tmp > 4)
1587 return NULL; 1608 return NULL;
1588 1609
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
1594 for (tmp = 0; tmp < pdata->nr_masters; tmp++) 1615 for (tmp = 0; tmp < pdata->nr_masters; tmp++)
1595 pdata->data_width[tmp] = arr[tmp]; 1616 pdata->data_width[tmp] = arr[tmp];
1596 1617
1597 /* parse slave data */
1598 sn = of_find_node_by_name(np, "slave_info");
1599 if (!sn)
1600 return pdata;
1601
1602 /* calculate number of slaves */
1603 tmp = of_get_child_count(sn);
1604 if (!tmp)
1605 return NULL;
1606
1607 sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
1608 if (!sd)
1609 return NULL;
1610
1611 pdata->sd = sd;
1612 pdata->sd_count = tmp;
1613
1614 for_each_child_of_node(sn, cn) {
1615 sd->dma_dev = &pdev->dev;
1616 of_property_read_string(cn, "bus_id", &sd->bus_id);
1617 of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
1618 of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
1619 if (!of_property_read_u32(cn, "src_master", &tmp))
1620 sd->src_master = tmp;
1621
1622 if (!of_property_read_u32(cn, "dst_master", &tmp))
1623 sd->dst_master = tmp;
1624 sd++;
1625 }
1626
1627 return pdata; 1618 return pdata;
1628} 1619}
1629#else 1620#else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
1704 clk_prepare_enable(dw->clk); 1695 clk_prepare_enable(dw->clk);
1705 1696
1706 dw->regs = regs; 1697 dw->regs = regs;
1707 dw->sd = pdata->sd;
1708 dw->sd_count = pdata->sd_count;
1709 1698
1710 /* get hardware configuration parameters */ 1699 /* get hardware configuration parameters */
1711 if (autocfg) { 1700 if (autocfg) {
@@ -1836,6 +1825,14 @@ static int dw_probe(struct platform_device *pdev)
1836 1825
1837 dma_async_device_register(&dw->dma); 1826 dma_async_device_register(&dw->dma);
1838 1827
1828 if (pdev->dev.of_node) {
1829 err = of_dma_controller_register(pdev->dev.of_node,
1830 dw_dma_xlate, dw);
1831 if (err && err != -ENODEV)
1832 dev_err(&pdev->dev,
1833 "could not register of_dma_controller\n");
1834 }
1835
1839 return 0; 1836 return 0;
1840} 1837}
1841 1838
@@ -1844,6 +1841,8 @@ static int __devexit dw_remove(struct platform_device *pdev)
1844 struct dw_dma *dw = platform_get_drvdata(pdev); 1841 struct dw_dma *dw = platform_get_drvdata(pdev);
1845 struct dw_dma_chan *dwc, *_dwc; 1842 struct dw_dma_chan *dwc, *_dwc;
1846 1843
1844 if (pdev->dev.of_node)
1845 of_dma_controller_free(pdev->dev.of_node);
1847 dw_dma_off(dw); 1846 dw_dma_off(dw);
1848 dma_async_device_unregister(&dw->dma); 1847 dma_async_device_unregister(&dw->dma);
1849 1848
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb31957..cf0ce5c77d60 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
13#include <linux/dw_dmac.h> 13#include <linux/dw_dmac.h>
14 14
15#define DW_DMA_MAX_NR_CHANNELS 8 15#define DW_DMA_MAX_NR_CHANNELS 8
16#define DW_DMA_MAX_NR_REQUESTS 16
16 17
17/* flow controller */ 18/* flow controller */
18enum dw_dma_fc { 19enum dw_dma_fc {
@@ -211,6 +212,8 @@ struct dw_dma_chan {
211 /* hardware configuration */ 212 /* hardware configuration */
212 unsigned int block_size; 213 unsigned int block_size;
213 bool nollp; 214 bool nollp;
215 unsigned int request_line;
216 struct dw_dma_slave slave;
214 217
215 /* configuration passed via DMA_SLAVE_CONFIG */ 218 /* configuration passed via DMA_SLAVE_CONFIG */
216 struct dma_slave_config dma_sconfig; 219 struct dma_slave_config dma_sconfig;
@@ -239,10 +242,6 @@ struct dw_dma {
239 struct tasklet_struct tasklet; 242 struct tasklet_struct tasklet;
240 struct clk *clk; 243 struct clk *clk;
241 244
242 /* slave information */
243 struct dw_dma_slave *sd;
244 unsigned int sd_count;
245
246 u8 all_chan_mask; 245 u8 all_chan_mask;
247 246
248 /* hardware configuration */ 247 /* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de66e33..481ab2345d6b 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
27 */ 27 */
28struct dw_dma_slave { 28struct dw_dma_slave {
29 struct device *dma_dev; 29 struct device *dma_dev;
30 const char *bus_id;
31 u32 cfg_hi; 30 u32 cfg_hi;
32 u32 cfg_lo; 31 u32 cfg_lo;
33 u8 src_master; 32 u8 src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
60 unsigned short block_size; 59 unsigned short block_size;
61 unsigned char nr_masters; 60 unsigned char nr_masters;
62 unsigned char data_width[4]; 61 unsigned char data_width[4];
63
64 struct dw_dma_slave *sd;
65 unsigned int sd_count;
66}; 62};
67 63
68/* bursts size */ 64/* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
114dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan); 110dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
115 111
116dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan); 112dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
117bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
118 113
119#endif /* DW_DMAC_H */ 114#endif /* DW_DMAC_H */