Skip to content

Commit

Permalink
dw_dmac: get number of channels from hardware if possible
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Shevchenko authored and Vinod Koul committed Sep 27, 2012
1 parent 2a9fe9a commit 482c67e
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions drivers/dma/dw_dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,10 @@ static int __devinit dw_probe(struct platform_device *pdev)
struct resource *io;
struct dw_dma *dw;
size_t size;
void __iomem *regs;
bool autocfg;
unsigned int dw_params;
unsigned int nr_channels;
int irq;
int err;
int i;
Expand All @@ -1395,23 +1399,32 @@ static int __devinit dw_probe(struct platform_device *pdev)
if (irq < 0)
return irq;

size = sizeof(struct dw_dma);
size += pdata->nr_channels * sizeof(struct dw_dma_chan);
regs = devm_request_and_ioremap(&pdev->dev, io);
if (!regs)
return -EBUSY;

dw_params = dma_read_byaddr(regs, DW_PARAMS);
autocfg = dw_params >> DW_PARAMS_EN & 0x1;

if (autocfg)
nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1;
else
nr_channels = pdata->nr_channels;

size = sizeof(struct dw_dma) + nr_channels * sizeof(struct dw_dma_chan);
dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!dw)
return -ENOMEM;

dw->regs = devm_request_and_ioremap(&pdev->dev, io);
if (!dw->regs)
return -EBUSY;

dw->clk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(dw->clk))
return PTR_ERR(dw->clk);
clk_prepare_enable(dw->clk);

dw->regs = regs;

/* Calculate all channel mask before DMA setup */
dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
dw->all_chan_mask = (1 << nr_channels) - 1;

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

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

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

/* 7 is highest priority & 0 is lowest. */
if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
dwc->priority = pdata->nr_channels - i - 1;
dwc->priority = nr_channels - i - 1;
else
dwc->priority = i;

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

printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
dev_name(&pdev->dev), pdata->nr_channels);
dev_name(&pdev->dev), nr_channels);

dma_async_device_register(&dw->dma);

Expand Down

0 comments on commit 482c67e

Please sign in to comment.