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/mmc/host/atmel-mci.c | |
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/mmc/host/atmel-mci.c')
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 98 |
1 files changed, 27 insertions, 71 deletions
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"); |