aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2012-02-09 16:57:09 -0500
committerChris Ball <cjb@laptop.org>2012-03-27 12:20:15 -0400
commitc8be24c2afd3ed2445bbf8f542af35a9787fc0e8 (patch)
treee0e757bb3b6a45f55eef145484ca5707d9e45fa8
parent2b1ac5c2caccbfd43bd616321cbbe21eb33c7879 (diff)
mmc: tmio_mmc: support the generic MMC GPIO card hotplug helper
If the platform specifies the TMIO_MMC_HAS_COLD_CD flag, use the generic MMC GPIO card hotplug helper. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/host/tmio_mmc.h4
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c69
-rw-r--r--include/linux/mfd/tmio.h25
3 files changed, 50 insertions, 48 deletions
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 8531d8d44fc1..ede2f4e5b952 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -53,10 +53,6 @@ struct tmio_mmc_host {
53 void (*set_pwr)(struct platform_device *host, int state); 53 void (*set_pwr)(struct platform_device *host, int state);
54 void (*set_clk_div)(struct platform_device *host, int state); 54 void (*set_clk_div)(struct platform_device *host, int state);
55 55
56 int pm_error;
57 /* recognise system-wide suspend in runtime PM methods */
58 bool pm_global;
59
60 /* pio related stuff */ 56 /* pio related stuff */
61 struct scatterlist *sg_ptr; 57 struct scatterlist *sg_ptr;
62 struct scatterlist *sg_orig; 58 struct scatterlist *sg_orig;
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 49f7f218cee1..42970ab6e803 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -34,6 +34,7 @@
34#include <linux/io.h> 34#include <linux/io.h>
35#include <linux/irq.h> 35#include <linux/irq.h>
36#include <linux/mfd/tmio.h> 36#include <linux/mfd/tmio.h>
37#include <linux/mmc/cd-gpio.h>
37#include <linux/mmc/host.h> 38#include <linux/mmc/host.h>
38#include <linux/mmc/tmio.h> 39#include <linux/mmc/tmio.h>
39#include <linux/module.h> 40#include <linux/module.h>
@@ -791,8 +792,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
791 spin_unlock_irqrestore(&host->lock, flags); 792 spin_unlock_irqrestore(&host->lock, flags);
792 793
793 /* 794 /*
794 * pdata->power == false only if COLD_CD is available, otherwise only 795 * pdata->power toggles between false and true in both cases - either
795 * in short time intervals during probing or resuming 796 * or not the controller can be runtime-suspended during inactivity.
797 * But if the controller has to be kept on, the runtime-pm usage_count
798 * is kept positive, so no suspending actually takes place.
796 */ 799 */
797 if (ios->power_mode == MMC_POWER_ON && ios->clock) { 800 if (ios->power_mode == MMC_POWER_ON && ios->clock) {
798 if (!pdata->power) { 801 if (!pdata->power) {
@@ -916,7 +919,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
916 else 919 else
917 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 920 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
918 921
919 _host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD || 922 _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
920 mmc->caps & MMC_CAP_NEEDS_POLL || 923 mmc->caps & MMC_CAP_NEEDS_POLL ||
921 mmc->caps & MMC_CAP_NONREMOVABLE); 924 mmc->caps & MMC_CAP_NONREMOVABLE);
922 925
@@ -933,8 +936,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
933 * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL 936 * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
934 * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE 937 * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
935 * 938 *
936 * While we increment the rtpm counter for all scenarios when the mmc 939 * While we increment the runtime PM counter for all scenarios when
937 * core activates us by calling an appropriate set_ios(), we must 940 * the mmc core activates us by calling an appropriate set_ios(), we
941 * must additionally ensure that in case 2) the tmio mmc hardware stays
938 * additionally ensure that in case 2) the tmio mmc hardware stays 942 * additionally ensure that in case 2) the tmio mmc hardware stays
939 * powered on during runtime for the card detection to work. 943 * powered on during runtime for the card detection to work.
940 */ 944 */
@@ -973,6 +977,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
973 977
974 tmio_mmc_enable_mmc_irqs(_host, irq_mask); 978 tmio_mmc_enable_mmc_irqs(_host, irq_mask);
975 979
980 if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
981 ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
982 if (ret < 0) {
983 tmio_mmc_host_remove(_host);
984 return ret;
985 }
986 }
987
976 *host = _host; 988 *host = _host;
977 989
978 return 0; 990 return 0;
@@ -990,20 +1002,22 @@ EXPORT_SYMBOL(tmio_mmc_host_probe);
990void tmio_mmc_host_remove(struct tmio_mmc_host *host) 1002void tmio_mmc_host_remove(struct tmio_mmc_host *host)
991{ 1003{
992 struct platform_device *pdev = host->pdev; 1004 struct platform_device *pdev = host->pdev;
1005 struct tmio_mmc_data *pdata = host->pdata;
1006 struct mmc_host *mmc = host->mmc;
1007
1008 if (pdata->flags & TMIO_MMC_USE_GPIO_CD)
1009 /*
1010 * This means we can miss a card-eject, but this is anyway
1011 * possible, because of delayed processing of hotplug events.
1012 */
1013 mmc_cd_gpio_free(mmc);
993 1014
994 /*
995 * We don't have to manipulate pdata->power here: if there is a card in
996 * the slot, the runtime PM is active and our .runtime_resume() will not
997 * be run. If there is no card in the slot and the platform can suspend
998 * the controller, the runtime PM is suspended and pdata->power == false,
999 * so, our .runtime_resume() will not try to detect a card in the slot.
1000 */
1001 if (!host->native_hotplug) 1015 if (!host->native_hotplug)
1002 pm_runtime_get_sync(&pdev->dev); 1016 pm_runtime_get_sync(&pdev->dev);
1003 1017
1004 dev_pm_qos_hide_latency_limit(&pdev->dev); 1018 dev_pm_qos_hide_latency_limit(&pdev->dev);
1005 1019
1006 mmc_remove_host(host->mmc); 1020 mmc_remove_host(mmc);
1007 cancel_work_sync(&host->done); 1021 cancel_work_sync(&host->done);
1008 cancel_delayed_work_sync(&host->delayed_reset_work); 1022 cancel_delayed_work_sync(&host->delayed_reset_work);
1009 tmio_mmc_release_dma(host); 1023 tmio_mmc_release_dma(host);
@@ -1012,7 +1026,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
1012 pm_runtime_disable(&pdev->dev); 1026 pm_runtime_disable(&pdev->dev);
1013 1027
1014 iounmap(host->ctl); 1028 iounmap(host->ctl);
1015 mmc_free_host(host->mmc); 1029 mmc_free_host(mmc);
1016} 1030}
1017EXPORT_SYMBOL(tmio_mmc_host_remove); 1031EXPORT_SYMBOL(tmio_mmc_host_remove);
1018 1032
@@ -1026,8 +1040,6 @@ int tmio_mmc_host_suspend(struct device *dev)
1026 if (!ret) 1040 if (!ret)
1027 tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); 1041 tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
1028 1042
1029 host->pm_error = pm_runtime_put_sync(dev);
1030
1031 return ret; 1043 return ret;
1032} 1044}
1033EXPORT_SYMBOL(tmio_mmc_host_suspend); 1045EXPORT_SYMBOL(tmio_mmc_host_suspend);
@@ -1037,20 +1049,10 @@ int tmio_mmc_host_resume(struct device *dev)
1037 struct mmc_host *mmc = dev_get_drvdata(dev); 1049 struct mmc_host *mmc = dev_get_drvdata(dev);
1038 struct tmio_mmc_host *host = mmc_priv(mmc); 1050 struct tmio_mmc_host *host = mmc_priv(mmc);
1039 1051
1040 /* The MMC core will perform the complete set up */ 1052 tmio_mmc_reset(host);
1041 host->pdata->power = false; 1053 tmio_mmc_enable_dma(host, true);
1042
1043 host->pm_global = true;
1044 if (!host->pm_error)
1045 pm_runtime_get_sync(dev);
1046
1047 if (host->pm_global) {
1048 /* Runtime PM resume callback didn't run */
1049 tmio_mmc_reset(host);
1050 tmio_mmc_enable_dma(host, true);
1051 host->pm_global = false;
1052 }
1053 1054
1055 /* The MMC core will perform the complete set up */
1054 return mmc_resume_host(mmc); 1056 return mmc_resume_host(mmc);
1055} 1057}
1056EXPORT_SYMBOL(tmio_mmc_host_resume); 1058EXPORT_SYMBOL(tmio_mmc_host_resume);
@@ -1067,19 +1069,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
1067{ 1069{
1068 struct mmc_host *mmc = dev_get_drvdata(dev); 1070 struct mmc_host *mmc = dev_get_drvdata(dev);
1069 struct tmio_mmc_host *host = mmc_priv(mmc); 1071 struct tmio_mmc_host *host = mmc_priv(mmc);
1070 struct tmio_mmc_data *pdata = host->pdata;
1071 1072
1072 tmio_mmc_reset(host); 1073 tmio_mmc_reset(host);
1073 tmio_mmc_enable_dma(host, true); 1074 tmio_mmc_enable_dma(host, true);
1074 1075
1075 if (pdata->power) {
1076 /* Only entered after a card-insert interrupt */
1077 if (!mmc->card)
1078 tmio_mmc_set_ios(mmc, &mmc->ios);
1079 mmc_detect_change(mmc, msecs_to_jiffies(100));
1080 }
1081 host->pm_global = false;
1082
1083 return 0; 1076 return 0;
1084} 1077}
1085EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); 1078EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 0dc98044d8b7..5a197de4aac9 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -1,8 +1,10 @@
1#ifndef MFD_TMIO_H 1#ifndef MFD_TMIO_H
2#define MFD_TMIO_H 2#define MFD_TMIO_H
3 3
4#include <linux/device.h>
4#include <linux/fb.h> 5#include <linux/fb.h>
5#include <linux/io.h> 6#include <linux/io.h>
7#include <linux/jiffies.h>
6#include <linux/platform_device.h> 8#include <linux/platform_device.h>
7#include <linux/pm_runtime.h> 9#include <linux/pm_runtime.h>
8 10
@@ -64,8 +66,8 @@
64#define TMIO_MMC_SDIO_IRQ (1 << 2) 66#define TMIO_MMC_SDIO_IRQ (1 << 2)
65/* 67/*
66 * Some platforms can detect card insertion events with controller powered 68 * 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 69 * down, using a GPIO IRQ, in which case they have to fill in cd_irq, cd_gpio,
68 * controller and report the event to the driver. 70 * and cd_flags fields of struct tmio_mmc_data.
69 */ 71 */
70#define TMIO_MMC_HAS_COLD_CD (1 << 3) 72#define TMIO_MMC_HAS_COLD_CD (1 << 3)
71/* 73/*
@@ -73,6 +75,12 @@
73 * idle before writing to some registers. 75 * idle before writing to some registers.
74 */ 76 */
75#define TMIO_MMC_HAS_IDLE_WAIT (1 << 4) 77#define TMIO_MMC_HAS_IDLE_WAIT (1 << 4)
78/*
79 * A GPIO is used for card hotplug detection. We need an extra flag for this,
80 * because 0 is a valid GPIO number too, and requiring users to specify
81 * cd_gpio < 0 to disable GPIO hotplug would break backwards compatibility.
82 */
83#define TMIO_MMC_USE_GPIO_CD (1 << 5)
76 84
77int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); 85int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
78int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); 86int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
@@ -98,18 +106,23 @@ struct tmio_mmc_data {
98 struct tmio_mmc_dma *dma; 106 struct tmio_mmc_dma *dma;
99 struct device *dev; 107 struct device *dev;
100 bool power; 108 bool power;
109 unsigned int cd_gpio;
101 void (*set_pwr)(struct platform_device *host, int state); 110 void (*set_pwr)(struct platform_device *host, int state);
102 void (*set_clk_div)(struct platform_device *host, int state); 111 void (*set_clk_div)(struct platform_device *host, int state);
103 int (*get_cd)(struct platform_device *host); 112 int (*get_cd)(struct platform_device *host);
104 int (*write16_hook)(struct tmio_mmc_host *host, int addr); 113 int (*write16_hook)(struct tmio_mmc_host *host, int addr);
105}; 114};
106 115
116/*
117 * This function is deprecated and will be removed soon. Please, convert your
118 * platform to use drivers/mmc/core/cd-gpio.c
119 */
120#include <linux/mmc/host.h>
107static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata) 121static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
108{ 122{
109 if (pdata && !pdata->power) { 123 if (pdata)
110 pdata->power = true; 124 mmc_detect_change(dev_get_drvdata(pdata->dev),
111 pm_runtime_get(pdata->dev); 125 msecs_to_jiffies(100));
112 }
113} 126}
114 127
115/* 128/*