diff options
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 52 | ||||
-rw-r--r-- | include/linux/mmc/slot-gpio.h | 4 |
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 | ||
20 | struct mmc_gpio { | 20 | struct 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 | ||
65 | int 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 | } | ||
75 | EXPORT_SYMBOL(mmc_gpio_get_ro); | ||
76 | |||
60 | int mmc_gpio_get_cd(struct mmc_host *host) | 77 | int 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 | } |
70 | EXPORT_SYMBOL(mmc_gpio_get_cd); | 87 | EXPORT_SYMBOL(mmc_gpio_get_cd); |
71 | 88 | ||
89 | int 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 | } | ||
105 | EXPORT_SYMBOL(mmc_gpio_request_ro); | ||
106 | |||
72 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) | 107 | int 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 | } |
118 | EXPORT_SYMBOL(mmc_gpio_request_cd); | 153 | EXPORT_SYMBOL(mmc_gpio_request_cd); |
119 | 154 | ||
155 | void 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 | } | ||
168 | EXPORT_SYMBOL(mmc_gpio_free_ro); | ||
169 | |||
120 | void mmc_gpio_free_cd(struct mmc_host *host) | 170 | void 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 | ||
14 | struct mmc_host; | 14 | struct mmc_host; |
15 | 15 | ||
16 | int mmc_gpio_get_ro(struct mmc_host *host); | ||
17 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio); | ||
18 | void mmc_gpio_free_ro(struct mmc_host *host); | ||
19 | |||
16 | int mmc_gpio_get_cd(struct mmc_host *host); | 20 | int mmc_gpio_get_cd(struct mmc_host *host); |
17 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); | 21 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); |
18 | void mmc_gpio_free_cd(struct mmc_host *host); | 22 | void mmc_gpio_free_cd(struct mmc_host *host); |