diff options
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 3 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 64 | ||||
-rw-r--r-- | include/linux/mfd/tmio.h | 17 |
3 files changed, 78 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"); |
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 8e70310ee945..5a90266c3a5a 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/fb.h> | 4 | #include <linux/fb.h> |
5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
6 | #include <linux/platform_device.h> | 6 | #include <linux/platform_device.h> |
7 | #include <linux/pm_runtime.h> | ||
7 | 8 | ||
8 | #define tmio_ioread8(addr) readb(addr) | 9 | #define tmio_ioread8(addr) readb(addr) |
9 | #define tmio_ioread16(addr) readw(addr) | 10 | #define tmio_ioread16(addr) readw(addr) |
@@ -61,6 +62,12 @@ | |||
61 | * Some controllers can support SDIO IRQ signalling. | 62 | * Some controllers can support SDIO IRQ signalling. |
62 | */ | 63 | */ |
63 | #define TMIO_MMC_SDIO_IRQ (1 << 2) | 64 | #define TMIO_MMC_SDIO_IRQ (1 << 2) |
65 | /* | ||
66 | * Some platforms can detect card insertion events with controller powered | ||
67 | * down, in which case they have to call tmio_mmc_cd_wakeup() to power up the | ||
68 | * controller and report the event to the driver. | ||
69 | */ | ||
70 | #define TMIO_MMC_HAS_COLD_CD (1 << 3) | ||
64 | 71 | ||
65 | int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); | 72 | int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); |
66 | int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); | 73 | int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); |
@@ -82,11 +89,21 @@ struct tmio_mmc_data { | |||
82 | unsigned long flags; | 89 | unsigned long flags; |
83 | u32 ocr_mask; /* available voltages */ | 90 | u32 ocr_mask; /* available voltages */ |
84 | struct tmio_mmc_dma *dma; | 91 | struct tmio_mmc_dma *dma; |
92 | struct device *dev; | ||
93 | bool power; | ||
85 | void (*set_pwr)(struct platform_device *host, int state); | 94 | void (*set_pwr)(struct platform_device *host, int state); |
86 | void (*set_clk_div)(struct platform_device *host, int state); | 95 | void (*set_clk_div)(struct platform_device *host, int state); |
87 | int (*get_cd)(struct platform_device *host); | 96 | int (*get_cd)(struct platform_device *host); |
88 | }; | 97 | }; |
89 | 98 | ||
99 | static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata) | ||
100 | { | ||
101 | if (pdata && !pdata->power) { | ||
102 | pdata->power = true; | ||
103 | pm_runtime_get(pdata->dev); | ||
104 | } | ||
105 | } | ||
106 | |||
90 | /* | 107 | /* |
91 | * data for the NAND controller | 108 | * data for the NAND controller |
92 | */ | 109 | */ |