aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-esdhc-imx.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-esdhc-imx.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-esdhc-imx.c')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c113
1 files changed, 82 insertions, 31 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a19967d0bfc4..e27ccbb5285b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -191,16 +191,6 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
191 return clk_get_rate(pltfm_host->clk) / 256 / 16; 191 return clk_get_rate(pltfm_host->clk) / 256 / 16;
192} 192}
193 193
194static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
195{
196 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
197
198 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
199 return gpio_get_value(boarddata->wp_gpio);
200 else
201 return -ENOSYS;
202}
203
204static struct sdhci_ops sdhci_esdhc_ops = { 194static struct sdhci_ops sdhci_esdhc_ops = {
205 .read_l = esdhc_readl_le, 195 .read_l = esdhc_readl_le,
206 .read_w = esdhc_readw_le, 196 .read_w = esdhc_readw_le,
@@ -212,6 +202,24 @@ static struct sdhci_ops sdhci_esdhc_ops = {
212 .get_min_clock = esdhc_pltfm_get_min_clock, 202 .get_min_clock = esdhc_pltfm_get_min_clock,
213}; 203};
214 204
205static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
206 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
207 | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
208 /* ADMA has issues. Might be fixable */
209 .ops = &sdhci_esdhc_ops,
210};
211
212static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
213{
214 struct esdhc_platform_data *boarddata =
215 host->mmc->parent->platform_data;
216
217 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
218 return gpio_get_value(boarddata->wp_gpio);
219 else
220 return -ENOSYS;
221}
222
215static irqreturn_t cd_irq(int irq, void *data) 223static irqreturn_t cd_irq(int irq, void *data)
216{ 224{
217 struct sdhci_host *sdhost = (struct sdhci_host *)data; 225 struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -220,30 +228,35 @@ static irqreturn_t cd_irq(int irq, void *data)
220 return IRQ_HANDLED; 228 return IRQ_HANDLED;
221}; 229};
222 230
223static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata) 231static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
224{ 232{
225 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 233 struct sdhci_pltfm_host *pltfm_host;
226 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; 234 struct sdhci_host *host;
235 struct esdhc_platform_data *boarddata;
227 struct clk *clk; 236 struct clk *clk;
228 int err; 237 int err;
229 struct pltfm_imx_data *imx_data; 238 struct pltfm_imx_data *imx_data;
230 239
240 host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
241 if (IS_ERR(host))
242 return PTR_ERR(host);
243
244 pltfm_host = sdhci_priv(host);
245
246 imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
247 if (!imx_data)
248 return -ENOMEM;
249 pltfm_host->priv = imx_data;
250
231 clk = clk_get(mmc_dev(host->mmc), NULL); 251 clk = clk_get(mmc_dev(host->mmc), NULL);
232 if (IS_ERR(clk)) { 252 if (IS_ERR(clk)) {
233 dev_err(mmc_dev(host->mmc), "clk err\n"); 253 dev_err(mmc_dev(host->mmc), "clk err\n");
234 return PTR_ERR(clk); 254 err = PTR_ERR(clk);
255 goto err_clk_get;
235 } 256 }
236 clk_enable(clk); 257 clk_enable(clk);
237 pltfm_host->clk = clk; 258 pltfm_host->clk = clk;
238 259
239 imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
240 if (!imx_data) {
241 clk_disable(pltfm_host->clk);
242 clk_put(pltfm_host->clk);
243 return -ENOMEM;
244 }
245 pltfm_host->priv = imx_data;
246
247 if (!cpu_is_mx25()) 260 if (!cpu_is_mx25())
248 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 261 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
249 262
@@ -257,6 +270,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
257 if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51())) 270 if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
258 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; 271 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
259 272
273 boarddata = host->mmc->parent->platform_data;
260 if (boarddata) { 274 if (boarddata) {
261 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP"); 275 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
262 if (err) { 276 if (err) {
@@ -289,6 +303,10 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
289 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 303 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
290 } 304 }
291 305
306 err = sdhci_add_host(host);
307 if (err)
308 goto err_add_host;
309
292 return 0; 310 return 0;
293 311
294 no_card_detect_irq: 312 no_card_detect_irq:
@@ -297,14 +315,23 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
297 boarddata->cd_gpio = err; 315 boarddata->cd_gpio = err;
298 not_supported: 316 not_supported:
299 kfree(imx_data); 317 kfree(imx_data);
300 return 0; 318 err_add_host:
319 clk_disable(pltfm_host->clk);
320 clk_put(pltfm_host->clk);
321 err_clk_get:
322 sdhci_pltfm_free(pdev);
323 return err;
301} 324}
302 325
303static void esdhc_pltfm_exit(struct sdhci_host *host) 326static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
304{ 327{
328 struct sdhci_host *host = platform_get_drvdata(pdev);
305 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 329 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
306 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; 330 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
307 struct pltfm_imx_data *imx_data = pltfm_host->priv; 331 struct pltfm_imx_data *imx_data = pltfm_host->priv;
332 int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
333
334 sdhci_remove_host(host, dead);
308 335
309 if (boarddata && gpio_is_valid(boarddata->wp_gpio)) 336 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
310 gpio_free(boarddata->wp_gpio); 337 gpio_free(boarddata->wp_gpio);
@@ -319,13 +346,37 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
319 clk_disable(pltfm_host->clk); 346 clk_disable(pltfm_host->clk);
320 clk_put(pltfm_host->clk); 347 clk_put(pltfm_host->clk);
321 kfree(imx_data); 348 kfree(imx_data);
349
350 sdhci_pltfm_free(pdev);
351
352 return 0;
322} 353}
323 354
324struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { 355static struct platform_driver sdhci_esdhc_imx_driver = {
325 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA 356 .driver = {
326 | SDHCI_QUIRK_BROKEN_CARD_DETECTION, 357 .name = "sdhci-esdhc-imx",
327 /* ADMA has issues. Might be fixable */ 358 .owner = THIS_MODULE,
328 .ops = &sdhci_esdhc_ops, 359 },
329 .init = esdhc_pltfm_init, 360 .probe = sdhci_esdhc_imx_probe,
330 .exit = esdhc_pltfm_exit, 361 .remove = __devexit_p(sdhci_esdhc_imx_remove),
362#ifdef CONFIG_PM
363 .suspend = sdhci_pltfm_suspend,
364 .resume = sdhci_pltfm_resume,
365#endif
331}; 366};
367
368static int __init sdhci_esdhc_imx_init(void)
369{
370 return platform_driver_register(&sdhci_esdhc_imx_driver);
371}
372module_init(sdhci_esdhc_imx_init);
373
374static void __exit sdhci_esdhc_imx_exit(void)
375{
376 platform_driver_unregister(&sdhci_esdhc_imx_driver);
377}
378module_exit(sdhci_esdhc_imx_exit);
379
380MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
381MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
382MODULE_LICENSE("GPL v2");