diff options
author | Vinod Koul <vinod.koul@intel.com> | 2014-06-09 12:25:40 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2014-06-09 12:25:40 -0400 |
commit | 3c814be9712f1a9f22009fb56bf96cf6de2ec663 (patch) | |
tree | de68086c72202eaa6625c8262d403f7409dff3b4 /drivers/dma/dw | |
parent | 877d8425072b50965f6f04ea3a127928f66db72f (diff) | |
parent | 1222934e54b63752b4b1ad305d6a7f632a3ae46d (diff) |
Merge branch 'topic/dw' into for-linus
Diffstat (limited to 'drivers/dma/dw')
-rw-r--r-- | drivers/dma/dw/core.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index cfdbb92aae1d..a27ded53ab4f 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c | |||
@@ -1493,6 +1493,13 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1493 | dw->regs = chip->regs; | 1493 | dw->regs = chip->regs; |
1494 | chip->dw = dw; | 1494 | chip->dw = dw; |
1495 | 1495 | ||
1496 | dw->clk = devm_clk_get(chip->dev, "hclk"); | ||
1497 | if (IS_ERR(dw->clk)) | ||
1498 | return PTR_ERR(dw->clk); | ||
1499 | err = clk_prepare_enable(dw->clk); | ||
1500 | if (err) | ||
1501 | return err; | ||
1502 | |||
1496 | dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); | 1503 | dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); |
1497 | autocfg = dw_params >> DW_PARAMS_EN & 0x1; | 1504 | autocfg = dw_params >> DW_PARAMS_EN & 0x1; |
1498 | 1505 | ||
@@ -1500,15 +1507,19 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1500 | 1507 | ||
1501 | if (!pdata && autocfg) { | 1508 | if (!pdata && autocfg) { |
1502 | pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); | 1509 | pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); |
1503 | if (!pdata) | 1510 | if (!pdata) { |
1504 | return -ENOMEM; | 1511 | err = -ENOMEM; |
1512 | goto err_pdata; | ||
1513 | } | ||
1505 | 1514 | ||
1506 | /* Fill platform data with the default values */ | 1515 | /* Fill platform data with the default values */ |
1507 | pdata->is_private = true; | 1516 | pdata->is_private = true; |
1508 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; | 1517 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; |
1509 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; | 1518 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; |
1510 | } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) | 1519 | } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { |
1511 | return -EINVAL; | 1520 | err = -EINVAL; |
1521 | goto err_pdata; | ||
1522 | } | ||
1512 | 1523 | ||
1513 | if (autocfg) | 1524 | if (autocfg) |
1514 | nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1; | 1525 | nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1; |
@@ -1517,13 +1528,10 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1517 | 1528 | ||
1518 | dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan), | 1529 | dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan), |
1519 | GFP_KERNEL); | 1530 | GFP_KERNEL); |
1520 | if (!dw->chan) | 1531 | if (!dw->chan) { |
1521 | return -ENOMEM; | 1532 | err = -ENOMEM; |
1522 | 1533 | goto err_pdata; | |
1523 | dw->clk = devm_clk_get(chip->dev, "hclk"); | 1534 | } |
1524 | if (IS_ERR(dw->clk)) | ||
1525 | return PTR_ERR(dw->clk); | ||
1526 | clk_prepare_enable(dw->clk); | ||
1527 | 1535 | ||
1528 | /* Get hardware configuration parameters */ | 1536 | /* Get hardware configuration parameters */ |
1529 | if (autocfg) { | 1537 | if (autocfg) { |
@@ -1548,21 +1556,22 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1548 | /* Disable BLOCK interrupts as well */ | 1556 | /* Disable BLOCK interrupts as well */ |
1549 | channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); | 1557 | channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); |
1550 | 1558 | ||
1551 | err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt, | ||
1552 | IRQF_SHARED, "dw_dmac", dw); | ||
1553 | if (err) | ||
1554 | return err; | ||
1555 | |||
1556 | /* Create a pool of consistent memory blocks for hardware descriptors */ | 1559 | /* Create a pool of consistent memory blocks for hardware descriptors */ |
1557 | dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev, | 1560 | dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev, |
1558 | sizeof(struct dw_desc), 4, 0); | 1561 | sizeof(struct dw_desc), 4, 0); |
1559 | if (!dw->desc_pool) { | 1562 | if (!dw->desc_pool) { |
1560 | dev_err(chip->dev, "No memory for descriptors dma pool\n"); | 1563 | dev_err(chip->dev, "No memory for descriptors dma pool\n"); |
1561 | return -ENOMEM; | 1564 | err = -ENOMEM; |
1565 | goto err_pdata; | ||
1562 | } | 1566 | } |
1563 | 1567 | ||
1564 | tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); | 1568 | tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); |
1565 | 1569 | ||
1570 | err = request_irq(chip->irq, dw_dma_interrupt, IRQF_SHARED, | ||
1571 | "dw_dmac", dw); | ||
1572 | if (err) | ||
1573 | goto err_pdata; | ||
1574 | |||
1566 | INIT_LIST_HEAD(&dw->dma.channels); | 1575 | INIT_LIST_HEAD(&dw->dma.channels); |
1567 | for (i = 0; i < nr_channels; i++) { | 1576 | for (i = 0; i < nr_channels; i++) { |
1568 | struct dw_dma_chan *dwc = &dw->chan[i]; | 1577 | struct dw_dma_chan *dwc = &dw->chan[i]; |
@@ -1650,12 +1659,20 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1650 | 1659 | ||
1651 | dma_writel(dw, CFG, DW_CFG_DMA_EN); | 1660 | dma_writel(dw, CFG, DW_CFG_DMA_EN); |
1652 | 1661 | ||
1662 | err = dma_async_device_register(&dw->dma); | ||
1663 | if (err) | ||
1664 | goto err_dma_register; | ||
1665 | |||
1653 | dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", | 1666 | dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", |
1654 | nr_channels); | 1667 | nr_channels); |
1655 | 1668 | ||
1656 | dma_async_device_register(&dw->dma); | ||
1657 | |||
1658 | return 0; | 1669 | return 0; |
1670 | |||
1671 | err_dma_register: | ||
1672 | free_irq(chip->irq, dw); | ||
1673 | err_pdata: | ||
1674 | clk_disable_unprepare(dw->clk); | ||
1675 | return err; | ||
1659 | } | 1676 | } |
1660 | EXPORT_SYMBOL_GPL(dw_dma_probe); | 1677 | EXPORT_SYMBOL_GPL(dw_dma_probe); |
1661 | 1678 | ||
@@ -1667,6 +1684,7 @@ int dw_dma_remove(struct dw_dma_chip *chip) | |||
1667 | dw_dma_off(dw); | 1684 | dw_dma_off(dw); |
1668 | dma_async_device_unregister(&dw->dma); | 1685 | dma_async_device_unregister(&dw->dma); |
1669 | 1686 | ||
1687 | free_irq(chip->irq, dw); | ||
1670 | tasklet_kill(&dw->tasklet); | 1688 | tasklet_kill(&dw->tasklet); |
1671 | 1689 | ||
1672 | list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels, | 1690 | list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels, |
@@ -1675,6 +1693,8 @@ int dw_dma_remove(struct dw_dma_chip *chip) | |||
1675 | channel_clear_bit(dw, CH_EN, dwc->mask); | 1693 | channel_clear_bit(dw, CH_EN, dwc->mask); |
1676 | } | 1694 | } |
1677 | 1695 | ||
1696 | clk_disable_unprepare(dw->clk); | ||
1697 | |||
1678 | return 0; | 1698 | return 0; |
1679 | } | 1699 | } |
1680 | EXPORT_SYMBOL_GPL(dw_dma_remove); | 1700 | EXPORT_SYMBOL_GPL(dw_dma_remove); |