aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorShashidhar Hiremath <shashidharh@vayavyalabs.com>2012-01-13 05:34:57 -0500
committerChris Ball <cjb@laptop.org>2012-03-25 19:33:44 -0400
commit62ca8034d940439490a450ae7e2b7702591e3192 (patch)
treeaa2bb114f123e0850a5ce6008c0e6188dbd5f2ca /drivers/mmc/host
parent356ac2cf066174aecc3380f82fabe8a01f046c3f (diff)
mmc: Support of PCI mode in the dw_mmc driver
Support of PCI mode for the dw_mmc driver. This Patch adds the support for the scenario where the Synopsys Designware IP is present on the PCI bus. The patch adds the minimal modifications necessary for the driver to work on PCI platform. Also added separate files for PCI and PLATFORM modes of operation. Signed-off-by: Shashidhar Hiremath <shashidharh@vayavyalabs.com> Acked-by: James Hogan <james.hogan@imgtec.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/Kconfig25
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c158
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c134
-rw-r--r--drivers/mmc/host/dw_mmc.c155
-rw-r--r--drivers/mmc/host/dw_mmc.h7
6 files changed, 379 insertions, 102 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 00fcbed1afd2..0c9b3b12652b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -533,6 +533,31 @@ config MMC_DW_IDMAC
533 Designware Mobile Storage IP block. This disables the external DMA 533 Designware Mobile Storage IP block. This disables the external DMA
534 interface. 534 interface.
535 535
536config MMC_DW_PLTFM
537 tristate "Synopsys Designware MCI Support as platform device"
538 depends on MMC_DW
539 default y
540 help
541 This selects the common helper functions support for Host Controller
542 Interface based platform driver. Please select this option if the IP
543 is present as a platform device. This is the common interface for the
544 Synopsys Designware IP.
545
546 If you have a controller with this interface, say Y or M here.
547
548 If unsure, say Y.
549
550config MMC_DW_PCI
551 tristate "Synopsys Designware MCI support on PCI bus"
552 depends on MMC_DW && PCI
553 help
554 This selects the PCI bus for the Synopsys Designware Mobile Storage IP.
555 Select this option if the IP is present on PCI platform.
556
557 If you have a controller with this interface, say Y or M here.
558
559 If unsure, say N.
560
536config MMC_SH_MMCIF 561config MMC_SH_MMCIF
537 tristate "SuperH Internal MMCIF support" 562 tristate "SuperH Internal MMCIF support"
538 depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) 563 depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE)
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 745f8fce2519..3e7e26d08073 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -39,6 +39,8 @@ obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
39obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o 39obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
40obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o 40obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
41obj-$(CONFIG_MMC_DW) += dw_mmc.o 41obj-$(CONFIG_MMC_DW) += dw_mmc.o
42obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o
43obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o
42obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o 44obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o
43obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o 45obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
44obj-$(CONFIG_MMC_VUB300) += vub300.o 46obj-$(CONFIG_MMC_VUB300) += vub300.o
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
new file mode 100644
index 000000000000..dc0d25a013e0
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -0,0 +1,158 @@
1/*
2 * Synopsys DesignWare Multimedia Card PCI Interface driver
3 *
4 * Copyright (C) 2012 Vayavya Labs Pvt. Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/io.h>
15#include <linux/irq.h>
16#include <linux/pci.h>
17#include <linux/slab.h>
18#include <linux/mmc/host.h>
19#include <linux/mmc/mmc.h>
20#include <linux/mmc/dw_mmc.h>
21#include "dw_mmc.h"
22
23#define PCI_BAR_NO 2
24#define COMPLETE_BAR 0
25#define SYNOPSYS_DW_MCI_VENDOR_ID 0x700
26#define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107
27/* Defining the Capabilities */
28#define DW_MCI_CAPABILITIES (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |\
29 MMC_CAP_SD_HIGHSPEED | MMC_CAP_8_BIT_DATA |\
30 MMC_CAP_SDIO_IRQ)
31
32static struct dw_mci_board pci_board_data = {
33 .num_slots = 1,
34 .caps = DW_MCI_CAPABILITIES,
35 .bus_hz = 33 * 1000 * 1000,
36 .detect_delay_ms = 200,
37 .fifo_depth = 32,
38};
39
40static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
41 const struct pci_device_id *entries)
42{
43 struct dw_mci *host;
44 int ret;
45
46 ret = pci_enable_device(pdev);
47 if (ret)
48 return ret;
49 if (pci_request_regions(pdev, "dw_mmc_pci")) {
50 ret = -ENODEV;
51 goto err_disable_dev;
52 }
53
54 host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
55 if (!host) {
56 ret = -ENOMEM;
57 goto err_release;
58 }
59
60 host->irq = pdev->irq;
61 host->irq_flags = IRQF_SHARED;
62 host->dev = pdev->dev;
63 host->pdata = &pci_board_data;
64
65 host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR);
66 if (!host->regs) {
67 ret = -EIO;
68 goto err_unmap;
69 }
70
71 pci_set_drvdata(pdev, host);
72 ret = dw_mci_probe(host);
73 if (ret)
74 goto err_probe_failed;
75 return ret;
76
77err_probe_failed:
78 pci_iounmap(pdev, host->regs);
79err_unmap:
80 kfree(host);
81err_release:
82 pci_release_regions(pdev);
83err_disable_dev:
84 pci_disable_device(pdev);
85 return ret;
86}
87
88static void __devexit dw_mci_pci_remove(struct pci_dev *pdev)
89{
90 struct dw_mci *host = pci_get_drvdata(pdev);
91
92 dw_mci_remove(host);
93 pci_set_drvdata(pdev, NULL);
94 pci_release_regions(pdev);
95 pci_iounmap(pdev, host->regs);
96 kfree(host);
97 pci_disable_device(pdev);
98}
99
100#ifdef CONFIG_PM_SLEEP
101static int dw_mci_pci_suspend(struct device *dev)
102{
103 int ret;
104 struct pci_dev *pdev = to_pci_dev(dev);
105 struct dw_mci *host = pci_get_drvdata(pdev);
106
107 ret = dw_mci_suspend(host);
108 return ret;
109}
110
111static int dw_mci_pci_resume(struct device *dev)
112{
113 int ret;
114 struct pci_dev *pdev = to_pci_dev(dev);
115 struct dw_mci *host = pci_get_drvdata(pdev);
116
117 ret = dw_mci_resume(host);
118 return ret;
119}
120#else
121#define dw_mci_pci_suspend NULL
122#define dw_mci_pci_resume NULL
123#endif /* CONFIG_PM_SLEEP */
124
125static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
126
127static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = {
128 { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
129 {}
130};
131MODULE_DEVICE_TABLE(pci, dw_mci_pci_id);
132
133static struct pci_driver dw_mci_pci_driver = {
134 .name = "dw_mmc_pci",
135 .id_table = dw_mci_pci_id,
136 .probe = dw_mci_pci_probe,
137 .remove = dw_mci_pci_remove,
138 .driver = {
139 .pm = &dw_mci_pci_pmops
140 },
141};
142
143static int __init dw_mci_init(void)
144{
145 return pci_register_driver(&dw_mci_pci_driver);
146}
147
148static void __exit dw_mci_exit(void)
149{
150 pci_unregister_driver(&dw_mci_pci_driver);
151}
152
153module_init(dw_mci_init);
154module_exit(dw_mci_exit);
155
156MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver");
157MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>");
158MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
new file mode 100644
index 000000000000..92ec3eb3aae7
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -0,0 +1,134 @@
1/*
2 * Synopsys DesignWare Multimedia Card Interface driver
3 *
4 * Copyright (C) 2009 NXP Semiconductors
5 * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/interrupt.h>
14#include <linux/module.h>
15#include <linux/io.h>
16#include <linux/irq.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include <linux/mmc/host.h>
20#include <linux/mmc/mmc.h>
21#include <linux/mmc/dw_mmc.h>
22#include "dw_mmc.h"
23
24static int dw_mci_pltfm_probe(struct platform_device *pdev)
25{
26 struct dw_mci *host;
27 struct resource *regs;
28 int ret;
29
30 host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
31 if (!host)
32 return -ENOMEM;
33
34 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
35 if (!regs) {
36 ret = -ENXIO;
37 goto err_free;
38 }
39
40 host->irq = platform_get_irq(pdev, 0);
41 if (host->irq < 0) {
42 ret = host->irq;
43 goto err_free;
44 }
45
46 host->dev = pdev->dev;
47 host->irq_flags = 0;
48 host->pdata = pdev->dev.platform_data;
49 ret = -ENOMEM;
50 host->regs = ioremap(regs->start, resource_size(regs));
51 if (!host->regs)
52 goto err_free;
53 platform_set_drvdata(pdev, host);
54 ret = dw_mci_probe(host);
55 if (ret)
56 goto err_out;
57 return ret;
58err_out:
59 iounmap(host->regs);
60err_free:
61 kfree(host);
62 return ret;
63}
64
65static int __exit dw_mci_pltfm_remove(struct platform_device *pdev)
66{
67 struct dw_mci *host = platform_get_drvdata(pdev);
68
69 platform_set_drvdata(pdev, NULL);
70 dw_mci_remove(host);
71 iounmap(host->regs);
72 kfree(host);
73 return 0;
74}
75
76#ifdef CONFIG_PM_SLEEP
77/*
78 * TODO: we should probably disable the clock to the card in the suspend path.
79 */
80static int dw_mci_pltfm_suspend(struct device *dev)
81{
82 int ret;
83 struct dw_mci *host = dev_get_drvdata(dev);
84
85 ret = dw_mci_suspend(host);
86 if (ret)
87 return ret;
88
89 return 0;
90}
91
92static int dw_mci_pltfm_resume(struct device *dev)
93{
94 int ret;
95 struct dw_mci *host = dev_get_drvdata(dev);
96
97 ret = dw_mci_resume(host);
98 if (ret)
99 return ret;
100
101 return 0;
102}
103#else
104#define dw_mci_pltfm_suspend NULL
105#define dw_mci_pltfm_resume NULL
106#endif /* CONFIG_PM_SLEEP */
107
108static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
109
110static struct platform_driver dw_mci_pltfm_driver = {
111 .remove = __exit_p(dw_mci_pltfm_remove),
112 .driver = {
113 .name = "dw_mmc",
114 .pm = &dw_mci_pltfm_pmops,
115 },
116};
117
118static int __init dw_mci_init(void)
119{
120 return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe);
121}
122
123static void __exit dw_mci_exit(void)
124{
125 platform_driver_unregister(&dw_mci_pltfm_driver);
126}
127
128module_init(dw_mci_init);
129module_exit(dw_mci_exit);
130
131MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
132MODULE_AUTHOR("NXP Semiconductor VietNam");
133MODULE_AUTHOR("Imagination Technologies Ltd");
134MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 1dfcdef452b9..987a26549711 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -268,7 +268,7 @@ static void dw_mci_start_command(struct dw_mci *host,
268 struct mmc_command *cmd, u32 cmd_flags) 268 struct mmc_command *cmd, u32 cmd_flags)
269{ 269{
270 host->cmd = cmd; 270 host->cmd = cmd;
271 dev_vdbg(&host->pdev->dev, 271 dev_vdbg(&host->dev,
272 "start command: ARGR=0x%08x CMDR=0x%08x\n", 272 "start command: ARGR=0x%08x CMDR=0x%08x\n",
273 cmd->arg, cmd_flags); 273 cmd->arg, cmd_flags);
274 274
@@ -301,7 +301,7 @@ static void dw_mci_dma_cleanup(struct dw_mci *host)
301 struct mmc_data *data = host->data; 301 struct mmc_data *data = host->data;
302 302
303 if (data) 303 if (data)
304 dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, 304 dma_unmap_sg(&host->dev, data->sg, data->sg_len,
305 ((data->flags & MMC_DATA_WRITE) 305 ((data->flags & MMC_DATA_WRITE)
306 ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); 306 ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
307} 307}
@@ -326,7 +326,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host)
326{ 326{
327 struct mmc_data *data = host->data; 327 struct mmc_data *data = host->data;
328 328
329 dev_vdbg(&host->pdev->dev, "DMA complete\n"); 329 dev_vdbg(&host->dev, "DMA complete\n");
330 330
331 host->dma_ops->cleanup(host); 331 host->dma_ops->cleanup(host);
332 332
@@ -462,10 +462,10 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
462 else 462 else
463 direction = DMA_TO_DEVICE; 463 direction = DMA_TO_DEVICE;
464 464
465 sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, 465 sg_len = dma_map_sg(&host->dev, data->sg, data->sg_len,
466 direction); 466 direction);
467 467
468 dev_vdbg(&host->pdev->dev, 468 dev_vdbg(&host->dev,
469 "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", 469 "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
470 (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, 470 (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
471 sg_len); 471 sg_len);
@@ -821,12 +821,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
821 slot = list_entry(host->queue.next, 821 slot = list_entry(host->queue.next,
822 struct dw_mci_slot, queue_node); 822 struct dw_mci_slot, queue_node);
823 list_del(&slot->queue_node); 823 list_del(&slot->queue_node);
824 dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n", 824 dev_vdbg(&host->dev, "list not empty: %s is next\n",
825 mmc_hostname(slot->mmc)); 825 mmc_hostname(slot->mmc));
826 host->state = STATE_SENDING_CMD; 826 host->state = STATE_SENDING_CMD;
827 dw_mci_start_request(host, slot); 827 dw_mci_start_request(host, slot);
828 } else { 828 } else {
829 dev_vdbg(&host->pdev->dev, "list empty\n"); 829 dev_vdbg(&host->dev, "list empty\n");
830 host->state = STATE_IDLE; 830 host->state = STATE_IDLE;
831 } 831 }
832 832
@@ -965,7 +965,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
965 data->bytes_xfered = 0; 965 data->bytes_xfered = 0;
966 data->error = -ETIMEDOUT; 966 data->error = -ETIMEDOUT;
967 } else { 967 } else {
968 dev_err(&host->pdev->dev, 968 dev_err(&host->dev,
969 "data FIFO error " 969 "data FIFO error "
970 "(status=%08x)\n", 970 "(status=%08x)\n",
971 status); 971 status);
@@ -1682,7 +1682,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1682 struct mmc_host *mmc; 1682 struct mmc_host *mmc;
1683 struct dw_mci_slot *slot; 1683 struct dw_mci_slot *slot;
1684 1684
1685 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev); 1685 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->dev);
1686 if (!mmc) 1686 if (!mmc)
1687 return -ENOMEM; 1687 return -ENOMEM;
1688 1688
@@ -1794,10 +1794,10 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
1794static void dw_mci_init_dma(struct dw_mci *host) 1794static void dw_mci_init_dma(struct dw_mci *host)
1795{ 1795{
1796 /* Alloc memory for sg translation */ 1796 /* Alloc memory for sg translation */
1797 host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, PAGE_SIZE, 1797 host->sg_cpu = dma_alloc_coherent(&host->dev, PAGE_SIZE,
1798 &host->sg_dma, GFP_KERNEL); 1798 &host->sg_dma, GFP_KERNEL);
1799 if (!host->sg_cpu) { 1799 if (!host->sg_cpu) {
1800 dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n", 1800 dev_err(&host->dev, "%s: could not alloc DMA memory\n",
1801 __func__); 1801 __func__);
1802 goto no_dma; 1802 goto no_dma;
1803 } 1803 }
@@ -1805,7 +1805,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
1805 /* Determine which DMA interface to use */ 1805 /* Determine which DMA interface to use */
1806#ifdef CONFIG_MMC_DW_IDMAC 1806#ifdef CONFIG_MMC_DW_IDMAC
1807 host->dma_ops = &dw_mci_idmac_ops; 1807 host->dma_ops = &dw_mci_idmac_ops;
1808 dev_info(&host->pdev->dev, "Using internal DMA controller.\n"); 1808 dev_info(&host->dev, "Using internal DMA controller.\n");
1809#endif 1809#endif
1810 1810
1811 if (!host->dma_ops) 1811 if (!host->dma_ops)
@@ -1813,12 +1813,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
1813 1813
1814 if (host->dma_ops->init) { 1814 if (host->dma_ops->init) {
1815 if (host->dma_ops->init(host)) { 1815 if (host->dma_ops->init(host)) {
1816 dev_err(&host->pdev->dev, "%s: Unable to initialize " 1816 dev_err(&host->dev, "%s: Unable to initialize "
1817 "DMA Controller.\n", __func__); 1817 "DMA Controller.\n", __func__);
1818 goto no_dma; 1818 goto no_dma;
1819 } 1819 }
1820 } else { 1820 } else {
1821 dev_err(&host->pdev->dev, "DMA initialization not found.\n"); 1821 dev_err(&host->dev, "DMA initialization not found.\n");
1822 goto no_dma; 1822 goto no_dma;
1823 } 1823 }
1824 1824
@@ -1826,7 +1826,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
1826 return; 1826 return;
1827 1827
1828no_dma: 1828no_dma:
1829 dev_info(&host->pdev->dev, "Using PIO mode.\n"); 1829 dev_info(&host->dev, "Using PIO mode.\n");
1830 host->use_dma = 0; 1830 host->use_dma = 0;
1831 return; 1831 return;
1832} 1832}
@@ -1852,61 +1852,37 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
1852 return false; 1852 return false;
1853} 1853}
1854 1854
1855static int dw_mci_probe(struct platform_device *pdev) 1855int dw_mci_probe(struct dw_mci *host)
1856{ 1856{
1857 struct dw_mci *host; 1857 int width, i, ret = 0;
1858 struct resource *regs;
1859 struct dw_mci_board *pdata;
1860 int irq, ret, i, width;
1861 u32 fifo_size; 1858 u32 fifo_size;
1862 1859
1863 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1860 if (!host->pdata || !host->pdata->init) {
1864 if (!regs) 1861 dev_err(&host->dev,
1865 return -ENXIO;
1866
1867 irq = platform_get_irq(pdev, 0);
1868 if (irq < 0)
1869 return irq;
1870
1871 host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
1872 if (!host)
1873 return -ENOMEM;
1874
1875 host->pdev = pdev;
1876 host->pdata = pdata = pdev->dev.platform_data;
1877 if (!pdata || !pdata->init) {
1878 dev_err(&pdev->dev,
1879 "Platform data must supply init function\n"); 1862 "Platform data must supply init function\n");
1880 ret = -ENODEV; 1863 return -ENODEV;
1881 goto err_freehost;
1882 } 1864 }
1883 1865
1884 if (!pdata->select_slot && pdata->num_slots > 1) { 1866 if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
1885 dev_err(&pdev->dev, 1867 dev_err(&host->dev,
1886 "Platform data must supply select_slot function\n"); 1868 "Platform data must supply select_slot function\n");
1887 ret = -ENODEV; 1869 return -ENODEV;
1888 goto err_freehost;
1889 } 1870 }
1890 1871
1891 if (!pdata->bus_hz) { 1872 if (!host->pdata->bus_hz) {
1892 dev_err(&pdev->dev, 1873 dev_err(&host->dev,
1893 "Platform data must supply bus speed\n"); 1874 "Platform data must supply bus speed\n");
1894 ret = -ENODEV; 1875 return -ENODEV;
1895 goto err_freehost;
1896 } 1876 }
1897 1877
1898 host->bus_hz = pdata->bus_hz; 1878 host->bus_hz = host->pdata->bus_hz;
1899 host->quirks = pdata->quirks; 1879 host->quirks = host->pdata->quirks;
1900 1880
1901 spin_lock_init(&host->lock); 1881 spin_lock_init(&host->lock);
1902 INIT_LIST_HEAD(&host->queue); 1882 INIT_LIST_HEAD(&host->queue);
1903 1883
1904 ret = -ENOMEM;
1905 host->regs = ioremap(regs->start, resource_size(regs));
1906 if (!host->regs)
1907 goto err_freehost;
1908 1884
1909 host->dma_ops = pdata->dma_ops; 1885 host->dma_ops = host->pdata->dma_ops;
1910 dw_mci_init_dma(host); 1886 dw_mci_init_dma(host);
1911 1887
1912 /* 1888 /*
@@ -1936,7 +1912,7 @@ static int dw_mci_probe(struct platform_device *pdev)
1936 } 1912 }
1937 1913
1938 /* Reset all blocks */ 1914 /* Reset all blocks */
1939 if (!mci_wait_reset(&pdev->dev, host)) { 1915 if (!mci_wait_reset(&host->dev, host)) {
1940 ret = -ENODEV; 1916 ret = -ENODEV;
1941 goto err_dmaunmap; 1917 goto err_dmaunmap;
1942 } 1918 }
@@ -1979,13 +1955,10 @@ static int dw_mci_probe(struct platform_device *pdev)
1979 if (!dw_mci_card_workqueue) 1955 if (!dw_mci_card_workqueue)
1980 goto err_dmaunmap; 1956 goto err_dmaunmap;
1981 INIT_WORK(&host->card_work, dw_mci_work_routine_card); 1957 INIT_WORK(&host->card_work, dw_mci_work_routine_card);
1982 1958 ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
1983 ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host);
1984 if (ret) 1959 if (ret)
1985 goto err_workqueue; 1960 goto err_workqueue;
1986 1961
1987 platform_set_drvdata(pdev, host);
1988
1989 if (host->pdata->num_slots) 1962 if (host->pdata->num_slots)
1990 host->num_slots = host->pdata->num_slots; 1963 host->num_slots = host->pdata->num_slots;
1991 else 1964 else
@@ -2005,7 +1978,7 @@ static int dw_mci_probe(struct platform_device *pdev)
2005 * Need to check the version-id and set data-offset for DATA register. 1978 * Need to check the version-id and set data-offset for DATA register.
2006 */ 1979 */
2007 host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); 1980 host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
2008 dev_info(&pdev->dev, "Version ID is %04x\n", host->verid); 1981 dev_info(&host->dev, "Version ID is %04x\n", host->verid);
2009 1982
2010 if (host->verid < DW_MMC_240A) 1983 if (host->verid < DW_MMC_240A)
2011 host->data_offset = DATA_OFFSET; 1984 host->data_offset = DATA_OFFSET;
@@ -2022,12 +1995,12 @@ static int dw_mci_probe(struct platform_device *pdev)
2022 DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); 1995 DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
2023 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ 1996 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
2024 1997
2025 dev_info(&pdev->dev, "DW MMC controller at irq %d, " 1998 dev_info(&host->dev, "DW MMC controller at irq %d, "
2026 "%d bit host data width, " 1999 "%d bit host data width, "
2027 "%u deep fifo\n", 2000 "%u deep fifo\n",
2028 irq, width, fifo_size); 2001 host->irq, width, fifo_size);
2029 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) 2002 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
2030 dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n"); 2003 dev_info(&host->dev, "Internal DMAC interrupt fix enabled.\n");
2031 2004
2032 return 0; 2005 return 0;
2033 2006
@@ -2038,7 +2011,7 @@ err_init_slot:
2038 dw_mci_cleanup_slot(host->slot[i], i); 2011 dw_mci_cleanup_slot(host->slot[i], i);
2039 i--; 2012 i--;
2040 } 2013 }
2041 free_irq(irq, host); 2014 free_irq(host->irq, host);
2042 2015
2043err_workqueue: 2016err_workqueue:
2044 destroy_workqueue(dw_mci_card_workqueue); 2017 destroy_workqueue(dw_mci_card_workqueue);
@@ -2046,33 +2019,26 @@ err_workqueue:
2046err_dmaunmap: 2019err_dmaunmap:
2047 if (host->use_dma && host->dma_ops->exit) 2020 if (host->use_dma && host->dma_ops->exit)
2048 host->dma_ops->exit(host); 2021 host->dma_ops->exit(host);
2049 dma_free_coherent(&host->pdev->dev, PAGE_SIZE, 2022 dma_free_coherent(&host->dev, PAGE_SIZE,
2050 host->sg_cpu, host->sg_dma); 2023 host->sg_cpu, host->sg_dma);
2051 iounmap(host->regs);
2052 2024
2053 if (host->vmmc) { 2025 if (host->vmmc) {
2054 regulator_disable(host->vmmc); 2026 regulator_disable(host->vmmc);
2055 regulator_put(host->vmmc); 2027 regulator_put(host->vmmc);
2056 } 2028 }
2057
2058
2059err_freehost:
2060 kfree(host);
2061 return ret; 2029 return ret;
2062} 2030}
2031EXPORT_SYMBOL(dw_mci_probe);
2063 2032
2064static int __exit dw_mci_remove(struct platform_device *pdev) 2033void dw_mci_remove(struct dw_mci *host)
2065{ 2034{
2066 struct dw_mci *host = platform_get_drvdata(pdev);
2067 int i; 2035 int i;
2068 2036
2069 mci_writel(host, RINTSTS, 0xFFFFFFFF); 2037 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2070 mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ 2038 mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
2071 2039
2072 platform_set_drvdata(pdev, NULL);
2073
2074 for (i = 0; i < host->num_slots; i++) { 2040 for (i = 0; i < host->num_slots; i++) {
2075 dev_dbg(&pdev->dev, "remove slot %d\n", i); 2041 dev_dbg(&host->dev, "remove slot %d\n", i);
2076 if (host->slot[i]) 2042 if (host->slot[i])
2077 dw_mci_cleanup_slot(host->slot[i], i); 2043 dw_mci_cleanup_slot(host->slot[i], i);
2078 } 2044 }
@@ -2081,9 +2047,9 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
2081 mci_writel(host, CLKENA, 0); 2047 mci_writel(host, CLKENA, 0);
2082 mci_writel(host, CLKSRC, 0); 2048 mci_writel(host, CLKSRC, 0);
2083 2049
2084 free_irq(platform_get_irq(pdev, 0), host); 2050 free_irq(host->irq, host);
2085 destroy_workqueue(dw_mci_card_workqueue); 2051 destroy_workqueue(dw_mci_card_workqueue);
2086 dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); 2052 dma_free_coherent(&host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
2087 2053
2088 if (host->use_dma && host->dma_ops->exit) 2054 if (host->use_dma && host->dma_ops->exit)
2089 host->dma_ops->exit(host); 2055 host->dma_ops->exit(host);
@@ -2093,20 +2059,18 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
2093 regulator_put(host->vmmc); 2059 regulator_put(host->vmmc);
2094 } 2060 }
2095 2061
2096 iounmap(host->regs);
2097
2098 kfree(host);
2099 return 0;
2100} 2062}
2063EXPORT_SYMBOL(dw_mci_remove);
2064
2065
2101 2066
2102#ifdef CONFIG_PM_SLEEP 2067#ifdef CONFIG_PM_SLEEP
2103/* 2068/*
2104 * TODO: we should probably disable the clock to the card in the suspend path. 2069 * TODO: we should probably disable the clock to the card in the suspend path.
2105 */ 2070 */
2106static int dw_mci_suspend(struct device *dev) 2071int dw_mci_suspend(struct dw_mci *host)
2107{ 2072{
2108 int i, ret; 2073 int i, ret = 0;
2109 struct dw_mci *host = dev_get_drvdata(dev);
2110 2074
2111 for (i = 0; i < host->num_slots; i++) { 2075 for (i = 0; i < host->num_slots; i++) {
2112 struct dw_mci_slot *slot = host->slot[i]; 2076 struct dw_mci_slot *slot = host->slot[i];
@@ -2128,11 +2092,11 @@ static int dw_mci_suspend(struct device *dev)
2128 2092
2129 return 0; 2093 return 0;
2130} 2094}
2095EXPORT_SYMBOL(dw_mci_suspend);
2131 2096
2132static int dw_mci_resume(struct device *dev) 2097int dw_mci_resume(struct dw_mci *host)
2133{ 2098{
2134 int i, ret; 2099 int i, ret;
2135 struct dw_mci *host = dev_get_drvdata(dev);
2136 2100
2137 if (host->vmmc) 2101 if (host->vmmc)
2138 regulator_enable(host->vmmc); 2102 regulator_enable(host->vmmc);
@@ -2140,7 +2104,7 @@ static int dw_mci_resume(struct device *dev)
2140 if (host->dma_ops->init) 2104 if (host->dma_ops->init)
2141 host->dma_ops->init(host); 2105 host->dma_ops->init(host);
2142 2106
2143 if (!mci_wait_reset(dev, host)) { 2107 if (!mci_wait_reset(&host->dev, host)) {
2144 ret = -ENODEV; 2108 ret = -ENODEV;
2145 return ret; 2109 return ret;
2146 } 2110 }
@@ -2162,32 +2126,19 @@ static int dw_mci_resume(struct device *dev)
2162 if (ret < 0) 2126 if (ret < 0)
2163 return ret; 2127 return ret;
2164 } 2128 }
2165
2166 return 0; 2129 return 0;
2167} 2130}
2168#else 2131EXPORT_SYMBOL(dw_mci_resume);
2169#define dw_mci_suspend NULL
2170#define dw_mci_resume NULL
2171#endif /* CONFIG_PM_SLEEP */ 2132#endif /* CONFIG_PM_SLEEP */
2172 2133
2173static SIMPLE_DEV_PM_OPS(dw_mci_pmops, dw_mci_suspend, dw_mci_resume);
2174
2175static struct platform_driver dw_mci_driver = {
2176 .remove = __exit_p(dw_mci_remove),
2177 .driver = {
2178 .name = "dw_mmc",
2179 .pm = &dw_mci_pmops,
2180 },
2181};
2182
2183static int __init dw_mci_init(void) 2134static int __init dw_mci_init(void)
2184{ 2135{
2185 return platform_driver_probe(&dw_mci_driver, dw_mci_probe); 2136 printk(KERN_INFO "Synopsys Designware Multimedia Card Interface Driver");
2137 return 0;
2186} 2138}
2187 2139
2188static void __exit dw_mci_exit(void) 2140static void __exit dw_mci_exit(void)
2189{ 2141{
2190 platform_driver_unregister(&dw_mci_driver);
2191} 2142}
2192 2143
2193module_init(dw_mci_init); 2144module_init(dw_mci_init);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index df392a1143f2..15c27e17c23f 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -175,4 +175,11 @@
175 (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) 175 (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
176#endif 176#endif
177 177
178extern int dw_mci_probe(struct dw_mci *host);
179extern void dw_mci_remove(struct dw_mci *host);
180#ifdef CONFIG_PM
181extern int dw_mci_suspend(struct dw_mci *host);
182extern int dw_mci_resume(struct dw_mci *host);
183#endif
184
178#endif /* _DW_MMC_H_ */ 185#endif /* _DW_MMC_H_ */