Skip to content

Commit 482c67e

Browse files
andy-shevVinod Koul
authored andcommitted
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>
1 parent 2a9fe9a commit 482c67e

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

drivers/dma/dw_dmac.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,10 @@ static int __devinit dw_probe(struct platform_device *pdev)
13791379
struct resource *io;
13801380
struct dw_dma *dw;
13811381
size_t size;
1382+
void __iomem *regs;
1383+
bool autocfg;
1384+
unsigned int dw_params;
1385+
unsigned int nr_channels;
13821386
int irq;
13831387
int err;
13841388
int i;
@@ -1395,23 +1399,32 @@ static int __devinit dw_probe(struct platform_device *pdev)
13951399
if (irq < 0)
13961400
return irq;
13971401

1398-
size = sizeof(struct dw_dma);
1399-
size += pdata->nr_channels * sizeof(struct dw_dma_chan);
1402+
regs = devm_request_and_ioremap(&pdev->dev, io);
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);
14001415
dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
14011416
if (!dw)
14021417
return -ENOMEM;
14031418

1404-
dw->regs = devm_request_and_ioremap(&pdev->dev, io);
1405-
if (!dw->regs)
1406-
return -EBUSY;
1407-
14081419
dw->clk = devm_clk_get(&pdev->dev, "hclk");
14091420
if (IS_ERR(dw->clk))
14101421
return PTR_ERR(dw->clk);
14111422
clk_prepare_enable(dw->clk);
14121423

1424+
dw->regs = regs;
1425+
14131426
/* 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;
14151428

14161429
/* force dma off, just in case */
14171430
dw_dma_off(dw);
@@ -1429,7 +1442,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
14291442
tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
14301443

14311444
INIT_LIST_HEAD(&dw->dma.channels);
1432-
for (i = 0; i < pdata->nr_channels; i++) {
1445+
for (i = 0; i < nr_channels; i++) {
14331446
struct dw_dma_chan *dwc = &dw->chan[i];
14341447

14351448
dwc->chan.device = &dw->dma;
@@ -1442,7 +1455,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
14421455

14431456
/* 7 is highest priority & 0 is lowest. */
14441457
if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
1445-
dwc->priority = pdata->nr_channels - i - 1;
1458+
dwc->priority = nr_channels - i - 1;
14461459
else
14471460
dwc->priority = i;
14481461

@@ -1483,7 +1496,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
14831496
dma_writel(dw, CFG, DW_CFG_DMA_EN);
14841497

14851498
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);
14871500

14881501
dma_async_device_register(&dw->dma);
14891502

0 commit comments

Comments
 (0)