blob: 2b708aa85553358a2b375cbb602fb07d1ea36c02 [file] [log] [blame]
Phil Blundell78a56aa2007-01-18 00:44:09 -05001/*
2 * Driver for keys on GPIO lines capable of generating interrupts.
3 *
4 * Copyright 2005 Phil Blundell
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/module.h>
Phil Blundell78a56aa2007-01-18 00:44:09 -050012
13#include <linux/init.h>
14#include <linux/fs.h>
15#include <linux/interrupt.h>
16#include <linux/irq.h>
17#include <linux/sched.h>
18#include <linux/pm.h>
19#include <linux/sysctl.h>
20#include <linux/proc_fs.h>
21#include <linux/delay.h>
22#include <linux/platform_device.h>
23#include <linux/input.h>
David Brownell49015be2007-03-05 00:30:22 -080024#include <linux/gpio_keys.h>
Jani Nikulada0d03f2009-06-28 22:38:56 -070025#include <linux/workqueue.h>
Ben Dooks111bc592009-11-10 21:01:31 -080026#include <linux/gpio.h>
Phil Blundell78a56aa2007-01-18 00:44:09 -050027
Dmitry Baryshkova33466e2008-05-07 16:30:15 -040028struct gpio_button_data {
29 struct gpio_keys_button *button;
30 struct input_dev *input;
Jani Nikulaca865a72009-06-28 22:38:44 -070031 struct timer_list timer;
Jani Nikulada0d03f2009-06-28 22:38:56 -070032 struct work_struct work;
Mika Westerberg9e3af042010-02-04 00:48:00 -080033 bool disabled;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -040034};
35
36struct gpio_keys_drvdata {
37 struct input_dev *input;
Mika Westerberg9e3af042010-02-04 00:48:00 -080038 struct mutex disable_lock;
39 unsigned int n_buttons;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -040040 struct gpio_button_data data[0];
41};
42
Mika Westerberg9e3af042010-02-04 00:48:00 -080043/*
44 * SYSFS interface for enabling/disabling keys and switches:
45 *
46 * There are 4 attributes under /sys/devices/platform/gpio-keys/
47 * keys [ro] - bitmap of keys (EV_KEY) which can be
48 * disabled
49 * switches [ro] - bitmap of switches (EV_SW) which can be
50 * disabled
51 * disabled_keys [rw] - bitmap of keys currently disabled
52 * disabled_switches [rw] - bitmap of switches currently disabled
53 *
54 * Userland can change these values and hence disable event generation
55 * for each key (or switch). Disabling a key means its interrupt line
56 * is disabled.
57 *
58 * For example, if we have following switches set up as gpio-keys:
59 * SW_DOCK = 5
60 * SW_CAMERA_LENS_COVER = 9
61 * SW_KEYPAD_SLIDE = 10
62 * SW_FRONT_PROXIMITY = 11
63 * This is read from switches:
64 * 11-9,5
65 * Next we want to disable proximity (11) and dock (5), we write:
66 * 11,5
67 * to file disabled_switches. Now proximity and dock IRQs are disabled.
68 * This can be verified by reading the file disabled_switches:
69 * 11,5
70 * If we now want to enable proximity (11) switch we write:
71 * 5
72 * to disabled_switches.
73 *
74 * We can disable only those keys which don't allow sharing the irq.
75 */
76
77/**
78 * get_n_events_by_type() - returns maximum number of events per @type
79 * @type: type of button (%EV_KEY, %EV_SW)
80 *
81 * Return value of this function can be used to allocate bitmap
82 * large enough to hold all bits for given type.
83 */
84static inline int get_n_events_by_type(int type)
85{
86 BUG_ON(type != EV_SW && type != EV_KEY);
87
88 return (type == EV_KEY) ? KEY_CNT : SW_CNT;
89}
90
91/**
92 * gpio_keys_disable_button() - disables given GPIO button
93 * @bdata: button data for button to be disabled
94 *
95 * Disables button pointed by @bdata. This is done by masking
96 * IRQ line. After this function is called, button won't generate
97 * input events anymore. Note that one can only disable buttons
98 * that don't share IRQs.
99 *
100 * Make sure that @bdata->disable_lock is locked when entering
101 * this function to avoid races when concurrent threads are
102 * disabling buttons at the same time.
103 */
104static void gpio_keys_disable_button(struct gpio_button_data *bdata)
105{
106 if (!bdata->disabled) {
107 /*
108 * Disable IRQ and possible debouncing timer.
109 */
110 disable_irq(gpio_to_irq(bdata->button->gpio));
111 if (bdata->button->debounce_interval)
112 del_timer_sync(&bdata->timer);
113
114 bdata->disabled = true;
115 }
116}
117
118/**
119 * gpio_keys_enable_button() - enables given GPIO button
120 * @bdata: button data for button to be disabled
121 *
122 * Enables given button pointed by @bdata.
123 *
124 * Make sure that @bdata->disable_lock is locked when entering
125 * this function to avoid races with concurrent threads trying
126 * to enable the same button at the same time.
127 */
128static void gpio_keys_enable_button(struct gpio_button_data *bdata)
129{
130 if (bdata->disabled) {
131 enable_irq(gpio_to_irq(bdata->button->gpio));
132 bdata->disabled = false;
133 }
134}
135
136/**
137 * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons
138 * @ddata: pointer to drvdata
139 * @buf: buffer where stringified bitmap is written
140 * @type: button type (%EV_KEY, %EV_SW)
141 * @only_disabled: does caller want only those buttons that are
142 * currently disabled or all buttons that can be
143 * disabled
144 *
145 * This function writes buttons that can be disabled to @buf. If
146 * @only_disabled is true, then @buf contains only those buttons
147 * that are currently disabled. Returns 0 on success or negative
148 * errno on failure.
149 */
150static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
151 char *buf, unsigned int type,
152 bool only_disabled)
153{
154 int n_events = get_n_events_by_type(type);
155 unsigned long *bits;
156 ssize_t ret;
157 int i;
158
159 bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
160 if (!bits)
161 return -ENOMEM;
162
163 for (i = 0; i < ddata->n_buttons; i++) {
164 struct gpio_button_data *bdata = &ddata->data[i];
165
166 if (bdata->button->type != type)
167 continue;
168
169 if (only_disabled && !bdata->disabled)
170 continue;
171
172 __set_bit(bdata->button->code, bits);
173 }
174
175 ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events);
176 buf[ret++] = '\n';
177 buf[ret] = '\0';
178
179 kfree(bits);
180
181 return ret;
182}
183
184/**
185 * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap
186 * @ddata: pointer to drvdata
187 * @buf: buffer from userspace that contains stringified bitmap
188 * @type: button type (%EV_KEY, %EV_SW)
189 *
190 * This function parses stringified bitmap from @buf and disables/enables
191 * GPIO buttons accordinly. Returns 0 on success and negative error
192 * on failure.
193 */
194static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
195 const char *buf, unsigned int type)
196{
197 int n_events = get_n_events_by_type(type);
198 unsigned long *bits;
199 ssize_t error;
200 int i;
201
202 bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
203 if (!bits)
204 return -ENOMEM;
205
206 error = bitmap_parselist(buf, bits, n_events);
207 if (error)
208 goto out;
209
210 /* First validate */
211 for (i = 0; i < ddata->n_buttons; i++) {
212 struct gpio_button_data *bdata = &ddata->data[i];
213
214 if (bdata->button->type != type)
215 continue;
216
217 if (test_bit(bdata->button->code, bits) &&
218 !bdata->button->can_disable) {
219 error = -EINVAL;
220 goto out;
221 }
222 }
223
224 mutex_lock(&ddata->disable_lock);
225
226 for (i = 0; i < ddata->n_buttons; i++) {
227 struct gpio_button_data *bdata = &ddata->data[i];
228
229 if (bdata->button->type != type)
230 continue;
231
232 if (test_bit(bdata->button->code, bits))
233 gpio_keys_disable_button(bdata);
234 else
235 gpio_keys_enable_button(bdata);
236 }
237
238 mutex_unlock(&ddata->disable_lock);
239
240out:
241 kfree(bits);
242 return error;
243}
244
245#define ATTR_SHOW_FN(name, type, only_disabled) \
246static ssize_t gpio_keys_show_##name(struct device *dev, \
247 struct device_attribute *attr, \
248 char *buf) \
249{ \
250 struct platform_device *pdev = to_platform_device(dev); \
251 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
252 \
253 return gpio_keys_attr_show_helper(ddata, buf, \
254 type, only_disabled); \
255}
256
257ATTR_SHOW_FN(keys, EV_KEY, false);
258ATTR_SHOW_FN(switches, EV_SW, false);
259ATTR_SHOW_FN(disabled_keys, EV_KEY, true);
260ATTR_SHOW_FN(disabled_switches, EV_SW, true);
261
262/*
263 * ATTRIBUTES:
264 *
265 * /sys/devices/platform/gpio-keys/keys [ro]
266 * /sys/devices/platform/gpio-keys/switches [ro]
267 */
268static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL);
269static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL);
270
271#define ATTR_STORE_FN(name, type) \
272static ssize_t gpio_keys_store_##name(struct device *dev, \
273 struct device_attribute *attr, \
274 const char *buf, \
275 size_t count) \
276{ \
277 struct platform_device *pdev = to_platform_device(dev); \
278 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
279 ssize_t error; \
280 \
281 error = gpio_keys_attr_store_helper(ddata, buf, type); \
282 if (error) \
283 return error; \
284 \
285 return count; \
286}
287
288ATTR_STORE_FN(disabled_keys, EV_KEY);
289ATTR_STORE_FN(disabled_switches, EV_SW);
290
291/*
292 * ATTRIBUTES:
293 *
294 * /sys/devices/platform/gpio-keys/disabled_keys [rw]
295 * /sys/devices/platform/gpio-keys/disables_switches [rw]
296 */
297static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO,
298 gpio_keys_show_disabled_keys,
299 gpio_keys_store_disabled_keys);
300static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO,
301 gpio_keys_show_disabled_switches,
302 gpio_keys_store_disabled_switches);
303
304static struct attribute *gpio_keys_attrs[] = {
305 &dev_attr_keys.attr,
306 &dev_attr_switches.attr,
307 &dev_attr_disabled_keys.attr,
308 &dev_attr_disabled_switches.attr,
309 NULL,
310};
311
312static struct attribute_group gpio_keys_attr_group = {
313 .attrs = gpio_keys_attrs,
314};
315
Daniel Mack6ee88d72009-11-30 00:04:02 -0800316static void gpio_keys_report_event(struct gpio_button_data *bdata)
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400317{
Uwe Kleine-Königce25d7e2008-08-08 12:14:36 -0400318 struct gpio_keys_button *button = bdata->button;
319 struct input_dev *input = bdata->input;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400320 unsigned int type = button->type ?: EV_KEY;
321 int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
322
323 input_event(input, type, button->code, !!state);
324 input_sync(input);
325}
326
Daniel Mack6ee88d72009-11-30 00:04:02 -0800327static void gpio_keys_work_func(struct work_struct *work)
328{
329 struct gpio_button_data *bdata =
330 container_of(work, struct gpio_button_data, work);
331
332 gpio_keys_report_event(bdata);
333}
334
Jani Nikulada0d03f2009-06-28 22:38:56 -0700335static void gpio_keys_timer(unsigned long _data)
Jani Nikulaca865a72009-06-28 22:38:44 -0700336{
337 struct gpio_button_data *data = (struct gpio_button_data *)_data;
338
Jani Nikulada0d03f2009-06-28 22:38:56 -0700339 schedule_work(&data->work);
Jani Nikulaca865a72009-06-28 22:38:44 -0700340}
341
Phil Blundell78a56aa2007-01-18 00:44:09 -0500342static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
343{
Uwe Kleine-König57ffe9d2008-08-08 12:14:34 -0400344 struct gpio_button_data *bdata = dev_id;
345 struct gpio_keys_button *button = bdata->button;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500346
Uwe Kleine-König57ffe9d2008-08-08 12:14:34 -0400347 BUG_ON(irq != gpio_to_irq(button->gpio));
Phil Blundell78a56aa2007-01-18 00:44:09 -0500348
Jani Nikulaca865a72009-06-28 22:38:44 -0700349 if (button->debounce_interval)
350 mod_timer(&bdata->timer,
351 jiffies + msecs_to_jiffies(button->debounce_interval));
352 else
Jani Nikulada0d03f2009-06-28 22:38:56 -0700353 schedule_work(&bdata->work);
Roman Moravcik84767d02007-05-01 00:39:13 -0400354
Uwe Kleine-König57ffe9d2008-08-08 12:14:34 -0400355 return IRQ_HANDLED;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500356}
357
Mika Westerberg9e3af042010-02-04 00:48:00 -0800358static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
Ben Dooksbc8f1ea2009-11-10 21:01:31 -0800359 struct gpio_button_data *bdata,
360 struct gpio_keys_button *button)
361{
362 char *desc = button->desc ? button->desc : "gpio_keys";
Mika Westerberg9e3af042010-02-04 00:48:00 -0800363 struct device *dev = &pdev->dev;
364 unsigned long irqflags;
Ben Dooksbc8f1ea2009-11-10 21:01:31 -0800365 int irq, error;
366
367 setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
Daniel Mack6ee88d72009-11-30 00:04:02 -0800368 INIT_WORK(&bdata->work, gpio_keys_work_func);
Ben Dooksbc8f1ea2009-11-10 21:01:31 -0800369
370 error = gpio_request(button->gpio, desc);
371 if (error < 0) {
372 dev_err(dev, "failed to request GPIO %d, error %d\n",
373 button->gpio, error);
374 goto fail2;
375 }
376
377 error = gpio_direction_input(button->gpio);
378 if (error < 0) {
379 dev_err(dev, "failed to configure"
380 " direction for GPIO %d, error %d\n",
381 button->gpio, error);
382 goto fail3;
383 }
384
385 irq = gpio_to_irq(button->gpio);
386 if (irq < 0) {
387 error = irq;
388 dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n",
389 button->gpio, error);
390 goto fail3;
391 }
392
Mika Westerberg9e3af042010-02-04 00:48:00 -0800393 irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
394 /*
395 * If platform has specified that the button can be disabled,
396 * we don't want it to share the interrupt line.
397 */
398 if (!button->can_disable)
399 irqflags |= IRQF_SHARED;
400
401 error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
Ben Dooksbc8f1ea2009-11-10 21:01:31 -0800402 if (error) {
403 dev_err(dev, "Unable to claim irq %d; error %d\n",
404 irq, error);
405 goto fail3;
406 }
407
408 return 0;
409
410fail3:
411 gpio_free(button->gpio);
412fail2:
413 return error;
414}
415
Phil Blundell78a56aa2007-01-18 00:44:09 -0500416static int __devinit gpio_keys_probe(struct platform_device *pdev)
417{
418 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400419 struct gpio_keys_drvdata *ddata;
Ben Dooksdb19fd82009-11-10 21:00:35 -0800420 struct device *dev = &pdev->dev;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500421 struct input_dev *input;
422 int i, error;
Anti Sulline15b0212007-09-26 00:01:17 -0400423 int wakeup = 0;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500424
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400425 ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
426 pdata->nbuttons * sizeof(struct gpio_button_data),
427 GFP_KERNEL);
Phil Blundell78a56aa2007-01-18 00:44:09 -0500428 input = input_allocate_device();
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400429 if (!ddata || !input) {
Ben Dooksdb19fd82009-11-10 21:00:35 -0800430 dev_err(dev, "failed to allocate state\n");
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400431 error = -ENOMEM;
432 goto fail1;
433 }
Phil Blundell78a56aa2007-01-18 00:44:09 -0500434
Mika Westerberg9e3af042010-02-04 00:48:00 -0800435 ddata->input = input;
436 ddata->n_buttons = pdata->nbuttons;
437 mutex_init(&ddata->disable_lock);
438
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400439 platform_set_drvdata(pdev, ddata);
Phil Blundell78a56aa2007-01-18 00:44:09 -0500440
441 input->name = pdev->name;
442 input->phys = "gpio-keys/input0";
Dmitry Torokhov469ba4d2007-04-12 01:34:58 -0400443 input->dev.parent = &pdev->dev;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500444
445 input->id.bustype = BUS_HOST;
446 input->id.vendor = 0x0001;
447 input->id.product = 0x0001;
448 input->id.version = 0x0100;
449
Dominic Curranb67b4b12008-10-27 22:30:53 -0400450 /* Enable auto repeat feature of Linux input subsystem */
451 if (pdata->rep)
452 __set_bit(EV_REP, input->evbit);
453
Phil Blundell78a56aa2007-01-18 00:44:09 -0500454 for (i = 0; i < pdata->nbuttons; i++) {
Roman Moravcik84767d02007-05-01 00:39:13 -0400455 struct gpio_keys_button *button = &pdata->buttons[i];
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400456 struct gpio_button_data *bdata = &ddata->data[i];
Roman Moravcik84767d02007-05-01 00:39:13 -0400457 unsigned int type = button->type ?: EV_KEY;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500458
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400459 bdata->input = input;
Uwe Kleine-König74dd4392008-07-30 10:33:43 -0400460 bdata->button = button;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400461
Mika Westerberg9e3af042010-02-04 00:48:00 -0800462 error = gpio_keys_setup_key(pdev, bdata, button);
Ben Dooksbc8f1ea2009-11-10 21:01:31 -0800463 if (error)
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400464 goto fail2;
Roman Moravcik84767d02007-05-01 00:39:13 -0400465
Anti Sulline15b0212007-09-26 00:01:17 -0400466 if (button->wakeup)
467 wakeup = 1;
468
Roman Moravcik84767d02007-05-01 00:39:13 -0400469 input_set_capability(input, type, button->code);
Phil Blundell78a56aa2007-01-18 00:44:09 -0500470 }
471
Mika Westerberg9e3af042010-02-04 00:48:00 -0800472 error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
473 if (error) {
474 dev_err(dev, "Unable to export keys/switches, error: %d\n",
475 error);
476 goto fail2;
477 }
478
Phil Blundell78a56aa2007-01-18 00:44:09 -0500479 error = input_register_device(input);
480 if (error) {
Mika Westerberg9e3af042010-02-04 00:48:00 -0800481 dev_err(dev, "Unable to register input device, error: %d\n",
482 error);
483 goto fail3;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500484 }
485
Daniel Mack6ee88d72009-11-30 00:04:02 -0800486 /* get current state of buttons */
487 for (i = 0; i < pdata->nbuttons; i++)
488 gpio_keys_report_event(&ddata->data[i]);
489 input_sync(input);
490
Anti Sulline15b0212007-09-26 00:01:17 -0400491 device_init_wakeup(&pdev->dev, wakeup);
492
Phil Blundell78a56aa2007-01-18 00:44:09 -0500493 return 0;
494
Mika Westerberg9e3af042010-02-04 00:48:00 -0800495 fail3:
496 sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400497 fail2:
Herbert Valerio Riedel6a2e3912007-11-21 14:42:33 -0500498 while (--i >= 0) {
Uwe Kleine-König57ffe9d2008-08-08 12:14:34 -0400499 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
Jani Nikulaca865a72009-06-28 22:38:44 -0700500 if (pdata->buttons[i].debounce_interval)
501 del_timer_sync(&ddata->data[i].timer);
Jani Nikulada0d03f2009-06-28 22:38:56 -0700502 cancel_work_sync(&ddata->data[i].work);
Herbert Valerio Riedel6a2e3912007-11-21 14:42:33 -0500503 gpio_free(pdata->buttons[i].gpio);
504 }
Phil Blundell78a56aa2007-01-18 00:44:09 -0500505
Anti Sullin006df302007-09-26 00:01:03 -0400506 platform_set_drvdata(pdev, NULL);
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400507 fail1:
Phil Blundell78a56aa2007-01-18 00:44:09 -0500508 input_free_device(input);
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400509 kfree(ddata);
Phil Blundell78a56aa2007-01-18 00:44:09 -0500510
511 return error;
512}
513
514static int __devexit gpio_keys_remove(struct platform_device *pdev)
515{
516 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
Dmitry Baryshkova33466e2008-05-07 16:30:15 -0400517 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
518 struct input_dev *input = ddata->input;
Phil Blundell78a56aa2007-01-18 00:44:09 -0500519 int i;
520
Mika Westerberg9e3af042010-02-04 00:48:00 -0800521 sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
522
Anti Sulline15b0212007-09-26 00:01:17 -0400523 device_init_wakeup(&pdev->dev, 0);
524
Phil Blundell78a56aa2007-01-18 00:44:09 -0500525 for (i = 0; i < pdata->nbuttons; i++) {
Philipp Zabel0d98f6b2007-02-18 01:40:46 -0500526 int irq = gpio_to_irq(pdata->buttons[i].gpio);
Uwe Kleine-König57ffe9d2008-08-08 12:14:34 -0400527 free_irq(irq, &ddata->data[i]);
Jani Nikulaca865a72009-06-28 22:38:44 -0700528 if (pdata->buttons[i].debounce_interval)
529 del_timer_sync(&ddata->data[i].timer);
Jani Nikulada0d03f2009-06-28 22:38:56 -0700530 cancel_work_sync(&ddata->data[i].work);
Herbert Valerio Riedel6a2e3912007-11-21 14:42:33 -0500531 gpio_free(pdata->buttons[i].gpio);
Phil Blundell78a56aa2007-01-18 00:44:09 -0500532 }
533
534 input_unregister_device(input);
535
536 return 0;
537}
538
Anti Sulline15b0212007-09-26 00:01:17 -0400539
540#ifdef CONFIG_PM
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700541static int gpio_keys_suspend(struct device *dev)
Anti Sulline15b0212007-09-26 00:01:17 -0400542{
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700543 struct platform_device *pdev = to_platform_device(dev);
Anti Sulline15b0212007-09-26 00:01:17 -0400544 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
545 int i;
546
547 if (device_may_wakeup(&pdev->dev)) {
548 for (i = 0; i < pdata->nbuttons; i++) {
549 struct gpio_keys_button *button = &pdata->buttons[i];
550 if (button->wakeup) {
551 int irq = gpio_to_irq(button->gpio);
552 enable_irq_wake(irq);
553 }
554 }
555 }
556
557 return 0;
558}
559
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700560static int gpio_keys_resume(struct device *dev)
Anti Sulline15b0212007-09-26 00:01:17 -0400561{
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700562 struct platform_device *pdev = to_platform_device(dev);
Daniel Mack6ee88d72009-11-30 00:04:02 -0800563 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
Anti Sulline15b0212007-09-26 00:01:17 -0400564 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
565 int i;
566
Daniel Mack6ee88d72009-11-30 00:04:02 -0800567 for (i = 0; i < pdata->nbuttons; i++) {
568
569 struct gpio_keys_button *button = &pdata->buttons[i];
570 if (button->wakeup && device_may_wakeup(&pdev->dev)) {
571 int irq = gpio_to_irq(button->gpio);
572 disable_irq_wake(irq);
Anti Sulline15b0212007-09-26 00:01:17 -0400573 }
Daniel Mack6ee88d72009-11-30 00:04:02 -0800574
575 gpio_keys_report_event(&ddata->data[i]);
Anti Sulline15b0212007-09-26 00:01:17 -0400576 }
Daniel Mack6ee88d72009-11-30 00:04:02 -0800577 input_sync(ddata->input);
Anti Sulline15b0212007-09-26 00:01:17 -0400578
579 return 0;
580}
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700581
582static const struct dev_pm_ops gpio_keys_pm_ops = {
583 .suspend = gpio_keys_suspend,
584 .resume = gpio_keys_resume,
585};
Anti Sulline15b0212007-09-26 00:01:17 -0400586#endif
587
Uwe Kleine-König9b070442008-07-30 10:34:02 -0400588static struct platform_driver gpio_keys_device_driver = {
Phil Blundell78a56aa2007-01-18 00:44:09 -0500589 .probe = gpio_keys_probe,
590 .remove = __devexit_p(gpio_keys_remove),
Phil Blundell78a56aa2007-01-18 00:44:09 -0500591 .driver = {
592 .name = "gpio-keys",
Kay Sieversd7b52472008-04-18 00:24:42 -0400593 .owner = THIS_MODULE,
Mike Rapoportae78e0e2009-07-22 23:02:54 -0700594#ifdef CONFIG_PM
595 .pm = &gpio_keys_pm_ops,
596#endif
Phil Blundell78a56aa2007-01-18 00:44:09 -0500597 }
598};
599
600static int __init gpio_keys_init(void)
601{
602 return platform_driver_register(&gpio_keys_device_driver);
603}
604
605static void __exit gpio_keys_exit(void)
606{
607 platform_driver_unregister(&gpio_keys_device_driver);
608}
609
610module_init(gpio_keys_init);
611module_exit(gpio_keys_exit);
612
613MODULE_LICENSE("GPL");
614MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
615MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
Kay Sieversd7b52472008-04-18 00:24:42 -0400616MODULE_ALIAS("platform:gpio-keys");