aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/slot-gpio.c52
-rw-r--r--include/linux/mmc/slot-gpio.h4
2 files changed, 55 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;
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
index 1a977d7ba3ba..7d88d27bfafa 100644
--- a/include/linux/mmc/slot-gpio.h
+++ b/include/linux/mmc/slot-gpio.h
@@ -13,6 +13,10 @@
13 13
14struct mmc_host; 14struct mmc_host;
15 15
16int mmc_gpio_get_ro(struct mmc_host *host);
17int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
18void mmc_gpio_free_ro(struct mmc_host *host);
19
16int mmc_gpio_get_cd(struct mmc_host *host); 20int mmc_gpio_get_cd(struct mmc_host *host);
17int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); 21int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
18void mmc_gpio_free_cd(struct mmc_host *host); 22void mmc_gpio_free_cd(struct mmc_host *host);