]>
Commit | Line | Data |
---|---|---|
78a56aab PB |
1 | /* |
2 | * Driver for keys on GPIO lines capable of generating interrupts. | |
3 | * | |
4 | * Copyright 2005 Phil Blundell | |
fd05d089 | 5 | * Copyright 2010, 2011 David Jander <david@protonic.nl> |
78a56aab PB |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/module.h> | |
78a56aab PB |
13 | |
14 | #include <linux/init.h> | |
15 | #include <linux/fs.h> | |
16 | #include <linux/interrupt.h> | |
17 | #include <linux/irq.h> | |
18 | #include <linux/sched.h> | |
19 | #include <linux/pm.h> | |
5a0e3ad6 | 20 | #include <linux/slab.h> |
78a56aab PB |
21 | #include <linux/sysctl.h> |
22 | #include <linux/proc_fs.h> | |
23 | #include <linux/delay.h> | |
24 | #include <linux/platform_device.h> | |
25 | #include <linux/input.h> | |
49015bee | 26 | #include <linux/gpio_keys.h> |
da0d03fe | 27 | #include <linux/workqueue.h> |
111bc59c | 28 | #include <linux/gpio.h> |
415a4caa | 29 | #include <linux/of.h> |
fd05d089 DJ |
30 | #include <linux/of_platform.h> |
31 | #include <linux/of_gpio.h> | |
f2d347ff | 32 | #include <linux/of_irq.h> |
d8ee4a1c | 33 | #include <linux/spinlock.h> |
78a56aab | 34 | |
a33466e3 | 35 | struct gpio_button_data { |
d9080921 | 36 | const struct gpio_keys_button *button; |
a33466e3 | 37 | struct input_dev *input; |
8ed92556 DT |
38 | |
39 | struct timer_list release_timer; | |
40 | unsigned int release_delay; /* in msecs, for IRQ-only buttons */ | |
41 | ||
42 | struct delayed_work work; | |
43 | unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ | |
44 | ||
d8ee4a1c LD |
45 | unsigned int irq; |
46 | spinlock_t lock; | |
9e3af04f | 47 | bool disabled; |
d8ee4a1c | 48 | bool key_pressed; |
a33466e3 DES |
49 | }; |
50 | ||
51 | struct gpio_keys_drvdata { | |
219edc71 | 52 | const struct gpio_keys_platform_data *pdata; |
a33466e3 | 53 | struct input_dev *input; |
9e3af04f | 54 | struct mutex disable_lock; |
a33466e3 DES |
55 | struct gpio_button_data data[0]; |
56 | }; | |
57 | ||
9e3af04f MW |
58 | /* |
59 | * SYSFS interface for enabling/disabling keys and switches: | |
60 | * | |
61 | * There are 4 attributes under /sys/devices/platform/gpio-keys/ | |
62 | * keys [ro] - bitmap of keys (EV_KEY) which can be | |
63 | * disabled | |
64 | * switches [ro] - bitmap of switches (EV_SW) which can be | |
65 | * disabled | |
66 | * disabled_keys [rw] - bitmap of keys currently disabled | |
67 | * disabled_switches [rw] - bitmap of switches currently disabled | |
68 | * | |
69 | * Userland can change these values and hence disable event generation | |
70 | * for each key (or switch). Disabling a key means its interrupt line | |
71 | * is disabled. | |
72 | * | |
73 | * For example, if we have following switches set up as gpio-keys: | |
74 | * SW_DOCK = 5 | |
75 | * SW_CAMERA_LENS_COVER = 9 | |
76 | * SW_KEYPAD_SLIDE = 10 | |
77 | * SW_FRONT_PROXIMITY = 11 | |
78 | * This is read from switches: | |
79 | * 11-9,5 | |
80 | * Next we want to disable proximity (11) and dock (5), we write: | |
81 | * 11,5 | |
82 | * to file disabled_switches. Now proximity and dock IRQs are disabled. | |
83 | * This can be verified by reading the file disabled_switches: | |
84 | * 11,5 | |
85 | * If we now want to enable proximity (11) switch we write: | |
86 | * 5 | |
87 | * to disabled_switches. | |
88 | * | |
89 | * We can disable only those keys which don't allow sharing the irq. | |
90 | */ | |
91 | ||
92 | /** | |
93 | * get_n_events_by_type() - returns maximum number of events per @type | |
94 | * @type: type of button (%EV_KEY, %EV_SW) | |
95 | * | |
96 | * Return value of this function can be used to allocate bitmap | |
97 | * large enough to hold all bits for given type. | |
98 | */ | |
99 | static inline int get_n_events_by_type(int type) | |
100 | { | |
101 | BUG_ON(type != EV_SW && type != EV_KEY); | |
102 | ||
103 | return (type == EV_KEY) ? KEY_CNT : SW_CNT; | |
104 | } | |
105 | ||
106 | /** | |
107 | * gpio_keys_disable_button() - disables given GPIO button | |
108 | * @bdata: button data for button to be disabled | |
109 | * | |
110 | * Disables button pointed by @bdata. This is done by masking | |
111 | * IRQ line. After this function is called, button won't generate | |
112 | * input events anymore. Note that one can only disable buttons | |
113 | * that don't share IRQs. | |
114 | * | |
115 | * Make sure that @bdata->disable_lock is locked when entering | |
116 | * this function to avoid races when concurrent threads are | |
117 | * disabling buttons at the same time. | |
118 | */ | |
119 | static void gpio_keys_disable_button(struct gpio_button_data *bdata) | |
120 | { | |
121 | if (!bdata->disabled) { | |
122 | /* | |
8ed92556 | 123 | * Disable IRQ and associated timer/work structure. |
9e3af04f | 124 | */ |
d8ee4a1c | 125 | disable_irq(bdata->irq); |
8ed92556 DT |
126 | |
127 | if (gpio_is_valid(bdata->button->gpio)) | |
128 | cancel_delayed_work_sync(&bdata->work); | |
129 | else | |
130 | del_timer_sync(&bdata->release_timer); | |
9e3af04f MW |
131 | |
132 | bdata->disabled = true; | |
133 | } | |
134 | } | |
135 | ||
136 | /** | |
137 | * gpio_keys_enable_button() - enables given GPIO button | |
138 | * @bdata: button data for button to be disabled | |
139 | * | |
140 | * Enables given button pointed by @bdata. | |
141 | * | |
142 | * Make sure that @bdata->disable_lock is locked when entering | |
143 | * this function to avoid races with concurrent threads trying | |
144 | * to enable the same button at the same time. | |
145 | */ | |
146 | static void gpio_keys_enable_button(struct gpio_button_data *bdata) | |
147 | { | |
148 | if (bdata->disabled) { | |
d8ee4a1c | 149 | enable_irq(bdata->irq); |
9e3af04f MW |
150 | bdata->disabled = false; |
151 | } | |
152 | } | |
153 | ||
154 | /** | |
155 | * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons | |
156 | * @ddata: pointer to drvdata | |
157 | * @buf: buffer where stringified bitmap is written | |
158 | * @type: button type (%EV_KEY, %EV_SW) | |
159 | * @only_disabled: does caller want only those buttons that are | |
160 | * currently disabled or all buttons that can be | |
161 | * disabled | |
162 | * | |
163 | * This function writes buttons that can be disabled to @buf. If | |
164 | * @only_disabled is true, then @buf contains only those buttons | |
165 | * that are currently disabled. Returns 0 on success or negative | |
166 | * errno on failure. | |
167 | */ | |
168 | static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, | |
169 | char *buf, unsigned int type, | |
170 | bool only_disabled) | |
171 | { | |
172 | int n_events = get_n_events_by_type(type); | |
173 | unsigned long *bits; | |
174 | ssize_t ret; | |
175 | int i; | |
176 | ||
177 | bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); | |
178 | if (!bits) | |
179 | return -ENOMEM; | |
180 | ||
219edc71 | 181 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
9e3af04f MW |
182 | struct gpio_button_data *bdata = &ddata->data[i]; |
183 | ||
184 | if (bdata->button->type != type) | |
185 | continue; | |
186 | ||
187 | if (only_disabled && !bdata->disabled) | |
188 | continue; | |
189 | ||
190 | __set_bit(bdata->button->code, bits); | |
191 | } | |
192 | ||
0b480037 | 193 | ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); |
9e3af04f MW |
194 | buf[ret++] = '\n'; |
195 | buf[ret] = '\0'; | |
196 | ||
197 | kfree(bits); | |
198 | ||
199 | return ret; | |
200 | } | |
201 | ||
202 | /** | |
203 | * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap | |
204 | * @ddata: pointer to drvdata | |
205 | * @buf: buffer from userspace that contains stringified bitmap | |
206 | * @type: button type (%EV_KEY, %EV_SW) | |
207 | * | |
208 | * This function parses stringified bitmap from @buf and disables/enables | |
a16ca239 | 209 | * GPIO buttons accordingly. Returns 0 on success and negative error |
9e3af04f MW |
210 | * on failure. |
211 | */ | |
212 | static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, | |
213 | const char *buf, unsigned int type) | |
214 | { | |
215 | int n_events = get_n_events_by_type(type); | |
216 | unsigned long *bits; | |
217 | ssize_t error; | |
218 | int i; | |
219 | ||
220 | bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); | |
221 | if (!bits) | |
222 | return -ENOMEM; | |
223 | ||
224 | error = bitmap_parselist(buf, bits, n_events); | |
225 | if (error) | |
226 | goto out; | |
227 | ||
228 | /* First validate */ | |
219edc71 | 229 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
9e3af04f MW |
230 | struct gpio_button_data *bdata = &ddata->data[i]; |
231 | ||
232 | if (bdata->button->type != type) | |
233 | continue; | |
234 | ||
235 | if (test_bit(bdata->button->code, bits) && | |
236 | !bdata->button->can_disable) { | |
237 | error = -EINVAL; | |
238 | goto out; | |
239 | } | |
240 | } | |
241 | ||
242 | mutex_lock(&ddata->disable_lock); | |
243 | ||
219edc71 | 244 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
9e3af04f MW |
245 | struct gpio_button_data *bdata = &ddata->data[i]; |
246 | ||
247 | if (bdata->button->type != type) | |
248 | continue; | |
249 | ||
250 | if (test_bit(bdata->button->code, bits)) | |
251 | gpio_keys_disable_button(bdata); | |
252 | else | |
253 | gpio_keys_enable_button(bdata); | |
254 | } | |
255 | ||
256 | mutex_unlock(&ddata->disable_lock); | |
257 | ||
258 | out: | |
259 | kfree(bits); | |
260 | return error; | |
261 | } | |
262 | ||
263 | #define ATTR_SHOW_FN(name, type, only_disabled) \ | |
264 | static ssize_t gpio_keys_show_##name(struct device *dev, \ | |
265 | struct device_attribute *attr, \ | |
266 | char *buf) \ | |
267 | { \ | |
268 | struct platform_device *pdev = to_platform_device(dev); \ | |
269 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ | |
270 | \ | |
271 | return gpio_keys_attr_show_helper(ddata, buf, \ | |
272 | type, only_disabled); \ | |
273 | } | |
274 | ||
275 | ATTR_SHOW_FN(keys, EV_KEY, false); | |
276 | ATTR_SHOW_FN(switches, EV_SW, false); | |
277 | ATTR_SHOW_FN(disabled_keys, EV_KEY, true); | |
278 | ATTR_SHOW_FN(disabled_switches, EV_SW, true); | |
279 | ||
280 | /* | |
281 | * ATTRIBUTES: | |
282 | * | |
283 | * /sys/devices/platform/gpio-keys/keys [ro] | |
284 | * /sys/devices/platform/gpio-keys/switches [ro] | |
285 | */ | |
286 | static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); | |
287 | static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); | |
288 | ||
289 | #define ATTR_STORE_FN(name, type) \ | |
290 | static ssize_t gpio_keys_store_##name(struct device *dev, \ | |
291 | struct device_attribute *attr, \ | |
292 | const char *buf, \ | |
293 | size_t count) \ | |
294 | { \ | |
295 | struct platform_device *pdev = to_platform_device(dev); \ | |
296 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ | |
297 | ssize_t error; \ | |
298 | \ | |
299 | error = gpio_keys_attr_store_helper(ddata, buf, type); \ | |
300 | if (error) \ | |
301 | return error; \ | |
302 | \ | |
303 | return count; \ | |
304 | } | |
305 | ||
306 | ATTR_STORE_FN(disabled_keys, EV_KEY); | |
307 | ATTR_STORE_FN(disabled_switches, EV_SW); | |
308 | ||
309 | /* | |
310 | * ATTRIBUTES: | |
311 | * | |
312 | * /sys/devices/platform/gpio-keys/disabled_keys [rw] | |
313 | * /sys/devices/platform/gpio-keys/disables_switches [rw] | |
314 | */ | |
315 | static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, | |
316 | gpio_keys_show_disabled_keys, | |
317 | gpio_keys_store_disabled_keys); | |
318 | static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, | |
319 | gpio_keys_show_disabled_switches, | |
320 | gpio_keys_store_disabled_switches); | |
321 | ||
322 | static struct attribute *gpio_keys_attrs[] = { | |
323 | &dev_attr_keys.attr, | |
324 | &dev_attr_switches.attr, | |
325 | &dev_attr_disabled_keys.attr, | |
326 | &dev_attr_disabled_switches.attr, | |
327 | NULL, | |
328 | }; | |
329 | ||
330 | static struct attribute_group gpio_keys_attr_group = { | |
331 | .attrs = gpio_keys_attrs, | |
332 | }; | |
333 | ||
d8ee4a1c | 334 | static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) |
a33466e3 | 335 | { |
d9080921 | 336 | const struct gpio_keys_button *button = bdata->button; |
ce25d7e9 | 337 | struct input_dev *input = bdata->input; |
a33466e3 | 338 | unsigned int type = button->type ?: EV_KEY; |
94a8cab8 | 339 | int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; |
a33466e3 | 340 | |
92a47674 AS |
341 | if (type == EV_ABS) { |
342 | if (state) | |
343 | input_event(input, type, button->code, button->value); | |
344 | } else { | |
345 | input_event(input, type, button->code, !!state); | |
346 | } | |
a33466e3 DES |
347 | input_sync(input); |
348 | } | |
349 | ||
d8ee4a1c | 350 | static void gpio_keys_gpio_work_func(struct work_struct *work) |
6ee88d71 DM |
351 | { |
352 | struct gpio_button_data *bdata = | |
8ed92556 | 353 | container_of(work, struct gpio_button_data, work.work); |
6ee88d71 | 354 | |
d8ee4a1c | 355 | gpio_keys_gpio_report_event(bdata); |
2fba26c6 N |
356 | |
357 | if (bdata->button->wakeup) | |
358 | pm_relax(bdata->input->dev.parent); | |
6ee88d71 DM |
359 | } |
360 | ||
d8ee4a1c | 361 | static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) |
78a56aab | 362 | { |
57ffe9d5 | 363 | struct gpio_button_data *bdata = dev_id; |
78a56aab | 364 | |
d8ee4a1c | 365 | BUG_ON(irq != bdata->irq); |
84767d00 | 366 | |
2fba26c6 N |
367 | if (bdata->button->wakeup) |
368 | pm_stay_awake(bdata->input->dev.parent); | |
8ed92556 DT |
369 | |
370 | mod_delayed_work(system_wq, | |
371 | &bdata->work, | |
372 | msecs_to_jiffies(bdata->software_debounce)); | |
78a56aab | 373 | |
57ffe9d5 | 374 | return IRQ_HANDLED; |
78a56aab PB |
375 | } |
376 | ||
d8ee4a1c LD |
377 | static void gpio_keys_irq_timer(unsigned long _data) |
378 | { | |
379 | struct gpio_button_data *bdata = (struct gpio_button_data *)_data; | |
380 | struct input_dev *input = bdata->input; | |
381 | unsigned long flags; | |
382 | ||
383 | spin_lock_irqsave(&bdata->lock, flags); | |
384 | if (bdata->key_pressed) { | |
385 | input_event(input, EV_KEY, bdata->button->code, 0); | |
386 | input_sync(input); | |
387 | bdata->key_pressed = false; | |
388 | } | |
389 | spin_unlock_irqrestore(&bdata->lock, flags); | |
390 | } | |
391 | ||
392 | static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) | |
393 | { | |
394 | struct gpio_button_data *bdata = dev_id; | |
395 | const struct gpio_keys_button *button = bdata->button; | |
396 | struct input_dev *input = bdata->input; | |
397 | unsigned long flags; | |
398 | ||
399 | BUG_ON(irq != bdata->irq); | |
400 | ||
401 | spin_lock_irqsave(&bdata->lock, flags); | |
402 | ||
403 | if (!bdata->key_pressed) { | |
2fba26c6 N |
404 | if (bdata->button->wakeup) |
405 | pm_wakeup_event(bdata->input->dev.parent, 0); | |
406 | ||
d8ee4a1c LD |
407 | input_event(input, EV_KEY, button->code, 1); |
408 | input_sync(input); | |
409 | ||
8ed92556 | 410 | if (!bdata->release_delay) { |
d8ee4a1c LD |
411 | input_event(input, EV_KEY, button->code, 0); |
412 | input_sync(input); | |
413 | goto out; | |
414 | } | |
415 | ||
416 | bdata->key_pressed = true; | |
417 | } | |
418 | ||
8ed92556 DT |
419 | if (bdata->release_delay) |
420 | mod_timer(&bdata->release_timer, | |
421 | jiffies + msecs_to_jiffies(bdata->release_delay)); | |
d8ee4a1c LD |
422 | out: |
423 | spin_unlock_irqrestore(&bdata->lock, flags); | |
424 | return IRQ_HANDLED; | |
425 | } | |
426 | ||
27245519 AS |
427 | static void gpio_keys_quiesce_key(void *data) |
428 | { | |
429 | struct gpio_button_data *bdata = data; | |
430 | ||
8ed92556 DT |
431 | if (gpio_is_valid(bdata->button->gpio)) |
432 | cancel_delayed_work_sync(&bdata->work); | |
433 | else | |
434 | del_timer_sync(&bdata->release_timer); | |
27245519 AS |
435 | } |
436 | ||
5298cc4c BP |
437 | static int gpio_keys_setup_key(struct platform_device *pdev, |
438 | struct input_dev *input, | |
439 | struct gpio_button_data *bdata, | |
440 | const struct gpio_keys_button *button) | |
bc8f1eaf | 441 | { |
92a47674 | 442 | const char *desc = button->desc ? button->desc : "gpio_keys"; |
9e3af04f | 443 | struct device *dev = &pdev->dev; |
d8ee4a1c | 444 | irq_handler_t isr; |
9e3af04f | 445 | unsigned long irqflags; |
27245519 AS |
446 | int irq; |
447 | int error; | |
bc8f1eaf | 448 | |
d9080921 DT |
449 | bdata->input = input; |
450 | bdata->button = button; | |
d8ee4a1c | 451 | spin_lock_init(&bdata->lock); |
bc8f1eaf | 452 | |
d8ee4a1c | 453 | if (gpio_is_valid(button->gpio)) { |
bc8f1eaf | 454 | |
27245519 AS |
455 | error = devm_gpio_request_one(&pdev->dev, button->gpio, |
456 | GPIOF_IN, desc); | |
d8ee4a1c LD |
457 | if (error < 0) { |
458 | dev_err(dev, "Failed to request GPIO %d, error %d\n", | |
459 | button->gpio, error); | |
460 | return error; | |
461 | } | |
bc8f1eaf | 462 | |
d8ee4a1c LD |
463 | if (button->debounce_interval) { |
464 | error = gpio_set_debounce(button->gpio, | |
465 | button->debounce_interval * 1000); | |
466 | /* use timer if gpiolib doesn't provide debounce */ | |
467 | if (error < 0) | |
8ed92556 | 468 | bdata->software_debounce = |
d8ee4a1c LD |
469 | button->debounce_interval; |
470 | } | |
471 | ||
97d86e07 DT |
472 | if (button->irq) { |
473 | bdata->irq = button->irq; | |
474 | } else { | |
475 | irq = gpio_to_irq(button->gpio); | |
476 | if (irq < 0) { | |
477 | error = irq; | |
478 | dev_err(dev, | |
479 | "Unable to get irq number for GPIO %d, error %d\n", | |
480 | button->gpio, error); | |
481 | return error; | |
482 | } | |
483 | bdata->irq = irq; | |
d8ee4a1c | 484 | } |
d8ee4a1c | 485 | |
8ed92556 | 486 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); |
d8ee4a1c LD |
487 | |
488 | isr = gpio_keys_gpio_isr; | |
489 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | |
490 | ||
491 | } else { | |
492 | if (!button->irq) { | |
493 | dev_err(dev, "No IRQ specified\n"); | |
494 | return -EINVAL; | |
495 | } | |
496 | bdata->irq = button->irq; | |
497 | ||
498 | if (button->type && button->type != EV_KEY) { | |
499 | dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); | |
500 | return -EINVAL; | |
501 | } | |
502 | ||
8ed92556 DT |
503 | bdata->release_delay = button->debounce_interval; |
504 | setup_timer(&bdata->release_timer, | |
d8ee4a1c LD |
505 | gpio_keys_irq_timer, (unsigned long)bdata); |
506 | ||
507 | isr = gpio_keys_irq_isr; | |
508 | irqflags = 0; | |
bc8f1eaf BD |
509 | } |
510 | ||
d8ee4a1c LD |
511 | input_set_capability(input, button->type ?: EV_KEY, button->code); |
512 | ||
27245519 | 513 | /* |
8ed92556 | 514 | * Install custom action to cancel release timer and |
27245519 AS |
515 | * workqueue item. |
516 | */ | |
517 | error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); | |
518 | if (error) { | |
519 | dev_err(&pdev->dev, | |
520 | "failed to register quiesce action, error: %d\n", | |
521 | error); | |
522 | return error; | |
523 | } | |
524 | ||
9e3af04f MW |
525 | /* |
526 | * If platform has specified that the button can be disabled, | |
527 | * we don't want it to share the interrupt line. | |
528 | */ | |
529 | if (!button->can_disable) | |
530 | irqflags |= IRQF_SHARED; | |
531 | ||
27245519 AS |
532 | error = devm_request_any_context_irq(&pdev->dev, bdata->irq, |
533 | isr, irqflags, desc, bdata); | |
94a8cab8 | 534 | if (error < 0) { |
bc8f1eaf | 535 | dev_err(dev, "Unable to claim irq %d; error %d\n", |
d8ee4a1c | 536 | bdata->irq, error); |
27245519 | 537 | return error; |
bc8f1eaf BD |
538 | } |
539 | ||
540 | return 0; | |
bc8f1eaf BD |
541 | } |
542 | ||
5b76d7b4 DT |
543 | static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) |
544 | { | |
545 | struct input_dev *input = ddata->input; | |
546 | int i; | |
547 | ||
548 | for (i = 0; i < ddata->pdata->nbuttons; i++) { | |
549 | struct gpio_button_data *bdata = &ddata->data[i]; | |
550 | if (gpio_is_valid(bdata->button->gpio)) | |
551 | gpio_keys_gpio_report_event(bdata); | |
552 | } | |
553 | input_sync(input); | |
554 | } | |
555 | ||
173bdd74 S |
556 | static int gpio_keys_open(struct input_dev *input) |
557 | { | |
558 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | |
219edc71 | 559 | const struct gpio_keys_platform_data *pdata = ddata->pdata; |
5b76d7b4 DT |
560 | int error; |
561 | ||
562 | if (pdata->enable) { | |
563 | error = pdata->enable(input->dev.parent); | |
564 | if (error) | |
565 | return error; | |
566 | } | |
173bdd74 | 567 | |
5b76d7b4 DT |
568 | /* Report current state of buttons that are connected to GPIOs */ |
569 | gpio_keys_report_state(ddata); | |
570 | ||
571 | return 0; | |
173bdd74 S |
572 | } |
573 | ||
574 | static void gpio_keys_close(struct input_dev *input) | |
575 | { | |
576 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | |
219edc71 | 577 | const struct gpio_keys_platform_data *pdata = ddata->pdata; |
173bdd74 | 578 | |
219edc71 APS |
579 | if (pdata->disable) |
580 | pdata->disable(input->dev.parent); | |
173bdd74 S |
581 | } |
582 | ||
fd05d089 DJ |
583 | /* |
584 | * Handlers for alternative sources of platform_data | |
585 | */ | |
219edc71 | 586 | |
fd05d089 DJ |
587 | #ifdef CONFIG_OF |
588 | /* | |
589 | * Translate OpenFirmware node properties into platform_data | |
590 | */ | |
5298cc4c | 591 | static struct gpio_keys_platform_data * |
219edc71 | 592 | gpio_keys_get_devtree_pdata(struct device *dev) |
fd05d089 DJ |
593 | { |
594 | struct device_node *node, *pp; | |
219edc71 APS |
595 | struct gpio_keys_platform_data *pdata; |
596 | struct gpio_keys_button *button; | |
597 | int error; | |
598 | int nbuttons; | |
fd05d089 | 599 | int i; |
fd05d089 DJ |
600 | |
601 | node = dev->of_node; | |
5d422f2e AS |
602 | if (!node) |
603 | return ERR_PTR(-ENODEV); | |
fd05d089 | 604 | |
219edc71 | 605 | nbuttons = of_get_child_count(node); |
5d422f2e AS |
606 | if (nbuttons == 0) |
607 | return ERR_PTR(-ENODEV); | |
fd05d089 | 608 | |
5d422f2e AS |
609 | pdata = devm_kzalloc(dev, |
610 | sizeof(*pdata) + nbuttons * sizeof(*button), | |
611 | GFP_KERNEL); | |
612 | if (!pdata) | |
613 | return ERR_PTR(-ENOMEM); | |
fd05d089 | 614 | |
219edc71 APS |
615 | pdata->buttons = (struct gpio_keys_button *)(pdata + 1); |
616 | pdata->nbuttons = nbuttons; | |
fd05d089 | 617 | |
219edc71 | 618 | pdata->rep = !!of_get_property(node, "autorepeat", NULL); |
fd05d089 | 619 | |
fd05d089 | 620 | i = 0; |
219edc71 | 621 | for_each_child_of_node(node, pp) { |
fd05d089 DJ |
622 | enum of_gpio_flags flags; |
623 | ||
1d6a0136 | 624 | button = &pdata->buttons[i++]; |
fd05d089 | 625 | |
97d86e07 DT |
626 | button->gpio = of_get_gpio_flags(pp, 0, &flags); |
627 | if (button->gpio < 0) { | |
628 | error = button->gpio; | |
629 | if (error != -ENOENT) { | |
f2d347ff AS |
630 | if (error != -EPROBE_DEFER) |
631 | dev_err(dev, | |
632 | "Failed to get gpio flags, error: %d\n", | |
633 | error); | |
634 | return ERR_PTR(error); | |
635 | } | |
97d86e07 DT |
636 | } else { |
637 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | |
e324ce61 DT |
638 | } |
639 | ||
97d86e07 DT |
640 | button->irq = irq_of_parse_and_map(pp, 0); |
641 | ||
642 | if (!gpio_is_valid(button->gpio) && !button->irq) { | |
643 | dev_err(dev, "Found button without gpios or irqs\n"); | |
644 | return ERR_PTR(-EINVAL); | |
645 | } | |
fd05d089 | 646 | |
219edc71 APS |
647 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
648 | dev_err(dev, "Button without keycode: 0x%x\n", | |
649 | button->gpio); | |
5d422f2e | 650 | return ERR_PTR(-EINVAL); |
219edc71 | 651 | } |
fd05d089 | 652 | |
219edc71 | 653 | button->desc = of_get_property(pp, "label", NULL); |
fd05d089 | 654 | |
219edc71 APS |
655 | if (of_property_read_u32(pp, "linux,input-type", &button->type)) |
656 | button->type = EV_KEY; | |
657 | ||
658 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | |
fd05d089 | 659 | |
97d86e07 DT |
660 | button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL); |
661 | ||
219edc71 APS |
662 | if (of_property_read_u32(pp, "debounce-interval", |
663 | &button->debounce_interval)) | |
664 | button->debounce_interval = 5; | |
fd05d089 DJ |
665 | } |
666 | ||
5d422f2e AS |
667 | if (pdata->nbuttons == 0) |
668 | return ERR_PTR(-EINVAL); | |
fd05d089 | 669 | |
219edc71 | 670 | return pdata; |
fd05d089 DJ |
671 | } |
672 | ||
22daae31 | 673 | static const struct of_device_id gpio_keys_of_match[] = { |
fd05d089 DJ |
674 | { .compatible = "gpio-keys", }, |
675 | { }, | |
676 | }; | |
677 | MODULE_DEVICE_TABLE(of, gpio_keys_of_match); | |
678 | ||
679 | #else | |
680 | ||
219edc71 APS |
681 | static inline struct gpio_keys_platform_data * |
682 | gpio_keys_get_devtree_pdata(struct device *dev) | |
fd05d089 | 683 | { |
219edc71 | 684 | return ERR_PTR(-ENODEV); |
fd05d089 DJ |
685 | } |
686 | ||
fd05d089 DJ |
687 | #endif |
688 | ||
5298cc4c | 689 | static int gpio_keys_probe(struct platform_device *pdev) |
78a56aab | 690 | { |
db19fd8b | 691 | struct device *dev = &pdev->dev; |
219edc71 APS |
692 | const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); |
693 | struct gpio_keys_drvdata *ddata; | |
78a56aab | 694 | struct input_dev *input; |
5d422f2e | 695 | size_t size; |
78a56aab | 696 | int i, error; |
e15b0213 | 697 | int wakeup = 0; |
78a56aab | 698 | |
fd05d089 | 699 | if (!pdata) { |
219edc71 APS |
700 | pdata = gpio_keys_get_devtree_pdata(dev); |
701 | if (IS_ERR(pdata)) | |
702 | return PTR_ERR(pdata); | |
fd05d089 DJ |
703 | } |
704 | ||
5d422f2e AS |
705 | size = sizeof(struct gpio_keys_drvdata) + |
706 | pdata->nbuttons * sizeof(struct gpio_button_data); | |
707 | ddata = devm_kzalloc(dev, size, GFP_KERNEL); | |
708 | if (!ddata) { | |
db19fd8b | 709 | dev_err(dev, "failed to allocate state\n"); |
5d422f2e AS |
710 | return -ENOMEM; |
711 | } | |
712 | ||
713 | input = devm_input_allocate_device(dev); | |
714 | if (!input) { | |
715 | dev_err(dev, "failed to allocate input device\n"); | |
716 | return -ENOMEM; | |
a33466e3 | 717 | } |
78a56aab | 718 | |
219edc71 | 719 | ddata->pdata = pdata; |
9e3af04f | 720 | ddata->input = input; |
9e3af04f MW |
721 | mutex_init(&ddata->disable_lock); |
722 | ||
a33466e3 | 723 | platform_set_drvdata(pdev, ddata); |
173bdd74 | 724 | input_set_drvdata(input, ddata); |
78a56aab | 725 | |
46711277 | 726 | input->name = pdata->name ? : pdev->name; |
78a56aab | 727 | input->phys = "gpio-keys/input0"; |
469ba4df | 728 | input->dev.parent = &pdev->dev; |
173bdd74 S |
729 | input->open = gpio_keys_open; |
730 | input->close = gpio_keys_close; | |
78a56aab PB |
731 | |
732 | input->id.bustype = BUS_HOST; | |
733 | input->id.vendor = 0x0001; | |
734 | input->id.product = 0x0001; | |
735 | input->id.version = 0x0100; | |
736 | ||
b67b4b11 DC |
737 | /* Enable auto repeat feature of Linux input subsystem */ |
738 | if (pdata->rep) | |
739 | __set_bit(EV_REP, input->evbit); | |
740 | ||
78a56aab | 741 | for (i = 0; i < pdata->nbuttons; i++) { |
d9080921 | 742 | const struct gpio_keys_button *button = &pdata->buttons[i]; |
a33466e3 | 743 | struct gpio_button_data *bdata = &ddata->data[i]; |
78a56aab | 744 | |
d9080921 | 745 | error = gpio_keys_setup_key(pdev, input, bdata, button); |
bc8f1eaf | 746 | if (error) |
27245519 | 747 | return error; |
84767d00 | 748 | |
e15b0213 AS |
749 | if (button->wakeup) |
750 | wakeup = 1; | |
78a56aab PB |
751 | } |
752 | ||
9e3af04f | 753 | error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); |
78a56aab | 754 | if (error) { |
9e3af04f MW |
755 | dev_err(dev, "Unable to export keys/switches, error: %d\n", |
756 | error); | |
27245519 | 757 | return error; |
78a56aab PB |
758 | } |
759 | ||
9e3af04f MW |
760 | error = input_register_device(input); |
761 | if (error) { | |
762 | dev_err(dev, "Unable to register input device, error: %d\n", | |
763 | error); | |
27245519 | 764 | goto err_remove_group; |
9e3af04f MW |
765 | } |
766 | ||
e15b0213 AS |
767 | device_init_wakeup(&pdev->dev, wakeup); |
768 | ||
78a56aab PB |
769 | return 0; |
770 | ||
27245519 | 771 | err_remove_group: |
9e3af04f | 772 | sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); |
78a56aab PB |
773 | return error; |
774 | } | |
775 | ||
e2619cf7 | 776 | static int gpio_keys_remove(struct platform_device *pdev) |
78a56aab | 777 | { |
9e3af04f MW |
778 | sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); |
779 | ||
e15b0213 AS |
780 | device_init_wakeup(&pdev->dev, 0); |
781 | ||
78a56aab PB |
782 | return 0; |
783 | } | |
784 | ||
bdda8216 | 785 | #ifdef CONFIG_PM_SLEEP |
ae78e0e0 | 786 | static int gpio_keys_suspend(struct device *dev) |
e15b0213 | 787 | { |
fd05d089 | 788 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
dda19a92 | 789 | struct input_dev *input = ddata->input; |
e15b0213 AS |
790 | int i; |
791 | ||
fd05d089 | 792 | if (device_may_wakeup(dev)) { |
219edc71 | 793 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
d8ee4a1c LD |
794 | struct gpio_button_data *bdata = &ddata->data[i]; |
795 | if (bdata->button->wakeup) | |
796 | enable_irq_wake(bdata->irq); | |
e15b0213 | 797 | } |
dda19a92 JA |
798 | } else { |
799 | mutex_lock(&input->mutex); | |
800 | if (input->users) | |
801 | gpio_keys_close(input); | |
802 | mutex_unlock(&input->mutex); | |
e15b0213 AS |
803 | } |
804 | ||
805 | return 0; | |
806 | } | |
807 | ||
ae78e0e0 | 808 | static int gpio_keys_resume(struct device *dev) |
e15b0213 | 809 | { |
fd05d089 | 810 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
dda19a92 JA |
811 | struct input_dev *input = ddata->input; |
812 | int error = 0; | |
e15b0213 AS |
813 | int i; |
814 | ||
dda19a92 JA |
815 | if (device_may_wakeup(dev)) { |
816 | for (i = 0; i < ddata->pdata->nbuttons; i++) { | |
817 | struct gpio_button_data *bdata = &ddata->data[i]; | |
818 | if (bdata->button->wakeup) | |
819 | disable_irq_wake(bdata->irq); | |
820 | } | |
821 | } else { | |
822 | mutex_lock(&input->mutex); | |
823 | if (input->users) | |
824 | error = gpio_keys_open(input); | |
825 | mutex_unlock(&input->mutex); | |
e15b0213 | 826 | } |
5b76d7b4 | 827 | |
dda19a92 JA |
828 | if (error) |
829 | return error; | |
e15b0213 | 830 | |
dda19a92 | 831 | gpio_keys_report_state(ddata); |
e15b0213 AS |
832 | return 0; |
833 | } | |
e15b0213 AS |
834 | #endif |
835 | ||
bdda8216 DT |
836 | static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); |
837 | ||
9b07044c | 838 | static struct platform_driver gpio_keys_device_driver = { |
78a56aab | 839 | .probe = gpio_keys_probe, |
1cb0aa88 | 840 | .remove = gpio_keys_remove, |
78a56aab PB |
841 | .driver = { |
842 | .name = "gpio-keys", | |
ae78e0e0 | 843 | .pm = &gpio_keys_pm_ops, |
219edc71 | 844 | .of_match_table = of_match_ptr(gpio_keys_of_match), |
78a56aab PB |
845 | } |
846 | }; | |
847 | ||
848 | static int __init gpio_keys_init(void) | |
849 | { | |
850 | return platform_driver_register(&gpio_keys_device_driver); | |
851 | } | |
852 | ||
853 | static void __exit gpio_keys_exit(void) | |
854 | { | |
855 | platform_driver_unregister(&gpio_keys_device_driver); | |
856 | } | |
857 | ||
b2330205 | 858 | late_initcall(gpio_keys_init); |
78a56aab PB |
859 | module_exit(gpio_keys_exit); |
860 | ||
861 | MODULE_LICENSE("GPL"); | |
862 | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); | |
7e2ecdf4 | 863 | MODULE_DESCRIPTION("Keyboard driver for GPIOs"); |
d7b5247b | 864 | MODULE_ALIAS("platform:gpio-keys"); |