aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2012-05-01 10:59:38 -0400
committerChris Ball <cjb@laptop.org>2012-07-21 00:02:18 -0400
commit5aa7dad305594ea30d21e23b3036565042adf50c (patch)
treed9c7c2962e35c63ffe7d4ad2d48e8e99109dadb4 /drivers/mmc
parenta7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b (diff)
mmc: core: add WP pin handler to slot functions
Card Write-Protect pin is often implemented, using a GPIO, which makes it simple to provide a generic handler for it. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/slot-gpio.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 41689da14b8d..058242916cef 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -18,7 +18,9 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19 19
20struct mmc_gpio { 20struct mmc_gpio {
21 int ro_gpio;
21 int cd_gpio; 22 int cd_gpio;
23 char *ro_label;
22 char cd_label[0]; 24 char cd_label[0];
23}; 25};
24 26
@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host)
43 * before device_add(), i.e., between mmc_alloc_host() and 45 * before device_add(), i.e., between mmc_alloc_host() and
44 * mmc_add_host() 46 * mmc_add_host()
45 */ 47 */
46 ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len, 48 ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
47 GFP_KERNEL); 49 GFP_KERNEL);
48 if (ctx) { 50 if (ctx) {
51 ctx->ro_label = ctx->cd_label + len;
49 snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); 52 snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
53 snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
50 ctx->cd_gpio = -EINVAL; 54 ctx->cd_gpio = -EINVAL;
55 ctx->ro_gpio = -EINVAL;
51 host->slot.handler_priv = ctx; 56 host->slot.handler_priv = ctx;
52 } 57 }
53 } 58 }
@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host)
57 return ctx ? 0 : -ENOMEM; 62 return ctx ? 0 : -ENOMEM;
58} 63}
59 64
65int mmc_gpio_get_ro(struct mmc_host *host)
66{
67 struct mmc_gpio *ctx = host->slot.handler_priv;
68
69 if (!ctx || !gpio_is_valid(ctx->ro_gpio))
70 return -ENOSYS;
71
72 return !gpio_get_value_cansleep(ctx->ro_gpio) ^
73 !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
74}
75EXPORT_SYMBOL(mmc_gpio_get_ro);
76
60int mmc_gpio_get_cd(struct mmc_host *host) 77int mmc_gpio_get_cd(struct mmc_host *host)
61{ 78{
62 struct mmc_gpio *ctx = host->slot.handler_priv; 79 struct mmc_gpio *ctx = host->slot.handler_priv;
@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host)
69} 86}
70EXPORT_SYMBOL(mmc_gpio_get_cd); 87EXPORT_SYMBOL(mmc_gpio_get_cd);
71 88
89int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
90{
91 struct mmc_gpio *ctx;
92 int ret;
93
94 if (!gpio_is_valid(gpio))
95 return -EINVAL;
96
97 ret = mmc_gpio_alloc(host);
98 if (ret < 0)
99 return ret;
100
101 ctx = host->slot.handler_priv;
102
103 return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
104}
105EXPORT_SYMBOL(mmc_gpio_request_ro);
106
72int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) 107int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
73{ 108{
74 struct mmc_gpio *ctx; 109 struct mmc_gpio *ctx;
@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
117} 152}
118EXPORT_SYMBOL(mmc_gpio_request_cd); 153EXPORT_SYMBOL(mmc_gpio_request_cd);
119 154
155void mmc_gpio_free_ro(struct mmc_host *host)
156{
157 struct mmc_gpio *ctx = host->slot.handler_priv;
158 int gpio;
159
160 if (!ctx || !gpio_is_valid(ctx->ro_gpio))
161 return;
162
163 gpio = ctx->ro_gpio;
164 ctx->ro_gpio = -EINVAL;
165
166 gpio_free(gpio);
167}
168EXPORT_SYMBOL(mmc_gpio_free_ro);
169
120void mmc_gpio_free_cd(struct mmc_host *host) 170void mmc_gpio_free_cd(struct mmc_host *host)
121{ 171{
122 struct mmc_gpio *ctx = host->slot.handler_priv; 172 struct mmc_gpio *ctx = host->slot.handler_priv;