aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r--drivers/mmc/host/sdhci-s3c.c159
1 files changed, 125 insertions, 34 deletions
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index b19e7d435f8d..55a164fcaa15 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -20,6 +20,10 @@
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/gpio.h> 21#include <linux/gpio.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/of_gpio.h>
25#include <linux/pm.h>
26#include <linux/pm_runtime.h>
23 27
24#include <linux/mmc/host.h> 28#include <linux/mmc/host.h>
25 29
@@ -53,6 +57,18 @@ struct sdhci_s3c {
53 struct clk *clk_bus[MAX_BUS_CLK]; 57 struct clk *clk_bus[MAX_BUS_CLK];
54}; 58};
55 59
60/**
61 * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
62 * @sdhci_quirks: sdhci host specific quirks.
63 *
64 * Specifies platform specific configuration of sdhci controller.
65 * Note: A structure for driver specific platform data is used for future
66 * expansion of its usage.
67 */
68struct sdhci_s3c_drv_data {
69 unsigned int sdhci_quirks;
70};
71
56static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) 72static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
57{ 73{
58 return sdhci_priv(host); 74 return sdhci_priv(host);
@@ -132,10 +148,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
132 return UINT_MAX; 148 return UINT_MAX;
133 149
134 /* 150 /*
135 * Clock divider's step is different as 1 from that of host controller 151 * If controller uses a non-standard clock division, find the best clock
136 * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL. 152 * speed possible with selected clock source and skip the division.
137 */ 153 */
138 if (ourhost->pdata->clk_type) { 154 if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
139 rate = clk_round_rate(clksrc, wanted); 155 rate = clk_round_rate(clksrc, wanted);
140 return wanted - rate; 156 return wanted - rate;
141 } 157 }
@@ -272,6 +288,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
272static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) 288static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
273{ 289{
274 struct sdhci_s3c *ourhost = to_s3c(host); 290 struct sdhci_s3c *ourhost = to_s3c(host);
291 unsigned long timeout;
292 u16 clk = 0;
275 293
276 /* don't bother if the clock is going off */ 294 /* don't bother if the clock is going off */
277 if (clock == 0) 295 if (clock == 0)
@@ -282,6 +300,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
282 clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); 300 clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
283 301
284 host->clock = clock; 302 host->clock = clock;
303
304 clk = SDHCI_CLOCK_INT_EN;
305 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
306
307 /* Wait max 20 ms */
308 timeout = 20;
309 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
310 & SDHCI_CLOCK_INT_STABLE)) {
311 if (timeout == 0) {
312 printk(KERN_ERR "%s: Internal clock never "
313 "stabilised.\n", mmc_hostname(host->mmc));
314 return;
315 }
316 timeout--;
317 mdelay(1);
318 }
319
320 clk |= SDHCI_CLOCK_CARD_EN;
321 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
285} 322}
286 323
287/** 324/**
@@ -382,16 +419,24 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
382 } 419 }
383} 420}
384 421
422static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
423 struct platform_device *pdev)
424{
425 return (struct sdhci_s3c_drv_data *)
426 platform_get_device_id(pdev)->driver_data;
427}
428
385static int __devinit sdhci_s3c_probe(struct platform_device *pdev) 429static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
386{ 430{
387 struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; 431 struct s3c_sdhci_platdata *pdata;
432 struct sdhci_s3c_drv_data *drv_data;
388 struct device *dev = &pdev->dev; 433 struct device *dev = &pdev->dev;
389 struct sdhci_host *host; 434 struct sdhci_host *host;
390 struct sdhci_s3c *sc; 435 struct sdhci_s3c *sc;
391 struct resource *res; 436 struct resource *res;
392 int ret, irq, ptr, clks; 437 int ret, irq, ptr, clks;
393 438
394 if (!pdata) { 439 if (!pdev->dev.platform_data) {
395 dev_err(dev, "no device data specified\n"); 440 dev_err(dev, "no device data specified\n");
396 return -ENOENT; 441 return -ENOENT;
397 } 442 }
@@ -402,18 +447,20 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
402 return irq; 447 return irq;
403 } 448 }
404 449
405 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
406 if (!res) {
407 dev_err(dev, "no memory specified\n");
408 return -ENOENT;
409 }
410
411 host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); 450 host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
412 if (IS_ERR(host)) { 451 if (IS_ERR(host)) {
413 dev_err(dev, "sdhci_alloc_host() failed\n"); 452 dev_err(dev, "sdhci_alloc_host() failed\n");
414 return PTR_ERR(host); 453 return PTR_ERR(host);
415 } 454 }
416 455
456 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
457 if (!pdata) {
458 ret = -ENOMEM;
459 goto err_io_clk;
460 }
461 memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
462
463 drv_data = sdhci_s3c_get_driver_data(pdev);
417 sc = sdhci_priv(host); 464 sc = sdhci_priv(host);
418 465
419 sc->host = host; 466 sc->host = host;
@@ -464,15 +511,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
464 goto err_no_busclks; 511 goto err_no_busclks;
465 } 512 }
466 513
467 sc->ioarea = request_mem_region(res->start, resource_size(res), 514 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
468 mmc_hostname(host->mmc)); 515 host->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
469 if (!sc->ioarea) {
470 dev_err(dev, "failed to reserve register area\n");
471 ret = -ENXIO;
472 goto err_req_regs;
473 }
474
475 host->ioaddr = ioremap_nocache(res->start, resource_size(res));
476 if (!host->ioaddr) { 516 if (!host->ioaddr) {
477 dev_err(dev, "failed to map registers\n"); 517 dev_err(dev, "failed to map registers\n");
478 ret = -ENXIO; 518 ret = -ENXIO;
@@ -491,6 +531,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
491 /* Setup quirks for the controller */ 531 /* Setup quirks for the controller */
492 host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; 532 host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
493 host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; 533 host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
534 if (drv_data)
535 host->quirks |= drv_data->sdhci_quirks;
494 536
495#ifndef CONFIG_MMC_SDHCI_S3C_DMA 537#ifndef CONFIG_MMC_SDHCI_S3C_DMA
496 538
@@ -518,6 +560,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
518 if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) 560 if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
519 host->mmc->caps = MMC_CAP_NONREMOVABLE; 561 host->mmc->caps = MMC_CAP_NONREMOVABLE;
520 562
563 switch (pdata->max_width) {
564 case 8:
565 host->mmc->caps |= MMC_CAP_8_BIT_DATA;
566 case 4:
567 host->mmc->caps |= MMC_CAP_4_BIT_DATA;
568 break;
569 }
570
521 if (pdata->pm_caps) 571 if (pdata->pm_caps)
522 host->mmc->pm_caps |= pdata->pm_caps; 572 host->mmc->pm_caps |= pdata->pm_caps;
523 573
@@ -531,7 +581,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
531 * If controller does not have internal clock divider, 581 * If controller does not have internal clock divider,
532 * we can use overriding functions instead of default. 582 * we can use overriding functions instead of default.
533 */ 583 */
534 if (pdata->clk_type) { 584 if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
535 sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; 585 sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
536 sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; 586 sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
537 sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; 587 sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -544,10 +594,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
544 if (pdata->host_caps2) 594 if (pdata->host_caps2)
545 host->mmc->caps2 |= pdata->host_caps2; 595 host->mmc->caps2 |= pdata->host_caps2;
546 596
597 pm_runtime_enable(&pdev->dev);
598 pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
599 pm_runtime_use_autosuspend(&pdev->dev);
600 pm_suspend_ignore_children(&pdev->dev, 1);
601
547 ret = sdhci_add_host(host); 602 ret = sdhci_add_host(host);
548 if (ret) { 603 if (ret) {
549 dev_err(dev, "sdhci_add_host() failed\n"); 604 dev_err(dev, "sdhci_add_host() failed\n");
550 goto err_add_host; 605 pm_runtime_forbid(&pdev->dev);
606 pm_runtime_get_noresume(&pdev->dev);
607 goto err_req_regs;
551 } 608 }
552 609
553 /* The following two methods of card detection might call 610 /* The following two methods of card detection might call
@@ -561,10 +618,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
561 618
562 return 0; 619 return 0;
563 620
564 err_add_host:
565 release_resource(sc->ioarea);
566 kfree(sc->ioarea);
567
568 err_req_regs: 621 err_req_regs:
569 for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { 622 for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
570 if (sc->clk_bus[ptr]) { 623 if (sc->clk_bus[ptr]) {
@@ -601,6 +654,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
601 654
602 sdhci_remove_host(host, 1); 655 sdhci_remove_host(host, 1);
603 656
657 pm_runtime_disable(&pdev->dev);
658
604 for (ptr = 0; ptr < 3; ptr++) { 659 for (ptr = 0; ptr < 3; ptr++) {
605 if (sc->clk_bus[ptr]) { 660 if (sc->clk_bus[ptr]) {
606 clk_disable(sc->clk_bus[ptr]); 661 clk_disable(sc->clk_bus[ptr]);
@@ -610,18 +665,13 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
610 clk_disable(sc->clk_io); 665 clk_disable(sc->clk_io);
611 clk_put(sc->clk_io); 666 clk_put(sc->clk_io);
612 667
613 iounmap(host->ioaddr);
614 release_resource(sc->ioarea);
615 kfree(sc->ioarea);
616
617 sdhci_free_host(host); 668 sdhci_free_host(host);
618 platform_set_drvdata(pdev, NULL); 669 platform_set_drvdata(pdev, NULL);
619 670
620 return 0; 671 return 0;
621} 672}
622 673
623#ifdef CONFIG_PM 674#ifdef CONFIG_PM_SLEEP
624
625static int sdhci_s3c_suspend(struct device *dev) 675static int sdhci_s3c_suspend(struct device *dev)
626{ 676{
627 struct sdhci_host *host = dev_get_drvdata(dev); 677 struct sdhci_host *host = dev_get_drvdata(dev);
@@ -635,10 +685,29 @@ static int sdhci_s3c_resume(struct device *dev)
635 685
636 return sdhci_resume_host(host); 686 return sdhci_resume_host(host);
637} 687}
688#endif
689
690#ifdef CONFIG_PM_RUNTIME
691static int sdhci_s3c_runtime_suspend(struct device *dev)
692{
693 struct sdhci_host *host = dev_get_drvdata(dev);
694
695 return sdhci_runtime_suspend_host(host);
696}
638 697
698static int sdhci_s3c_runtime_resume(struct device *dev)
699{
700 struct sdhci_host *host = dev_get_drvdata(dev);
701
702 return sdhci_runtime_resume_host(host);
703}
704#endif
705
706#ifdef CONFIG_PM
639static const struct dev_pm_ops sdhci_s3c_pmops = { 707static const struct dev_pm_ops sdhci_s3c_pmops = {
640 .suspend = sdhci_s3c_suspend, 708 SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume)
641 .resume = sdhci_s3c_resume, 709 SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume,
710 NULL)
642}; 711};
643 712
644#define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) 713#define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops)
@@ -647,9 +716,31 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
647#define SDHCI_S3C_PMOPS NULL 716#define SDHCI_S3C_PMOPS NULL
648#endif 717#endif
649 718
719#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
720static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
721 .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
722};
723#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
724#else
725#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL)
726#endif
727
728static struct platform_device_id sdhci_s3c_driver_ids[] = {
729 {
730 .name = "s3c-sdhci",
731 .driver_data = (kernel_ulong_t)NULL,
732 }, {
733 .name = "exynos4-sdhci",
734 .driver_data = EXYNOS4_SDHCI_DRV_DATA,
735 },
736 { }
737};
738MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
739
650static struct platform_driver sdhci_s3c_driver = { 740static struct platform_driver sdhci_s3c_driver = {
651 .probe = sdhci_s3c_probe, 741 .probe = sdhci_s3c_probe,
652 .remove = __devexit_p(sdhci_s3c_remove), 742 .remove = __devexit_p(sdhci_s3c_remove),
743 .id_table = sdhci_s3c_driver_ids,
653 .driver = { 744 .driver = {
654 .owner = THIS_MODULE, 745 .owner = THIS_MODULE,
655 .name = "s3c-sdhci", 746 .name = "s3c-sdhci",