diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2009-12-14 21:01:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:53:35 -0500 |
commit | 2635d1ba711560d521f6218c585a3e0401f566e1 (patch) | |
tree | 11c8f09f15cd2f19bfd6f2d2d9b2cac67544179f | |
parent | bd68e0838fe85794b06892054772fa013a8d1986 (diff) |
atmel-mci: change use of dma slave interface
Allow the use of another DMA controller driver in atmel-mci sd/mmc driver.
This adds a generic dma_slave pointer to the mci platform structure where
we can store DMA controller information. In atmel-mci we use information
provided by this structure to initialize the driver (with new helper
functions that are architecture dependant).
This also adds at32/avr32 chip modifications to cope with this new access
method.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/arm/mach-at91/include/mach/atmel-mci.h | 24 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 18 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/include/mach/atmel-mci.h | 24 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 56 | ||||
-rw-r--r-- | include/linux/atmel-mci.h | 4 |
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 | */ | ||
9 | struct 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 | |||
1320 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | 1322 | at32_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 | ||
1413 | fail: | 1419 | fail: |
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 | */ | ||
9 | struct 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 |
1585 | static bool filter(struct dma_chan *chan, void *slave) | 1587 | static 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 | |||
1599 | static 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 | ||
1625 | static void atmci_configure_dma(struct atmel_mci *host) {} | ||
1595 | #endif | 1626 | #endif |
1596 | 1627 | ||
1597 | static int __init atmci_probe(struct platform_device *pdev) | 1628 | static 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 | */ |
36 | struct mci_platform_data { | 34 | struct 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 | ||