Branch data Line data Source code
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/interrupt.h>
14 : : #include <linux/jiffies.h>
15 : : #include <linux/mmc/host.h>
16 : : #include <linux/mmc/slot-gpio.h>
17 : : #include <linux/module.h>
18 : : #include <linux/slab.h>
19 : :
20 : : struct mmc_gpio {
21 : : int ro_gpio;
22 : : int cd_gpio;
23 : : char *ro_label;
24 : : char cd_label[0];
25 : : };
26 : :
27 : 0 : static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
28 : : {
29 : : /* Schedule a card detection after a debounce timeout */
30 : : struct mmc_host *host = dev_id;
31 : :
32 [ # # ]: 0 : if (host->ops->card_event)
33 : 0 : host->ops->card_event(host);
34 : :
35 : 0 : mmc_detect_change(host, msecs_to_jiffies(200));
36 : :
37 : 0 : return IRQ_HANDLED;
38 : : }
39 : :
40 : 0 : static int mmc_gpio_alloc(struct mmc_host *host)
41 : : {
42 : 0 : size_t len = strlen(dev_name(host->parent)) + 4;
43 : : struct mmc_gpio *ctx;
44 : :
45 : 0 : mutex_lock(&host->slot.lock);
46 : :
47 : 0 : ctx = host->slot.handler_priv;
48 [ # # ]: 0 : if (!ctx) {
49 : : /*
50 : : * devm_kzalloc() can be called after device_initialize(), even
51 : : * before device_add(), i.e., between mmc_alloc_host() and
52 : : * mmc_add_host()
53 : : */
54 : 0 : ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
55 : : GFP_KERNEL);
56 [ # # ]: 0 : if (ctx) {
57 : 0 : ctx->ro_label = ctx->cd_label + len;
58 : 0 : snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
59 : 0 : snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
60 : 0 : ctx->cd_gpio = -EINVAL;
61 : 0 : ctx->ro_gpio = -EINVAL;
62 : 0 : host->slot.handler_priv = ctx;
63 : : }
64 : : }
65 : :
66 : 0 : mutex_unlock(&host->slot.lock);
67 : :
68 [ # # ]: 0 : return ctx ? 0 : -ENOMEM;
69 : : }
70 : :
71 : 0 : int mmc_gpio_get_ro(struct mmc_host *host)
72 : : {
73 : 0 : struct mmc_gpio *ctx = host->slot.handler_priv;
74 : :
75 [ # # ][ # # ]: 0 : if (!ctx || !gpio_is_valid(ctx->ro_gpio))
76 : : return -ENOSYS;
77 : :
78 : 0 : return !gpio_get_value_cansleep(ctx->ro_gpio) ^
79 : 0 : !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
80 : : }
81 : : EXPORT_SYMBOL(mmc_gpio_get_ro);
82 : :
83 : 0 : int mmc_gpio_get_cd(struct mmc_host *host)
84 : : {
85 : 0 : struct mmc_gpio *ctx = host->slot.handler_priv;
86 : :
87 [ # # ][ # # ]: 0 : if (!ctx || !gpio_is_valid(ctx->cd_gpio))
88 : : return -ENOSYS;
89 : :
90 : 0 : return !gpio_get_value_cansleep(ctx->cd_gpio) ^
91 : 0 : !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
92 : : }
93 : : EXPORT_SYMBOL(mmc_gpio_get_cd);
94 : :
95 : : /**
96 : : * mmc_gpio_request_ro - request a gpio for write-protection
97 : : * @host: mmc host
98 : : * @gpio: gpio number requested
99 : : *
100 : : * As devm_* managed functions are used in mmc_gpio_request_ro(), client
101 : : * drivers do not need to explicitly call mmc_gpio_free_ro() for freeing up,
102 : : * if the requesting and freeing are only needed at probing and unbinding time
103 : : * for once. However, if client drivers do something special like runtime
104 : : * switching for write-protection, they are responsible for calling
105 : : * mmc_gpio_request_ro() and mmc_gpio_free_ro() as a pair on their own.
106 : : *
107 : : * Returns zero on success, else an error.
108 : : */
109 : 0 : int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
110 : : {
111 : : struct mmc_gpio *ctx;
112 : : int ret;
113 : :
114 [ # # ]: 0 : if (!gpio_is_valid(gpio))
115 : : return -EINVAL;
116 : :
117 : 0 : ret = mmc_gpio_alloc(host);
118 [ # # ]: 0 : if (ret < 0)
119 : : return ret;
120 : :
121 : 0 : ctx = host->slot.handler_priv;
122 : :
123 : 0 : ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
124 : 0 : ctx->ro_label);
125 [ # # ]: 0 : if (ret < 0)
126 : : return ret;
127 : :
128 : 0 : ctx->ro_gpio = gpio;
129 : :
130 : 0 : return 0;
131 : : }
132 : : EXPORT_SYMBOL(mmc_gpio_request_ro);
133 : :
134 : : /**
135 : : * mmc_gpio_request_cd - request a gpio for card-detection
136 : : * @host: mmc host
137 : : * @gpio: gpio number requested
138 : : * @debounce: debounce time in microseconds
139 : : *
140 : : * As devm_* managed functions are used in mmc_gpio_request_cd(), client
141 : : * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
142 : : * if the requesting and freeing are only needed at probing and unbinding time
143 : : * for once. However, if client drivers do something special like runtime
144 : : * switching for card-detection, they are responsible for calling
145 : : * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
146 : : *
147 : : * If GPIO debouncing is desired, set the debounce parameter to a non-zero
148 : : * value. The caller is responsible for ensuring that the GPIO driver associated
149 : : * with the GPIO supports debouncing, otherwise an error will be returned.
150 : : *
151 : : * Returns zero on success, else an error.
152 : : */
153 : 0 : int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
154 : : unsigned int debounce)
155 : : {
156 : : struct mmc_gpio *ctx;
157 : : int irq = gpio_to_irq(gpio);
158 : : int ret;
159 : :
160 : 0 : ret = mmc_gpio_alloc(host);
161 [ # # ]: 0 : if (ret < 0)
162 : : return ret;
163 : :
164 : 0 : ctx = host->slot.handler_priv;
165 : :
166 : 0 : ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
167 : 0 : ctx->cd_label);
168 [ # # ]: 0 : if (ret < 0)
169 : : /*
170 : : * don't bother freeing memory. It might still get used by other
171 : : * slot functions, in any case it will be freed, when the device
172 : : * is destroyed.
173 : : */
174 : : return ret;
175 : :
176 [ # # ]: 0 : if (debounce) {
177 : : ret = gpio_set_debounce(gpio, debounce);
178 [ # # ]: 0 : if (ret < 0)
179 : : return ret;
180 : : }
181 : :
182 : : /*
183 : : * Even if gpio_to_irq() returns a valid IRQ number, the platform might
184 : : * still prefer to poll, e.g., because that IRQ number is already used
185 : : * by another unit and cannot be shared.
186 : : */
187 [ # # ][ # # ]: 0 : if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
188 : : irq = -EINVAL;
189 : :
190 [ # # ]: 0 : if (irq >= 0) {
191 : 0 : ret = devm_request_threaded_irq(&host->class_dev, irq,
192 : : NULL, mmc_gpio_cd_irqt,
193 : : IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
194 : : ctx->cd_label, host);
195 [ # # ]: 0 : if (ret < 0)
196 : : irq = ret;
197 : : }
198 : :
199 : 0 : host->slot.cd_irq = irq;
200 : :
201 [ # # ]: 0 : if (irq < 0)
202 : 0 : host->caps |= MMC_CAP_NEEDS_POLL;
203 : :
204 : 0 : ctx->cd_gpio = gpio;
205 : :
206 : 0 : return 0;
207 : : }
208 : : EXPORT_SYMBOL(mmc_gpio_request_cd);
209 : :
210 : : /**
211 : : * mmc_gpio_free_ro - free the write-protection gpio
212 : : * @host: mmc host
213 : : *
214 : : * It's provided only for cases that client drivers need to manually free
215 : : * up the write-protection gpio requested by mmc_gpio_request_ro().
216 : : */
217 : 0 : void mmc_gpio_free_ro(struct mmc_host *host)
218 : : {
219 : 0 : struct mmc_gpio *ctx = host->slot.handler_priv;
220 : : int gpio;
221 : :
222 [ # # ][ # # ]: 0 : if (!ctx || !gpio_is_valid(ctx->ro_gpio))
223 : 0 : return;
224 : :
225 : : gpio = ctx->ro_gpio;
226 : 0 : ctx->ro_gpio = -EINVAL;
227 : :
228 : 0 : devm_gpio_free(&host->class_dev, gpio);
229 : : }
230 : : EXPORT_SYMBOL(mmc_gpio_free_ro);
231 : :
232 : : /**
233 : : * mmc_gpio_free_cd - free the card-detection gpio
234 : : * @host: mmc host
235 : : *
236 : : * It's provided only for cases that client drivers need to manually free
237 : : * up the card-detection gpio requested by mmc_gpio_request_cd().
238 : : */
239 : 0 : void mmc_gpio_free_cd(struct mmc_host *host)
240 : : {
241 : 0 : struct mmc_gpio *ctx = host->slot.handler_priv;
242 : : int gpio;
243 : :
244 [ # # ][ # # ]: 0 : if (!ctx || !gpio_is_valid(ctx->cd_gpio))
245 : 0 : return;
246 : :
247 [ # # ]: 0 : if (host->slot.cd_irq >= 0) {
248 : 0 : devm_free_irq(&host->class_dev, host->slot.cd_irq, host);
249 : 0 : host->slot.cd_irq = -EINVAL;
250 : : }
251 : :
252 : 0 : gpio = ctx->cd_gpio;
253 : 0 : ctx->cd_gpio = -EINVAL;
254 : :
255 : 0 : devm_gpio_free(&host->class_dev, gpio);
256 : : }
257 : : EXPORT_SYMBOL(mmc_gpio_free_cd);
|