diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-01-06 13:38:16 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-01-06 13:38:16 -0500 |
commit | 74465b4ff9ac1da503025c0a0042e023bfa6505c (patch) | |
tree | ce63f4a4b055b65cae1edaddd334931bf512c76e /drivers | |
parent | 33df8ca068123457db56c316946a3c0e4ef787d6 (diff) |
atmel-mci: convert to dma_request_channel and down-level dma_slave
dma_request_channel provides an exclusive channel, so we no longer need to
pass slave data through dmaengine.
Cc: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/dmaengine.c | 8 | ||||
-rw-r--r-- | drivers/dma/dw_dmac.c | 25 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 98 |
3 files changed, 33 insertions, 98 deletions
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 7a0594f24a3f..90aca505a1df 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -234,10 +234,6 @@ static void dma_client_chan_alloc(struct dma_client *client) | |||
234 | list_for_each_entry(device, &dma_device_list, global_node) { | 234 | list_for_each_entry(device, &dma_device_list, global_node) { |
235 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) | 235 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) |
236 | continue; | 236 | continue; |
237 | /* Does the client require a specific DMA controller? */ | ||
238 | if (client->slave && client->slave->dma_dev | ||
239 | && client->slave->dma_dev != device->dev) | ||
240 | continue; | ||
241 | if (!dma_device_satisfies_mask(device, client->cap_mask)) | 237 | if (!dma_device_satisfies_mask(device, client->cap_mask)) |
242 | continue; | 238 | continue; |
243 | 239 | ||
@@ -613,10 +609,6 @@ void dma_async_client_register(struct dma_client *client) | |||
613 | struct dma_chan *chan; | 609 | struct dma_chan *chan; |
614 | int err; | 610 | int err; |
615 | 611 | ||
616 | /* validate client data */ | ||
617 | BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) && | ||
618 | !client->slave); | ||
619 | |||
620 | mutex_lock(&dma_list_mutex); | 612 | mutex_lock(&dma_list_mutex); |
621 | dmaengine_ref_count++; | 613 | dmaengine_ref_count++; |
622 | 614 | ||
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 377dafa37a20..dbd50804e5d2 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
@@ -567,7 +567,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
567 | if (unlikely(!dws || !sg_len)) | 567 | if (unlikely(!dws || !sg_len)) |
568 | return NULL; | 568 | return NULL; |
569 | 569 | ||
570 | reg_width = dws->slave.reg_width; | 570 | reg_width = dws->reg_width; |
571 | prev = first = NULL; | 571 | prev = first = NULL; |
572 | 572 | ||
573 | sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); | 573 | sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); |
@@ -579,7 +579,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
579 | | DWC_CTLL_DST_FIX | 579 | | DWC_CTLL_DST_FIX |
580 | | DWC_CTLL_SRC_INC | 580 | | DWC_CTLL_SRC_INC |
581 | | DWC_CTLL_FC_M2P); | 581 | | DWC_CTLL_FC_M2P); |
582 | reg = dws->slave.tx_reg; | 582 | reg = dws->tx_reg; |
583 | for_each_sg(sgl, sg, sg_len, i) { | 583 | for_each_sg(sgl, sg, sg_len, i) { |
584 | struct dw_desc *desc; | 584 | struct dw_desc *desc; |
585 | u32 len; | 585 | u32 len; |
@@ -625,7 +625,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
625 | | DWC_CTLL_SRC_FIX | 625 | | DWC_CTLL_SRC_FIX |
626 | | DWC_CTLL_FC_P2M); | 626 | | DWC_CTLL_FC_P2M); |
627 | 627 | ||
628 | reg = dws->slave.rx_reg; | 628 | reg = dws->rx_reg; |
629 | for_each_sg(sgl, sg, sg_len, i) { | 629 | for_each_sg(sgl, sg, sg_len, i) { |
630 | struct dw_desc *desc; | 630 | struct dw_desc *desc; |
631 | u32 len; | 631 | u32 len; |
@@ -764,7 +764,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
764 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | 764 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
765 | struct dw_dma *dw = to_dw_dma(chan->device); | 765 | struct dw_dma *dw = to_dw_dma(chan->device); |
766 | struct dw_desc *desc; | 766 | struct dw_desc *desc; |
767 | struct dma_slave *slave; | ||
768 | struct dw_dma_slave *dws; | 767 | struct dw_dma_slave *dws; |
769 | int i; | 768 | int i; |
770 | u32 cfghi; | 769 | u32 cfghi; |
@@ -772,12 +771,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
772 | 771 | ||
773 | dev_vdbg(&chan->dev, "alloc_chan_resources\n"); | 772 | dev_vdbg(&chan->dev, "alloc_chan_resources\n"); |
774 | 773 | ||
775 | /* Channels doing slave DMA can only handle one client. */ | ||
776 | if (dwc->dws || (client && client->slave)) { | ||
777 | if (chan->client_count) | ||
778 | return -EBUSY; | ||
779 | } | ||
780 | |||
781 | /* ASSERT: channel is idle */ | 774 | /* ASSERT: channel is idle */ |
782 | if (dma_readl(dw, CH_EN) & dwc->mask) { | 775 | if (dma_readl(dw, CH_EN) & dwc->mask) { |
783 | dev_dbg(&chan->dev, "DMA channel not idle?\n"); | 776 | dev_dbg(&chan->dev, "DMA channel not idle?\n"); |
@@ -789,23 +782,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
789 | cfghi = DWC_CFGH_FIFO_MODE; | 782 | cfghi = DWC_CFGH_FIFO_MODE; |
790 | cfglo = 0; | 783 | cfglo = 0; |
791 | 784 | ||
792 | slave = client->slave; | 785 | dws = dwc->dws; |
793 | if (slave) { | 786 | if (dws) { |
794 | /* | 787 | /* |
795 | * We need controller-specific data to set up slave | 788 | * We need controller-specific data to set up slave |
796 | * transfers. | 789 | * transfers. |
797 | */ | 790 | */ |
798 | BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev); | 791 | BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); |
799 | |||
800 | dws = container_of(slave, struct dw_dma_slave, slave); | ||
801 | 792 | ||
802 | dwc->dws = dws; | ||
803 | cfghi = dws->cfg_hi; | 793 | cfghi = dws->cfg_hi; |
804 | cfglo = dws->cfg_lo; | 794 | cfglo = dws->cfg_lo; |
805 | } else { | ||
806 | dwc->dws = NULL; | ||
807 | } | 795 | } |
808 | |||
809 | channel_writel(dwc, CFG_LO, cfglo); | 796 | channel_writel(dwc, CFG_LO, cfglo); |
810 | channel_writel(dwc, CFG_HI, cfghi); | 797 | channel_writel(dwc, CFG_HI, cfghi); |
811 | 798 | ||
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 6c11f4d4c4e9..7a34118507db 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -1441,60 +1441,6 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) | |||
1441 | return IRQ_HANDLED; | 1441 | return IRQ_HANDLED; |
1442 | } | 1442 | } |
1443 | 1443 | ||
1444 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1445 | |||
1446 | static inline struct atmel_mci * | ||
1447 | dma_client_to_atmel_mci(struct dma_client *client) | ||
1448 | { | ||
1449 | return container_of(client, struct atmel_mci, dma.client); | ||
1450 | } | ||
1451 | |||
1452 | static enum dma_state_client atmci_dma_event(struct dma_client *client, | ||
1453 | struct dma_chan *chan, enum dma_state state) | ||
1454 | { | ||
1455 | struct atmel_mci *host; | ||
1456 | enum dma_state_client ret = DMA_NAK; | ||
1457 | |||
1458 | host = dma_client_to_atmel_mci(client); | ||
1459 | |||
1460 | switch (state) { | ||
1461 | case DMA_RESOURCE_AVAILABLE: | ||
1462 | spin_lock_bh(&host->lock); | ||
1463 | if (!host->dma.chan) { | ||
1464 | host->dma.chan = chan; | ||
1465 | ret = DMA_ACK; | ||
1466 | } | ||
1467 | spin_unlock_bh(&host->lock); | ||
1468 | |||
1469 | if (ret == DMA_ACK) | ||
1470 | dev_info(&host->pdev->dev, | ||
1471 | "Using %s for DMA transfers\n", | ||
1472 | chan->dev.bus_id); | ||
1473 | break; | ||
1474 | |||
1475 | case DMA_RESOURCE_REMOVED: | ||
1476 | spin_lock_bh(&host->lock); | ||
1477 | if (host->dma.chan == chan) { | ||
1478 | host->dma.chan = NULL; | ||
1479 | ret = DMA_ACK; | ||
1480 | } | ||
1481 | spin_unlock_bh(&host->lock); | ||
1482 | |||
1483 | if (ret == DMA_ACK) | ||
1484 | dev_info(&host->pdev->dev, | ||
1485 | "Lost %s, falling back to PIO\n", | ||
1486 | chan->dev.bus_id); | ||
1487 | break; | ||
1488 | |||
1489 | default: | ||
1490 | break; | ||
1491 | } | ||
1492 | |||
1493 | |||
1494 | return ret; | ||
1495 | } | ||
1496 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
1497 | |||
1498 | static int __init atmci_init_slot(struct atmel_mci *host, | 1444 | static int __init atmci_init_slot(struct atmel_mci *host, |
1499 | struct mci_slot_pdata *slot_data, unsigned int id, | 1445 | struct mci_slot_pdata *slot_data, unsigned int id, |
1500 | u32 sdc_reg) | 1446 | u32 sdc_reg) |
@@ -1598,6 +1544,18 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, | |||
1598 | mmc_free_host(slot->mmc); | 1544 | mmc_free_host(slot->mmc); |
1599 | } | 1545 | } |
1600 | 1546 | ||
1547 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1548 | static enum dma_state_client filter(struct dma_chan *chan, void *slave) | ||
1549 | { | ||
1550 | struct dw_dma_slave *dws = slave; | ||
1551 | |||
1552 | if (dws->dma_dev == chan->device->dev) | ||
1553 | return DMA_ACK; | ||
1554 | else | ||
1555 | return DMA_DUP; | ||
1556 | } | ||
1557 | #endif | ||
1558 | |||
1601 | static int __init atmci_probe(struct platform_device *pdev) | 1559 | static int __init atmci_probe(struct platform_device *pdev) |
1602 | { | 1560 | { |
1603 | struct mci_platform_data *pdata; | 1561 | struct mci_platform_data *pdata; |
@@ -1650,22 +1608,20 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1650 | goto err_request_irq; | 1608 | goto err_request_irq; |
1651 | 1609 | ||
1652 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1610 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1653 | if (pdata->dma_slave) { | 1611 | if (pdata->dma_slave.dma_dev) { |
1654 | struct dma_slave *slave = pdata->dma_slave; | 1612 | struct dw_dma_slave *dws = &pdata->dma_slave; |
1613 | dma_cap_mask_t mask; | ||
1655 | 1614 | ||
1656 | slave->tx_reg = regs->start + MCI_TDR; | 1615 | dws->tx_reg = regs->start + MCI_TDR; |
1657 | slave->rx_reg = regs->start + MCI_RDR; | 1616 | dws->rx_reg = regs->start + MCI_RDR; |
1658 | 1617 | ||
1659 | /* Try to grab a DMA channel */ | 1618 | /* Try to grab a DMA channel */ |
1660 | host->dma.client.event_callback = atmci_dma_event; | 1619 | dma_cap_zero(mask); |
1661 | dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask); | 1620 | dma_cap_set(DMA_SLAVE, mask); |
1662 | host->dma.client.slave = slave; | 1621 | host->dma.chan = dma_request_channel(mask, filter, dws); |
1663 | |||
1664 | dma_async_client_register(&host->dma.client); | ||
1665 | dma_async_client_chan_request(&host->dma.client); | ||
1666 | } else { | ||
1667 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
1668 | } | 1622 | } |
1623 | if (!host->dma.chan) | ||
1624 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
1669 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | 1625 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ |
1670 | 1626 | ||
1671 | platform_set_drvdata(pdev, host); | 1627 | platform_set_drvdata(pdev, host); |
@@ -1697,8 +1653,8 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1697 | 1653 | ||
1698 | err_init_slot: | 1654 | err_init_slot: |
1699 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1655 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1700 | if (pdata->dma_slave) | 1656 | if (host->dma.chan) |
1701 | dma_async_client_unregister(&host->dma.client); | 1657 | dma_release_channel(host->dma.chan); |
1702 | #endif | 1658 | #endif |
1703 | free_irq(irq, host); | 1659 | free_irq(irq, host); |
1704 | err_request_irq: | 1660 | err_request_irq: |
@@ -1729,8 +1685,8 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
1729 | clk_disable(host->mck); | 1685 | clk_disable(host->mck); |
1730 | 1686 | ||
1731 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1687 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1732 | if (host->dma.client.slave) | 1688 | if (host->dma.chan) |
1733 | dma_async_client_unregister(&host->dma.client); | 1689 | dma_release_channel(host->dma.chan); |
1734 | #endif | 1690 | #endif |
1735 | 1691 | ||
1736 | free_irq(platform_get_irq(pdev, 0), host); | 1692 | free_irq(platform_get_irq(pdev, 0), host); |
@@ -1759,7 +1715,7 @@ static void __exit atmci_exit(void) | |||
1759 | platform_driver_unregister(&atmci_driver); | 1715 | platform_driver_unregister(&atmci_driver); |
1760 | } | 1716 | } |
1761 | 1717 | ||
1762 | module_init(atmci_init); | 1718 | late_initcall(atmci_init); /* try to load after dma driver when built-in */ |
1763 | module_exit(atmci_exit); | 1719 | module_exit(atmci_exit); |
1764 | 1720 | ||
1765 | MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver"); | 1721 | MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver"); |