aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-at91/include/mach/atmel-mci.h24
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c18
-rw-r--r--arch/avr32/mach-at32ap/include/mach/atmel-mci.h24
-rw-r--r--drivers/mmc/host/atmel-mci.c56
-rw-r--r--include/linux/atmel-mci.h4
5 files changed, 98 insertions, 28 deletions
diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h
new file mode 100644
index 000000000000..998cb0c07135
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/atmel-mci.h
@@ -0,0 +1,24 @@
1#ifndef __MACH_ATMEL_MCI_H
2#define __MACH_ATMEL_MCI_H
3
4#include <mach/at_hdmac.h>
5
6/**
7 * struct mci_dma_data - DMA data for MCI interface
8 */
9struct mci_dma_data {
10 struct at_dma_slave sdata;
11};
12
13/* accessor macros */
14#define slave_data_ptr(s) (&(s)->sdata)
15#define find_slave_dev(s) ((s)->sdata.dma_dev)
16
17#define setup_dma_addr(s, t, r) do { \
18 if (s) { \
19 (s)->sdata.tx_reg = (t); \
20 (s)->sdata.rx_reg = (r); \
21 } \
22} while (0)
23
24#endif /* __MACH_ATMEL_MCI_H */
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index eb9d4dc2e86d..b40ff39e0ac8 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -15,6 +15,8 @@
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16#include <linux/spi/spi.h> 16#include <linux/spi/spi.h>
17#include <linux/usb/atmel_usba_udc.h> 17#include <linux/usb/atmel_usba_udc.h>
18
19#include <mach/atmel-mci.h>
18#include <linux/atmel-mci.h> 20#include <linux/atmel-mci.h>
19 21
20#include <asm/io.h> 22#include <asm/io.h>
@@ -1320,7 +1322,7 @@ struct platform_device *__init
1320at32_add_device_mci(unsigned int id, struct mci_platform_data *data) 1322at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1321{ 1323{
1322 struct platform_device *pdev; 1324 struct platform_device *pdev;
1323 struct dw_dma_slave *dws = &data->dma_slave; 1325 struct mci_dma_slave *slave;
1324 u32 pioa_mask; 1326 u32 pioa_mask;
1325 u32 piob_mask; 1327 u32 piob_mask;
1326 1328
@@ -1339,13 +1341,17 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1339 ARRAY_SIZE(atmel_mci0_resource))) 1341 ARRAY_SIZE(atmel_mci0_resource)))
1340 goto fail; 1342 goto fail;
1341 1343
1342 dws->dma_dev = &dw_dmac0_device.dev; 1344 slave = kzalloc(sizeof(struct mci_dma_slave), GFP_KERNEL);
1343 dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; 1345
1344 dws->cfg_hi = (DWC_CFGH_SRC_PER(0) 1346 slave->sdata.dma_dev = &dw_dmac0_device.dev;
1347 slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
1348 slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0)
1345 | DWC_CFGH_DST_PER(1)); 1349 | DWC_CFGH_DST_PER(1));
1346 dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL 1350 slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL
1347 | DWC_CFGL_HS_SRC_POL); 1351 | DWC_CFGL_HS_SRC_POL);
1348 1352
1353 data->dma_slave = slave;
1354
1349 if (platform_device_add_data(pdev, data, 1355 if (platform_device_add_data(pdev, data,
1350 sizeof(struct mci_platform_data))) 1356 sizeof(struct mci_platform_data)))
1351 goto fail; 1357 goto fail;
@@ -1411,6 +1417,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1411 return pdev; 1417 return pdev;
1412 1418
1413fail: 1419fail:
1420 data->dma_slave = NULL;
1421 kfree(slave);
1414 platform_device_put(pdev); 1422 platform_device_put(pdev);
1415 return NULL; 1423 return NULL;
1416} 1424}
diff --git a/arch/avr32/mach-at32ap/include/mach/atmel-mci.h b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h
new file mode 100644
index 000000000000..a9b38967f703
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h
@@ -0,0 +1,24 @@
1#ifndef __MACH_ATMEL_MCI_H
2#define __MACH_ATMEL_MCI_H
3
4#include <linux/dw_dmac.h>
5
6/**
7 * struct mci_dma_data - DMA data for MCI interface
8 */
9struct mci_dma_data {
10 struct dw_dma_slave sdata;
11};
12
13/* accessor macros */
14#define slave_data_ptr(s) (&(s)->sdata)
15#define find_slave_dev(s) ((s)->sdata.dma_dev)
16
17#define setup_dma_addr(s, t, r) do { \
18 if (s) { \
19 (s)->sdata.tx_reg = (t); \
20 (s)->sdata.rx_reg = (r); \
21 } \
22} while (0)
23
24#endif /* __MACH_ATMEL_MCI_H */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index fc25586b7ee1..ba8b219d44c1 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -25,6 +25,8 @@
25#include <linux/stat.h> 25#include <linux/stat.h>
26 26
27#include <linux/mmc/host.h> 27#include <linux/mmc/host.h>
28
29#include <mach/atmel-mci.h>
28#include <linux/atmel-mci.h> 30#include <linux/atmel-mci.h>
29 31
30#include <asm/io.h> 32#include <asm/io.h>
@@ -1584,14 +1586,43 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
1584#ifdef CONFIG_MMC_ATMELMCI_DMA 1586#ifdef CONFIG_MMC_ATMELMCI_DMA
1585static bool filter(struct dma_chan *chan, void *slave) 1587static bool filter(struct dma_chan *chan, void *slave)
1586{ 1588{
1587 struct dw_dma_slave *dws = slave; 1589 struct mci_dma_data *sl = slave;
1588 1590
1589 if (dws->dma_dev == chan->device->dev) { 1591 if (sl && find_slave_dev(sl) == chan->device->dev) {
1590 chan->private = dws; 1592 chan->private = slave_data_ptr(sl);
1591 return true; 1593 return true;
1592 } else 1594 } else {
1593 return false; 1595 return false;
1596 }
1594} 1597}
1598
1599static void atmci_configure_dma(struct atmel_mci *host)
1600{
1601 struct mci_platform_data *pdata;
1602
1603 if (host == NULL)
1604 return;
1605
1606 pdata = host->pdev->dev.platform_data;
1607
1608 if (pdata && find_slave_dev(pdata->dma_slave)) {
1609 dma_cap_mask_t mask;
1610
1611 setup_dma_addr(pdata->dma_slave,
1612 host->mapbase + MCI_TDR,
1613 host->mapbase + MCI_RDR);
1614
1615 /* Try to grab a DMA channel */
1616 dma_cap_zero(mask);
1617 dma_cap_set(DMA_SLAVE, mask);
1618 host->dma.chan =
1619 dma_request_channel(mask, filter, pdata->dma_slave);
1620 }
1621 if (!host->dma.chan)
1622 dev_notice(&host->pdev->dev, "DMA not available, using PIO\n");
1623}
1624#else
1625static void atmci_configure_dma(struct atmel_mci *host) {}
1595#endif 1626#endif
1596 1627
1597static int __init atmci_probe(struct platform_device *pdev) 1628static int __init atmci_probe(struct platform_device *pdev)
@@ -1645,22 +1676,7 @@ static int __init atmci_probe(struct platform_device *pdev)
1645 if (ret) 1676 if (ret)
1646 goto err_request_irq; 1677 goto err_request_irq;
1647 1678
1648#ifdef CONFIG_MMC_ATMELMCI_DMA 1679 atmci_configure_dma(host);
1649 if (pdata->dma_slave.dma_dev) {
1650 struct dw_dma_slave *dws = &pdata->dma_slave;
1651 dma_cap_mask_t mask;
1652
1653 dws->tx_reg = regs->start + MCI_TDR;
1654 dws->rx_reg = regs->start + MCI_RDR;
1655
1656 /* Try to grab a DMA channel */
1657 dma_cap_zero(mask);
1658 dma_cap_set(DMA_SLAVE, mask);
1659 host->dma.chan = dma_request_channel(mask, filter, dws);
1660 }
1661 if (!host->dma.chan)
1662 dev_notice(&pdev->dev, "DMA not available, using PIO\n");
1663#endif /* CONFIG_MMC_ATMELMCI_DMA */
1664 1680
1665 platform_set_drvdata(pdev, host); 1681 platform_set_drvdata(pdev, host);
1666 1682
diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h
index 57b1846a3c87..3e09b345f4d6 100644
--- a/include/linux/atmel-mci.h
+++ b/include/linux/atmel-mci.h
@@ -3,8 +3,6 @@
3 3
4#define ATMEL_MCI_MAX_NR_SLOTS 2 4#define ATMEL_MCI_MAX_NR_SLOTS 2
5 5
6#include <linux/dw_dmac.h>
7
8/** 6/**
9 * struct mci_slot_pdata - board-specific per-slot configuration 7 * struct mci_slot_pdata - board-specific per-slot configuration
10 * @bus_width: Number of data lines wired up the slot 8 * @bus_width: Number of data lines wired up the slot
@@ -34,7 +32,7 @@ struct mci_slot_pdata {
34 * @slot: Per-slot configuration data. 32 * @slot: Per-slot configuration data.
35 */ 33 */
36struct mci_platform_data { 34struct mci_platform_data {
37 struct dw_dma_slave dma_slave; 35 struct mci_dma_data *dma_slave;
38 struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; 36 struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS];
39}; 37};
40 38