aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dw_dmac.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2012-09-21 08:05:46 -0400
committerVinod Koul <vinod.koul@linux.intel.com>2012-09-27 06:05:23 -0400
commit482c67ea7bab80b956185a3e7553151820bc5876 (patch)
treeedc73d4f17e086dde2d1531ca11a68e04872ccf3 /drivers/dma/dw_dmac.c
parent2a9fe9ae3a7b3986a4229900e900bfaa72c7a152 (diff)
dw_dmac: get number of channels from hardware if possible
In case the controller has the encoded parameters feature enabled the driver will use it to get the number of channels. In the future it will be used for the other important parameters as well. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma/dw_dmac.c')
-rw-r--r--drivers/dma/dw_dmac.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index e817610d97c9..d71bc7167891 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1379,6 +1379,10 @@ static int __devinit dw_probe(struct platform_device *pdev)
1379 struct resource *io; 1379 struct resource *io;
1380 struct dw_dma *dw; 1380 struct dw_dma *dw;
1381 size_t size; 1381 size_t size;
1382 void __iomem *regs;
1383 bool autocfg;
1384 unsigned int dw_params;
1385 unsigned int nr_channels;
1382 int irq; 1386 int irq;
1383 int err; 1387 int err;
1384 int i; 1388 int i;
@@ -1395,23 +1399,32 @@ static int __devinit dw_probe(struct platform_device *pdev)
1395 if (irq < 0) 1399 if (irq < 0)
1396 return irq; 1400 return irq;
1397 1401
1398 size = sizeof(struct dw_dma); 1402 regs = devm_request_and_ioremap(&pdev->dev, io);
1399 size += pdata->nr_channels * sizeof(struct dw_dma_chan); 1403 if (!regs)
1404 return -EBUSY;
1405
1406 dw_params = dma_read_byaddr(regs, DW_PARAMS);
1407 autocfg = dw_params >> DW_PARAMS_EN & 0x1;
1408
1409 if (autocfg)
1410 nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1;
1411 else
1412 nr_channels = pdata->nr_channels;
1413
1414 size = sizeof(struct dw_dma) + nr_channels * sizeof(struct dw_dma_chan);
1400 dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 1415 dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
1401 if (!dw) 1416 if (!dw)
1402 return -ENOMEM; 1417 return -ENOMEM;
1403 1418
1404 dw->regs = devm_request_and_ioremap(&pdev->dev, io);
1405 if (!dw->regs)
1406 return -EBUSY;
1407
1408 dw->clk = devm_clk_get(&pdev->dev, "hclk"); 1419 dw->clk = devm_clk_get(&pdev->dev, "hclk");
1409 if (IS_ERR(dw->clk)) 1420 if (IS_ERR(dw->clk))
1410 return PTR_ERR(dw->clk); 1421 return PTR_ERR(dw->clk);
1411 clk_prepare_enable(dw->clk); 1422 clk_prepare_enable(dw->clk);
1412 1423
1424 dw->regs = regs;
1425
1413 /* Calculate all channel mask before DMA setup */ 1426 /* Calculate all channel mask before DMA setup */
1414 dw->all_chan_mask = (1 << pdata->nr_channels) - 1; 1427 dw->all_chan_mask = (1 << nr_channels) - 1;
1415 1428
1416 /* force dma off, just in case */ 1429 /* force dma off, just in case */
1417 dw_dma_off(dw); 1430 dw_dma_off(dw);
@@ -1429,7 +1442,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
1429 tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); 1442 tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
1430 1443
1431 INIT_LIST_HEAD(&dw->dma.channels); 1444 INIT_LIST_HEAD(&dw->dma.channels);
1432 for (i = 0; i < pdata->nr_channels; i++) { 1445 for (i = 0; i < nr_channels; i++) {
1433 struct dw_dma_chan *dwc = &dw->chan[i]; 1446 struct dw_dma_chan *dwc = &dw->chan[i];
1434 1447
1435 dwc->chan.device = &dw->dma; 1448 dwc->chan.device = &dw->dma;
@@ -1442,7 +1455,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
1442 1455
1443 /* 7 is highest priority & 0 is lowest. */ 1456 /* 7 is highest priority & 0 is lowest. */
1444 if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) 1457 if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
1445 dwc->priority = pdata->nr_channels - i - 1; 1458 dwc->priority = nr_channels - i - 1;
1446 else 1459 else
1447 dwc->priority = i; 1460 dwc->priority = i;
1448 1461
@@ -1483,7 +1496,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
1483 dma_writel(dw, CFG, DW_CFG_DMA_EN); 1496 dma_writel(dw, CFG, DW_CFG_DMA_EN);
1484 1497
1485 printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n", 1498 printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
1486 dev_name(&pdev->dev), pdata->nr_channels); 1499 dev_name(&pdev->dev), nr_channels);
1487 1500
1488 dma_async_device_register(&dw->dma); 1501 dma_async_device_register(&dw->dma);
1489 1502