aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dw_dmac.c
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 /drivers/dma/dw_dmac.c
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>
Diffstat (limited to 'drivers/dma/dw_dmac.c')
-rw-r--r--drivers/dma/dw_dmac.c145
1 files changed, 72 insertions, 73 deletions
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