1 /*
2 * Generic GPIO card-detect helper
3 *
4 * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11 #include <linux/err.h>
12 #include <linux/gpio.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/interrupt.h>
15 #include <linux/jiffies.h>
16 #include <linux/mmc/host.h>
17 #include <linux/mmc/slot-gpio.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
20
21 #include "slot-gpio.h"
22
23 struct mmc_gpio {
24 struct gpio_desc *ro_gpio;
25 struct gpio_desc *cd_gpio;
26 bool override_ro_active_level;
27 bool override_cd_active_level;
28 irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);
29 char *ro_label;
30 u32 cd_debounce_delay_ms;
31 char cd_label[];
32 };
33
mmc_gpio_cd_irqt(int irq,void * dev_id)34 static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
35 {
36 /* Schedule a card detection after a debounce timeout */
37 struct mmc_host *host = dev_id;
38 struct mmc_gpio *ctx = host->slot.handler_priv;
39
40 host->trigger_card_event = true;
41 mmc_detect_change(host, msecs_to_jiffies(ctx->cd_debounce_delay_ms));
42
43 return IRQ_HANDLED;
44 }
45
mmc_gpio_alloc(struct mmc_host * host)46 int mmc_gpio_alloc(struct mmc_host *host)
47 {
48 size_t len = strlen(dev_name(host->parent)) + 4;
49 struct mmc_gpio *ctx = devm_kzalloc(host->parent,
50 sizeof(*ctx) + 2 * len, GFP_KERNEL);
51
52 if (ctx) {
53 ctx->ro_label = ctx->cd_label + len;
54 ctx->cd_debounce_delay_ms = 200;
55 snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
56 snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
57 host->slot.handler_priv = ctx;
58 host->slot.cd_irq = -EINVAL;
59 }
60
61 return ctx ? 0 : -ENOMEM;
62 }
63
mmc_gpio_get_ro(struct mmc_host * host)64 int mmc_gpio_get_ro(struct mmc_host *host)
65 {
66 struct mmc_gpio *ctx = host->slot.handler_priv;
67
68 if (!ctx || !ctx->ro_gpio)
69 return -ENOSYS;
70
71 if (ctx->override_ro_active_level)
72 return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^
73 !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
74
75 return gpiod_get_value_cansleep(ctx->ro_gpio);
76 }
77 EXPORT_SYMBOL(mmc_gpio_get_ro);
78
mmc_gpio_get_cd(struct mmc_host * host)79 int mmc_gpio_get_cd(struct mmc_host *host)
80 {
81 struct mmc_gpio *ctx = host->slot.handler_priv;
82 int cansleep;
83
84 if (!ctx || !ctx->cd_gpio)
85 return -ENOSYS;
86
87 cansleep = gpiod_cansleep(ctx->cd_gpio);
88 if (ctx->override_cd_active_level) {
89 int value = cansleep ?
90 gpiod_get_raw_value_cansleep(ctx->cd_gpio) :
91 gpiod_get_raw_value(ctx->cd_gpio);
92 return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
93 }
94
95 return cansleep ?
96 gpiod_get_value_cansleep(ctx->cd_gpio) :
97 gpiod_get_value(ctx->cd_gpio);
98 }
99 EXPORT_SYMBOL(mmc_gpio_get_cd);
100
101 /**
102 * mmc_gpio_request_ro - request a gpio for write-protection
103 * @host: mmc host
104 * @gpio: gpio number requested
105 *
106 * As devm_* managed functions are used in mmc_gpio_request_ro(), client
107 * drivers do not need to worry about freeing up memory.
108 *
109 * Returns zero on success, else an error.
110 */
mmc_gpio_request_ro(struct mmc_host * host,unsigned int gpio)111 int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
112 {
113 struct mmc_gpio *ctx = host->slot.handler_priv;
114 int ret;
115
116 if (!gpio_is_valid(gpio))
117 return -EINVAL;
118
119 ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN,
120 ctx->ro_label);
121 if (ret < 0)
122 return ret;
123
124 ctx->override_ro_active_level = true;
125 ctx->ro_gpio = gpio_to_desc(gpio);
126
127 return 0;
128 }
129 EXPORT_SYMBOL(mmc_gpio_request_ro);
130
mmc_gpiod_request_cd_irq(struct mmc_host * host)131 void mmc_gpiod_request_cd_irq(struct mmc_host *host)
132 {
133 struct mmc_gpio *ctx = host->slot.handler_priv;
134 int irq = -EINVAL;
135 int ret;
136
137 if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio)
138 return;
139
140 /*
141 * Do not use IRQ if the platform prefers to poll, e.g., because that
142 * IRQ number is already used by another unit and cannot be shared.
143 */
144 if (!(host->caps & MMC_CAP_NEEDS_POLL))
145 irq = gpiod_to_irq(ctx->cd_gpio);
146
147 if (irq >= 0) {
148 if (!ctx->cd_gpio_isr)
149 ctx->cd_gpio_isr = mmc_gpio_cd_irqt;
150 ret = devm_request_threaded_irq(host->parent, irq,
151 NULL, ctx->cd_gpio_isr,
152 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
153 ctx->cd_label, host);
154 if (ret < 0)
155 irq = ret;
156 }
157
158 host->slot.cd_irq = irq;
159
160 if (irq < 0)
161 host->caps |= MMC_CAP_NEEDS_POLL;
162 }
163 EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
164
mmc_gpio_set_cd_wake(struct mmc_host * host,bool on)165 int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
166 {
167 int ret = 0;
168
169 if (!(host->caps & MMC_CAP_CD_WAKE) ||
170 host->slot.cd_irq < 0 ||
171 on == host->slot.cd_wake_enabled)
172 return 0;
173
174 if (on) {
175 ret = enable_irq_wake(host->slot.cd_irq);
176 host->slot.cd_wake_enabled = !ret;
177 } else {
178 disable_irq_wake(host->slot.cd_irq);
179 host->slot.cd_wake_enabled = false;
180 }
181
182 return ret;
183 }
184 EXPORT_SYMBOL(mmc_gpio_set_cd_wake);
185
186 /* Register an alternate interrupt service routine for
187 * the card-detect GPIO.
188 */
mmc_gpio_set_cd_isr(struct mmc_host * host,irqreturn_t (* isr)(int irq,void * dev_id))189 void mmc_gpio_set_cd_isr(struct mmc_host *host,
190 irqreturn_t (*isr)(int irq, void *dev_id))
191 {
192 struct mmc_gpio *ctx = host->slot.handler_priv;
193
194 WARN_ON(ctx->cd_gpio_isr);
195 ctx->cd_gpio_isr = isr;
196 }
197 EXPORT_SYMBOL(mmc_gpio_set_cd_isr);
198
199 /**
200 * mmc_gpio_request_cd - request a gpio for card-detection
201 * @host: mmc host
202 * @gpio: gpio number requested
203 * @debounce: debounce time in microseconds
204 *
205 * As devm_* managed functions are used in mmc_gpio_request_cd(), client
206 * drivers do not need to worry about freeing up memory.
207 *
208 * If GPIO debouncing is desired, set the debounce parameter to a non-zero
209 * value. The caller is responsible for ensuring that the GPIO driver associated
210 * with the GPIO supports debouncing, otherwise an error will be returned.
211 *
212 * Returns zero on success, else an error.
213 */
mmc_gpio_request_cd(struct mmc_host * host,unsigned int gpio,unsigned int debounce)214 int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
215 unsigned int debounce)
216 {
217 struct mmc_gpio *ctx = host->slot.handler_priv;
218 int ret;
219
220 ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN,
221 ctx->cd_label);
222 if (ret < 0)
223 /*
224 * don't bother freeing memory. It might still get used by other
225 * slot functions, in any case it will be freed, when the device
226 * is destroyed.
227 */
228 return ret;
229
230 if (debounce) {
231 ret = gpio_set_debounce(gpio, debounce);
232 if (ret < 0)
233 return ret;
234 }
235
236 ctx->override_cd_active_level = true;
237 ctx->cd_gpio = gpio_to_desc(gpio);
238
239 return 0;
240 }
241 EXPORT_SYMBOL(mmc_gpio_request_cd);
242
243 /**
244 * mmc_gpiod_request_cd - request a gpio descriptor for card-detection
245 * @host: mmc host
246 * @con_id: function within the GPIO consumer
247 * @idx: index of the GPIO to obtain in the consumer
248 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
249 * @debounce: debounce time in microseconds
250 * @gpio_invert: will return whether the GPIO line is inverted or not, set
251 * to NULL to ignore
252 *
253 * Use this function in place of mmc_gpio_request_cd() to use the GPIO
254 * descriptor API. Note that it must be called prior to mmc_add_host()
255 * otherwise the caller must also call mmc_gpiod_request_cd_irq().
256 *
257 * Returns zero on success, else an error.
258 */
mmc_gpiod_request_cd(struct mmc_host * host,const char * con_id,unsigned int idx,bool override_active_level,unsigned int debounce,bool * gpio_invert)259 int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
260 unsigned int idx, bool override_active_level,
261 unsigned int debounce, bool *gpio_invert)
262 {
263 struct mmc_gpio *ctx = host->slot.handler_priv;
264 struct gpio_desc *desc;
265 int ret;
266
267 desc = devm_gpiod_get_index(host->parent, con_id, idx, GPIOD_IN);
268 if (IS_ERR(desc))
269 return PTR_ERR(desc);
270
271 if (debounce) {
272 ret = gpiod_set_debounce(desc, debounce);
273 if (ret < 0)
274 ctx->cd_debounce_delay_ms = debounce / 1000;
275 }
276
277 if (gpio_invert)
278 *gpio_invert = !gpiod_is_active_low(desc);
279
280 ctx->override_cd_active_level = override_active_level;
281 ctx->cd_gpio = desc;
282
283 return 0;
284 }
285 EXPORT_SYMBOL(mmc_gpiod_request_cd);
286
mmc_can_gpio_cd(struct mmc_host * host)287 bool mmc_can_gpio_cd(struct mmc_host *host)
288 {
289 struct mmc_gpio *ctx = host->slot.handler_priv;
290
291 return ctx->cd_gpio ? true : false;
292 }
293 EXPORT_SYMBOL(mmc_can_gpio_cd);
294
295 /**
296 * mmc_gpiod_request_ro - request a gpio descriptor for write protection
297 * @host: mmc host
298 * @con_id: function within the GPIO consumer
299 * @idx: index of the GPIO to obtain in the consumer
300 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
301 * @debounce: debounce time in microseconds
302 * @gpio_invert: will return whether the GPIO line is inverted or not,
303 * set to NULL to ignore
304 *
305 * Use this function in place of mmc_gpio_request_ro() to use the GPIO
306 * descriptor API.
307 *
308 * Returns zero on success, else an error.
309 */
mmc_gpiod_request_ro(struct mmc_host * host,const char * con_id,unsigned int idx,bool override_active_level,unsigned int debounce,bool * gpio_invert)310 int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
311 unsigned int idx, bool override_active_level,
312 unsigned int debounce, bool *gpio_invert)
313 {
314 struct mmc_gpio *ctx = host->slot.handler_priv;
315 struct gpio_desc *desc;
316 int ret;
317
318 desc = devm_gpiod_get_index(host->parent, con_id, idx, GPIOD_IN);
319 if (IS_ERR(desc))
320 return PTR_ERR(desc);
321
322 if (debounce) {
323 ret = gpiod_set_debounce(desc, debounce);
324 if (ret < 0)
325 return ret;
326 }
327
328 if (gpio_invert)
329 *gpio_invert = !gpiod_is_active_low(desc);
330
331 ctx->override_ro_active_level = override_active_level;
332 ctx->ro_gpio = desc;
333
334 return 0;
335 }
336 EXPORT_SYMBOL(mmc_gpiod_request_ro);
337
mmc_can_gpio_ro(struct mmc_host * host)338 bool mmc_can_gpio_ro(struct mmc_host *host)
339 {
340 struct mmc_gpio *ctx = host->slot.handler_priv;
341
342 return ctx->ro_gpio ? true : false;
343 }
344 EXPORT_SYMBOL(mmc_can_gpio_ro);
345