blob: 4e428199e580f36c1c9228870d8b4b1a8d02ef0f [file] [log] [blame]
Gabor Juhos0e7d0c82010-12-06 17:14:47 -08001/*
2 * Driver for buttons on GPIO lines not capable of generating interrupts
3 *
4 * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
6 *
7 * This file was based on: /drivers/input/misc/cobalt_btns.c
8 * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
9 *
10 * also was based on: /drivers/input/keyboard/gpio_keys.c
11 * Copyright 2005 Phil Blundell
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/slab.h>
22#include <linux/input.h>
23#include <linux/input-polldev.h>
24#include <linux/ioport.h>
25#include <linux/platform_device.h>
26#include <linux/gpio.h>
27#include <linux/gpio_keys.h>
Sachin Kamat27801702013-10-06 00:55:33 -070028#include <linux/of.h>
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -070029#include <linux/of_platform.h>
30#include <linux/of_gpio.h>
Gabor Juhos0e7d0c82010-12-06 17:14:47 -080031
32#define DRV_NAME "gpio-keys-polled"
33
34struct gpio_keys_button_data {
35 int last_state;
36 int count;
37 int threshold;
38 int can_sleep;
39};
40
41struct gpio_keys_polled_dev {
42 struct input_polled_dev *poll_dev;
43 struct device *dev;
Dmitry Torokhov2976f242012-07-29 22:48:33 -070044 const struct gpio_keys_platform_data *pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -080045 struct gpio_keys_button_data data[0];
46};
47
48static void gpio_keys_polled_check_state(struct input_dev *input,
49 struct gpio_keys_button *button,
50 struct gpio_keys_button_data *bdata)
51{
52 int state;
53
54 if (bdata->can_sleep)
55 state = !!gpio_get_value_cansleep(button->gpio);
56 else
57 state = !!gpio_get_value(button->gpio);
58
59 if (state != bdata->last_state) {
60 unsigned int type = button->type ?: EV_KEY;
61
62 input_event(input, type, button->code,
63 !!(state ^ button->active_low));
64 input_sync(input);
65 bdata->count = 0;
66 bdata->last_state = state;
67 }
68}
69
70static void gpio_keys_polled_poll(struct input_polled_dev *dev)
71{
72 struct gpio_keys_polled_dev *bdev = dev->private;
Dmitry Torokhov2976f242012-07-29 22:48:33 -070073 const struct gpio_keys_platform_data *pdata = bdev->pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -080074 struct input_dev *input = dev->input;
75 int i;
76
Dmitry Torokhov2976f242012-07-29 22:48:33 -070077 for (i = 0; i < pdata->nbuttons; i++) {
Gabor Juhos0e7d0c82010-12-06 17:14:47 -080078 struct gpio_keys_button_data *bdata = &bdev->data[i];
79
80 if (bdata->count < bdata->threshold)
81 bdata->count++;
82 else
83 gpio_keys_polled_check_state(input, &pdata->buttons[i],
84 bdata);
85 }
86}
87
88static void gpio_keys_polled_open(struct input_polled_dev *dev)
89{
90 struct gpio_keys_polled_dev *bdev = dev->private;
Dmitry Torokhov2976f242012-07-29 22:48:33 -070091 const struct gpio_keys_platform_data *pdata = bdev->pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -080092
93 if (pdata->enable)
94 pdata->enable(bdev->dev);
95}
96
97static void gpio_keys_polled_close(struct input_polled_dev *dev)
98{
99 struct gpio_keys_polled_dev *bdev = dev->private;
Dmitry Torokhov2976f242012-07-29 22:48:33 -0700100 const struct gpio_keys_platform_data *pdata = bdev->pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800101
102 if (pdata->disable)
103 pdata->disable(bdev->dev);
104}
105
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700106#ifdef CONFIG_OF
Bill Pemberton5298cc42012-11-23 21:38:25 -0800107static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700108{
109 struct device_node *node, *pp;
110 struct gpio_keys_platform_data *pdata;
111 struct gpio_keys_button *button;
112 int error;
113 int nbuttons;
114 int i;
115
116 node = dev->of_node;
117 if (!node)
118 return NULL;
119
120 nbuttons = of_get_child_count(node);
121 if (nbuttons == 0)
122 return NULL;
123
124 pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
125 GFP_KERNEL);
126 if (!pdata) {
127 error = -ENOMEM;
128 goto err_out;
129 }
130
131 pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
Alexandre Pereira da Silva87571452012-09-12 21:49:26 -0700132 pdata->nbuttons = nbuttons;
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700133
134 pdata->rep = !!of_get_property(node, "autorepeat", NULL);
135 of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
136
137 i = 0;
138 for_each_child_of_node(node, pp) {
Gabor Juhosd46329a2012-12-23 01:54:58 -0800139 int gpio;
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700140 enum of_gpio_flags flags;
141
142 if (!of_find_property(pp, "gpios", NULL)) {
143 pdata->nbuttons--;
144 dev_warn(dev, "Found button without gpios\n");
145 continue;
146 }
147
Gabor Juhosd46329a2012-12-23 01:54:58 -0800148 gpio = of_get_gpio_flags(pp, 0, &flags);
149 if (gpio < 0) {
150 error = gpio;
151 if (error != -EPROBE_DEFER)
152 dev_err(dev,
153 "Failed to get gpio flags, error: %d\n",
154 error);
155 goto err_free_pdata;
156 }
157
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700158 button = &pdata->buttons[i++];
159
Gabor Juhosd46329a2012-12-23 01:54:58 -0800160 button->gpio = gpio;
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700161 button->active_low = flags & OF_GPIO_ACTIVE_LOW;
162
163 if (of_property_read_u32(pp, "linux,code", &button->code)) {
164 dev_err(dev, "Button without keycode: 0x%x\n",
165 button->gpio);
166 error = -EINVAL;
167 goto err_free_pdata;
168 }
169
170 button->desc = of_get_property(pp, "label", NULL);
171
172 if (of_property_read_u32(pp, "linux,input-type", &button->type))
173 button->type = EV_KEY;
174
175 button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
176
177 if (of_property_read_u32(pp, "debounce-interval",
178 &button->debounce_interval))
179 button->debounce_interval = 5;
180 }
181
182 if (pdata->nbuttons == 0) {
183 error = -EINVAL;
184 goto err_free_pdata;
185 }
186
187 return pdata;
188
189err_free_pdata:
190 kfree(pdata);
191err_out:
192 return ERR_PTR(error);
193}
194
195static struct of_device_id gpio_keys_polled_of_match[] = {
196 { .compatible = "gpio-keys-polled", },
197 { },
198};
199MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
200
201#else
202
203static inline struct gpio_keys_platform_data *
204gpio_keys_polled_get_devtree_pdata(struct device *dev)
205{
206 return NULL;
207}
208#endif
209
Bill Pemberton5298cc42012-11-23 21:38:25 -0800210static int gpio_keys_polled_probe(struct platform_device *pdev)
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800211{
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800212 struct device *dev = &pdev->dev;
Dmitry Torokhov2976f242012-07-29 22:48:33 -0700213 const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800214 struct gpio_keys_polled_dev *bdev;
215 struct input_polled_dev *poll_dev;
216 struct input_dev *input;
217 int error;
218 int i;
219
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700220 if (!pdata) {
221 pdata = gpio_keys_polled_get_devtree_pdata(dev);
222 if (IS_ERR(pdata))
223 return PTR_ERR(pdata);
224 if (!pdata) {
225 dev_err(dev, "missing platform data\n");
226 return -EINVAL;
227 }
228 }
229
230 if (!pdata->poll_interval) {
231 dev_err(dev, "missing poll_interval value\n");
232 error = -EINVAL;
233 goto err_free_pdata;
234 }
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800235
236 bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
237 pdata->nbuttons * sizeof(struct gpio_keys_button_data),
238 GFP_KERNEL);
239 if (!bdev) {
240 dev_err(dev, "no memory for private data\n");
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700241 error = -ENOMEM;
242 goto err_free_pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800243 }
244
245 poll_dev = input_allocate_polled_device();
246 if (!poll_dev) {
247 dev_err(dev, "no memory for polled device\n");
248 error = -ENOMEM;
249 goto err_free_bdev;
250 }
251
252 poll_dev->private = bdev;
253 poll_dev->poll = gpio_keys_polled_poll;
254 poll_dev->poll_interval = pdata->poll_interval;
255 poll_dev->open = gpio_keys_polled_open;
256 poll_dev->close = gpio_keys_polled_close;
257
258 input = poll_dev->input;
259
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800260 input->name = pdev->name;
261 input->phys = DRV_NAME"/input0";
262 input->dev.parent = &pdev->dev;
263
264 input->id.bustype = BUS_HOST;
265 input->id.vendor = 0x0001;
266 input->id.product = 0x0001;
267 input->id.version = 0x0100;
268
Alexander Shiyan1a22e162012-11-29 08:57:17 -0800269 __set_bit(EV_KEY, input->evbit);
270 if (pdata->rep)
271 __set_bit(EV_REP, input->evbit);
272
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800273 for (i = 0; i < pdata->nbuttons; i++) {
274 struct gpio_keys_button *button = &pdata->buttons[i];
275 struct gpio_keys_button_data *bdata = &bdev->data[i];
276 unsigned int gpio = button->gpio;
277 unsigned int type = button->type ?: EV_KEY;
278
279 if (button->wakeup) {
280 dev_err(dev, DRV_NAME " does not support wakeup\n");
281 error = -EINVAL;
282 goto err_free_gpio;
283 }
284
Dmitry Torokhovda5ee072012-11-29 09:24:08 -0800285 error = gpio_request_one(gpio, GPIOF_IN,
286 button->desc ?: DRV_NAME);
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800287 if (error) {
288 dev_err(dev, "unable to claim gpio %u, err=%d\n",
289 gpio, error);
290 goto err_free_gpio;
291 }
292
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800293 bdata->can_sleep = gpio_cansleep(gpio);
294 bdata->last_state = -1;
295 bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
296 pdata->poll_interval);
297
298 input_set_capability(input, type, button->code);
299 }
300
301 bdev->poll_dev = poll_dev;
302 bdev->dev = dev;
303 bdev->pdata = pdata;
304 platform_set_drvdata(pdev, bdev);
305
306 error = input_register_polled_device(poll_dev);
307 if (error) {
308 dev_err(dev, "unable to register polled device, err=%d\n",
309 error);
310 goto err_free_gpio;
311 }
312
313 /* report initial state of the buttons */
314 for (i = 0; i < pdata->nbuttons; i++)
315 gpio_keys_polled_check_state(input, &pdata->buttons[i],
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700316 &bdev->data[i]);
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800317
318 return 0;
319
320err_free_gpio:
321 while (--i >= 0)
322 gpio_free(pdata->buttons[i].gpio);
323
324 input_free_polled_device(poll_dev);
325
326err_free_bdev:
327 kfree(bdev);
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700328
329err_free_pdata:
330 /* If we have no platform_data, we allocated pdata dynamically. */
331 if (!dev_get_platdata(&pdev->dev))
332 kfree(pdata);
333
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800334 return error;
335}
336
Bill Pembertone2619cf2012-11-23 21:50:47 -0800337static int gpio_keys_polled_remove(struct platform_device *pdev)
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800338{
339 struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
Dmitry Torokhov2976f242012-07-29 22:48:33 -0700340 const struct gpio_keys_platform_data *pdata = bdev->pdata;
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800341 int i;
342
343 input_unregister_polled_device(bdev->poll_dev);
344
345 for (i = 0; i < pdata->nbuttons; i++)
346 gpio_free(pdata->buttons[i].gpio);
347
348 input_free_polled_device(bdev->poll_dev);
349
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700350 /*
351 * If we had no platform_data, we allocated pdata dynamically and
352 * must free it here.
353 */
354 if (!dev_get_platdata(&pdev->dev))
355 kfree(pdata);
356
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800357 kfree(bdev);
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800358
359 return 0;
360}
361
362static struct platform_driver gpio_keys_polled_driver = {
363 .probe = gpio_keys_polled_probe,
Bill Pemberton1cb0aa82012-11-23 21:27:39 -0800364 .remove = gpio_keys_polled_remove,
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800365 .driver = {
366 .name = DRV_NAME,
367 .owner = THIS_MODULE,
Alexandre Pereira da Silvaa2f25242012-07-31 22:08:45 -0700368 .of_match_table = of_match_ptr(gpio_keys_polled_of_match),
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800369 },
370};
JJ Ding5146c842011-11-29 11:08:39 -0800371module_platform_driver(gpio_keys_polled_driver);
Gabor Juhos0e7d0c82010-12-06 17:14:47 -0800372
373MODULE_LICENSE("GPL v2");
374MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
375MODULE_DESCRIPTION("Polled GPIO Buttons driver");
376MODULE_ALIAS("platform:" DRV_NAME);