aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-pltfm.c
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-05-27 11:48:12 -0400
committerChris Ball <cjb@laptop.org>2011-07-20 17:16:06 -0400
commit85d6509dc8ca24b2b652863ef7a75622ddca17d6 (patch)
treee564c2d4f80478027abc96cb7d87da952b38409e /drivers/mmc/host/sdhci-pltfm.c
parent3a5c3743f15f27237ab025736a981e2d0c9fdfed (diff)
mmc: sdhci: make sdhci-pltfm device drivers self registered
The patch turns the common stuff in sdhci-pltfm.c into functions, and add device drivers their own .probe and .remove which in turn call into the common functions, so that those sdhci-pltfm device drivers register itself and keep all device specific things away from common sdhci-pltfm file. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Reviewed-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci-pltfm.c')
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c157
1 files changed, 37 insertions, 120 deletions
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index dbab0407f4b6..8ccf25666201 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -22,48 +22,22 @@
22 * Inspired by sdhci-pci.c, by Pierre Ossman 22 * Inspired by sdhci-pci.c, by Pierre Ossman
23 */ 23 */
24 24
25#include <linux/delay.h> 25#include <linux/err.h>
26#include <linux/highmem.h>
27#include <linux/mod_devicetable.h>
28#include <linux/platform_device.h>
29
30#include <linux/mmc/host.h>
31
32#include <linux/io.h>
33#include <linux/mmc/sdhci-pltfm.h>
34 26
35#include "sdhci.h" 27#include "sdhci.h"
36#include "sdhci-pltfm.h" 28#include "sdhci-pltfm.h"
37 29
38/*****************************************************************************\
39 * *
40 * SDHCI core callbacks *
41 * *
42\*****************************************************************************/
43
44static struct sdhci_ops sdhci_pltfm_ops = { 30static struct sdhci_ops sdhci_pltfm_ops = {
45}; 31};
46 32
47/*****************************************************************************\ 33struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
48 * * 34 struct sdhci_pltfm_data *pdata)
49 * Device probing/removal *
50 * *
51\*****************************************************************************/
52
53static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
54{ 35{
55 const struct platform_device_id *platid = platform_get_device_id(pdev);
56 struct sdhci_pltfm_data *pdata;
57 struct sdhci_host *host; 36 struct sdhci_host *host;
58 struct sdhci_pltfm_host *pltfm_host; 37 struct sdhci_pltfm_host *pltfm_host;
59 struct resource *iomem; 38 struct resource *iomem;
60 int ret; 39 int ret;
61 40
62 if (platid && platid->driver_data)
63 pdata = (void *)platid->driver_data;
64 else
65 pdata = pdev->dev.platform_data;
66
67 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 41 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
68 if (!iomem) { 42 if (!iomem) {
69 ret = -ENOMEM; 43 ret = -ENOMEM;
@@ -71,8 +45,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
71 } 45 }
72 46
73 if (resource_size(iomem) < 0x100) 47 if (resource_size(iomem) < 0x100)
74 dev_err(&pdev->dev, "Invalid iomem size. You may " 48 dev_err(&pdev->dev, "Invalid iomem size!\n");
75 "experience problems.\n");
76 49
77 /* Some PCI-based MFD need the parent here */ 50 /* Some PCI-based MFD need the parent here */
78 if (pdev->dev.parent != &platform_bus) 51 if (pdev->dev.parent != &platform_bus)
@@ -87,7 +60,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
87 60
88 pltfm_host = sdhci_priv(host); 61 pltfm_host = sdhci_priv(host);
89 62
90 host->hw_name = "platform"; 63 host->hw_name = dev_name(&pdev->dev);
91 if (pdata && pdata->ops) 64 if (pdata && pdata->ops)
92 host->ops = pdata->ops; 65 host->ops = pdata->ops;
93 else 66 else
@@ -110,126 +83,70 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
110 goto err_remap; 83 goto err_remap;
111 } 84 }
112 85
113 if (pdata && pdata->init) {
114 ret = pdata->init(host, pdata);
115 if (ret)
116 goto err_plat_init;
117 }
118
119 ret = sdhci_add_host(host);
120 if (ret)
121 goto err_add_host;
122
123 platform_set_drvdata(pdev, host); 86 platform_set_drvdata(pdev, host);
124 87
125 return 0; 88 return host;
126 89
127err_add_host:
128 if (pdata && pdata->exit)
129 pdata->exit(host);
130err_plat_init:
131 iounmap(host->ioaddr);
132err_remap: 90err_remap:
133 release_mem_region(iomem->start, resource_size(iomem)); 91 release_mem_region(iomem->start, resource_size(iomem));
134err_request: 92err_request:
135 sdhci_free_host(host); 93 sdhci_free_host(host);
136err: 94err:
137 printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret); 95 dev_err(&pdev->dev, "%s failed %d\n", __func__, ret);
138 return ret; 96 return ERR_PTR(ret);
139} 97}
140 98
141static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) 99void sdhci_pltfm_free(struct platform_device *pdev)
142{ 100{
143 struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
144 struct sdhci_host *host = platform_get_drvdata(pdev); 101 struct sdhci_host *host = platform_get_drvdata(pdev);
145 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 102 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
146 int dead;
147 u32 scratch;
148
149 dead = 0;
150 scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
151 if (scratch == (u32)-1)
152 dead = 1;
153 103
154 sdhci_remove_host(host, dead);
155 if (pdata && pdata->exit)
156 pdata->exit(host);
157 iounmap(host->ioaddr); 104 iounmap(host->ioaddr);
158 release_mem_region(iomem->start, resource_size(iomem)); 105 release_mem_region(iomem->start, resource_size(iomem));
159 sdhci_free_host(host); 106 sdhci_free_host(host);
160 platform_set_drvdata(pdev, NULL); 107 platform_set_drvdata(pdev, NULL);
108}
161 109
162 return 0; 110int sdhci_pltfm_register(struct platform_device *pdev,
111 struct sdhci_pltfm_data *pdata)
112{
113 struct sdhci_host *host;
114 int ret = 0;
115
116 host = sdhci_pltfm_init(pdev, pdata);
117 if (IS_ERR(host))
118 return PTR_ERR(host);
119
120 ret = sdhci_add_host(host);
121 if (ret)
122 sdhci_pltfm_free(pdev);
123
124 return ret;
163} 125}
164 126
165static const struct platform_device_id sdhci_pltfm_ids[] = { 127int sdhci_pltfm_unregister(struct platform_device *pdev)
166 { "sdhci", }, 128{
167#ifdef CONFIG_MMC_SDHCI_CNS3XXX 129 struct sdhci_host *host = platform_get_drvdata(pdev);
168 { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata }, 130 int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
169#endif 131
170#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX 132 sdhci_remove_host(host, dead);
171 { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata }, 133 sdhci_pltfm_free(pdev);
172#endif 134
173#ifdef CONFIG_MMC_SDHCI_DOVE 135 return 0;
174 { "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata }, 136}
175#endif
176#ifdef CONFIG_MMC_SDHCI_TEGRA
177 { "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata },
178#endif
179 { },
180};
181MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);
182 137
183#ifdef CONFIG_PM 138#ifdef CONFIG_PM
184static int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state) 139int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
185{ 140{
186 struct sdhci_host *host = platform_get_drvdata(dev); 141 struct sdhci_host *host = platform_get_drvdata(dev);
187 142
188 return sdhci_suspend_host(host, state); 143 return sdhci_suspend_host(host, state);
189} 144}
190 145
191static int sdhci_pltfm_resume(struct platform_device *dev) 146int sdhci_pltfm_resume(struct platform_device *dev)
192{ 147{
193 struct sdhci_host *host = platform_get_drvdata(dev); 148 struct sdhci_host *host = platform_get_drvdata(dev);
194 149
195 return sdhci_resume_host(host); 150 return sdhci_resume_host(host);
196} 151}
197#else
198#define sdhci_pltfm_suspend NULL
199#define sdhci_pltfm_resume NULL
200#endif /* CONFIG_PM */ 152#endif /* CONFIG_PM */
201
202static struct platform_driver sdhci_pltfm_driver = {
203 .driver = {
204 .name = "sdhci",
205 .owner = THIS_MODULE,
206 },
207 .probe = sdhci_pltfm_probe,
208 .remove = __devexit_p(sdhci_pltfm_remove),
209 .id_table = sdhci_pltfm_ids,
210 .suspend = sdhci_pltfm_suspend,
211 .resume = sdhci_pltfm_resume,
212};
213
214/*****************************************************************************\
215 * *
216 * Driver init/exit *
217 * *
218\*****************************************************************************/
219
220static int __init sdhci_drv_init(void)
221{
222 return platform_driver_register(&sdhci_pltfm_driver);
223}
224
225static void __exit sdhci_drv_exit(void)
226{
227 platform_driver_unregister(&sdhci_pltfm_driver);
228}
229
230module_init(sdhci_drv_init);
231module_exit(sdhci_drv_exit);
232
233MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
234MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
235MODULE_LICENSE("GPL v2");