diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 3 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 64 |
2 files changed, 61 insertions, 6 deletions
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index c6bf726c8f44..8260bc2c34e3 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -131,4 +131,7 @@ int tmio_mmc_host_resume(struct device *dev); | |||
131 | #define tmio_mmc_host_resume NULL | 131 | #define tmio_mmc_host_resume NULL |
132 | #endif | 132 | #endif |
133 | 133 | ||
134 | int tmio_mmc_host_runtime_suspend(struct device *dev); | ||
135 | int tmio_mmc_host_runtime_resume(struct device *dev); | ||
136 | |||
134 | #endif | 137 | #endif |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index af5d4f6d2233..ad6347bb02dd 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -746,6 +746,7 @@ fail: | |||
746 | static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 746 | static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
747 | { | 747 | { |
748 | struct tmio_mmc_host *host = mmc_priv(mmc); | 748 | struct tmio_mmc_host *host = mmc_priv(mmc); |
749 | struct tmio_mmc_data *pdata = host->pdata; | ||
749 | unsigned long flags; | 750 | unsigned long flags; |
750 | 751 | ||
751 | spin_lock_irqsave(&host->lock, flags); | 752 | spin_lock_irqsave(&host->lock, flags); |
@@ -775,13 +776,24 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
775 | 776 | ||
776 | /* Power sequence - OFF -> UP -> ON */ | 777 | /* Power sequence - OFF -> UP -> ON */ |
777 | if (ios->power_mode == MMC_POWER_UP) { | 778 | if (ios->power_mode == MMC_POWER_UP) { |
779 | if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && !pdata->power) { | ||
780 | pm_runtime_get_sync(&host->pdev->dev); | ||
781 | pdata->power = true; | ||
782 | } | ||
778 | /* power up SD bus */ | 783 | /* power up SD bus */ |
779 | if (host->set_pwr) | 784 | if (host->set_pwr) |
780 | host->set_pwr(host->pdev, 1); | 785 | host->set_pwr(host->pdev, 1); |
781 | } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { | 786 | } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { |
782 | /* power down SD bus */ | 787 | /* power down SD bus */ |
783 | if (ios->power_mode == MMC_POWER_OFF && host->set_pwr) | 788 | if (ios->power_mode == MMC_POWER_OFF) { |
784 | host->set_pwr(host->pdev, 0); | 789 | if (host->set_pwr) |
790 | host->set_pwr(host->pdev, 0); | ||
791 | if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && | ||
792 | pdata->power) { | ||
793 | pdata->power = false; | ||
794 | pm_runtime_put(&host->pdev->dev); | ||
795 | } | ||
796 | } | ||
785 | tmio_mmc_clk_stop(host); | 797 | tmio_mmc_clk_stop(host); |
786 | } else { | 798 | } else { |
787 | /* start bus clock */ | 799 | /* start bus clock */ |
@@ -853,6 +865,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
853 | if (!mmc) | 865 | if (!mmc) |
854 | return -ENOMEM; | 866 | return -ENOMEM; |
855 | 867 | ||
868 | pdata->dev = &pdev->dev; | ||
856 | _host = mmc_priv(mmc); | 869 | _host = mmc_priv(mmc); |
857 | _host->pdata = pdata; | 870 | _host->pdata = pdata; |
858 | _host->mmc = mmc; | 871 | _host->mmc = mmc; |
@@ -886,6 +899,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
886 | else | 899 | else |
887 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 900 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
888 | 901 | ||
902 | pdata->power = false; | ||
889 | pm_runtime_enable(&pdev->dev); | 903 | pm_runtime_enable(&pdev->dev); |
890 | ret = pm_runtime_resume(&pdev->dev); | 904 | ret = pm_runtime_resume(&pdev->dev); |
891 | if (ret < 0) | 905 | if (ret < 0) |
@@ -907,7 +921,8 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
907 | tmio_mmc_request_dma(_host, pdata); | 921 | tmio_mmc_request_dma(_host, pdata); |
908 | 922 | ||
909 | /* We have to keep the device powered for its card detection to work */ | 923 | /* We have to keep the device powered for its card detection to work */ |
910 | pm_runtime_get_noresume(&pdev->dev); | 924 | if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) |
925 | pm_runtime_get_noresume(&pdev->dev); | ||
911 | 926 | ||
912 | mmc_add_host(mmc); | 927 | mmc_add_host(mmc); |
913 | 928 | ||
@@ -937,15 +952,25 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) | |||
937 | { | 952 | { |
938 | struct platform_device *pdev = host->pdev; | 953 | struct platform_device *pdev = host->pdev; |
939 | 954 | ||
955 | /* | ||
956 | * We don't have to manipulate pdata->power here: if there is a card in | ||
957 | * the slot, the runtime PM is active and our .runtime_resume() will not | ||
958 | * be run. If there is no card in the slot and the platform can suspend | ||
959 | * the controller, the runtime PM is suspended and pdata->power == false, | ||
960 | * so, our .runtime_resume() will not try to detect a card in the slot. | ||
961 | */ | ||
962 | if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD) | ||
963 | pm_runtime_get_sync(&pdev->dev); | ||
964 | |||
940 | mmc_remove_host(host->mmc); | 965 | mmc_remove_host(host->mmc); |
941 | cancel_delayed_work_sync(&host->delayed_reset_work); | 966 | cancel_delayed_work_sync(&host->delayed_reset_work); |
942 | tmio_mmc_release_dma(host); | 967 | tmio_mmc_release_dma(host); |
943 | iounmap(host->ctl); | ||
944 | mmc_free_host(host->mmc); | ||
945 | 968 | ||
946 | /* Compensate for pm_runtime_get_sync() in probe() above */ | ||
947 | pm_runtime_put_sync(&pdev->dev); | 969 | pm_runtime_put_sync(&pdev->dev); |
948 | pm_runtime_disable(&pdev->dev); | 970 | pm_runtime_disable(&pdev->dev); |
971 | |||
972 | iounmap(host->ctl); | ||
973 | mmc_free_host(host->mmc); | ||
949 | } | 974 | } |
950 | EXPORT_SYMBOL(tmio_mmc_host_remove); | 975 | EXPORT_SYMBOL(tmio_mmc_host_remove); |
951 | 976 | ||
@@ -970,6 +995,9 @@ int tmio_mmc_host_resume(struct device *dev) | |||
970 | struct mmc_host *mmc = dev_get_drvdata(dev); | 995 | struct mmc_host *mmc = dev_get_drvdata(dev); |
971 | struct tmio_mmc_host *host = mmc_priv(mmc); | 996 | struct tmio_mmc_host *host = mmc_priv(mmc); |
972 | 997 | ||
998 | /* The MMC core will perform the complete set up */ | ||
999 | host->pdata->power = false; | ||
1000 | |||
973 | if (!host->pm_error) | 1001 | if (!host->pm_error) |
974 | pm_runtime_get_sync(dev); | 1002 | pm_runtime_get_sync(dev); |
975 | 1003 | ||
@@ -982,4 +1010,28 @@ EXPORT_SYMBOL(tmio_mmc_host_resume); | |||
982 | 1010 | ||
983 | #endif /* CONFIG_PM */ | 1011 | #endif /* CONFIG_PM */ |
984 | 1012 | ||
1013 | int tmio_mmc_host_runtime_suspend(struct device *dev) | ||
1014 | { | ||
1015 | return 0; | ||
1016 | } | ||
1017 | EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend); | ||
1018 | |||
1019 | int tmio_mmc_host_runtime_resume(struct device *dev) | ||
1020 | { | ||
1021 | struct mmc_host *mmc = dev_get_drvdata(dev); | ||
1022 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
1023 | struct tmio_mmc_data *pdata = host->pdata; | ||
1024 | |||
1025 | tmio_mmc_reset(host); | ||
1026 | |||
1027 | if (pdata->power) { | ||
1028 | /* Only entered after a card-insert interrupt */ | ||
1029 | tmio_mmc_set_ios(mmc, &mmc->ios); | ||
1030 | mmc_detect_change(mmc, msecs_to_jiffies(100)); | ||
1031 | } | ||
1032 | |||
1033 | return 0; | ||
1034 | } | ||
1035 | EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); | ||
1036 | |||
985 | MODULE_LICENSE("GPL v2"); | 1037 | MODULE_LICENSE("GPL v2"); |