blob: 904bd684449b0702590a242a045797e09461f60a [file] [log] [blame]
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -07001/* drivers/input/misc/gpio_input.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/gpio.h>
18#include <linux/gpio_event.h>
19#include <linux/hrtimer.h>
20#include <linux/input.h>
21#include <linux/interrupt.h>
22#include <linux/slab.h>
23#include <linux/wakelock.h>
24
25enum {
26 DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */
27 DEBOUNCE_PRESSED = BIT(1),
28 DEBOUNCE_NOTPRESSED = BIT(2),
29 DEBOUNCE_WAIT_IRQ = BIT(3), /* Stable irq state */
30 DEBOUNCE_POLL = BIT(4), /* Stable polling state */
31
32 DEBOUNCE_UNKNOWN =
33 DEBOUNCE_PRESSED | DEBOUNCE_NOTPRESSED,
34};
35
36struct gpio_key_state {
37 struct gpio_input_state *ds;
38 uint8_t debounce;
39};
40
41struct gpio_input_state {
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -070042 struct gpio_event_input_devs *input_devs;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070043 const struct gpio_event_input_info *info;
44 struct hrtimer timer;
45 int use_irq;
46 int debounce_count;
47 spinlock_t irq_lock;
48 struct wake_lock wake_lock;
49 struct gpio_key_state key_state[0];
50};
51
52static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer)
53{
54 int i;
55 int pressed;
56 struct gpio_input_state *ds =
57 container_of(timer, struct gpio_input_state, timer);
58 unsigned gpio_flags = ds->info->flags;
59 unsigned npolarity;
60 int nkeys = ds->info->keymap_size;
61 const struct gpio_event_direct_entry *key_entry;
62 struct gpio_key_state *key_state;
63 unsigned long irqflags;
64 uint8_t debounce;
Jeff Brown4700c542011-03-18 16:02:26 -070065 bool sync_needed;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070066
67#if 0
68 key_entry = kp->keys_info->keymap;
69 key_state = kp->key_state;
70 for (i = 0; i < nkeys; i++, key_entry++, key_state++)
71 pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio,
72 gpio_read_detect_status(key_entry->gpio));
73#endif
74 key_entry = ds->info->keymap;
75 key_state = ds->key_state;
Jeff Brown4700c542011-03-18 16:02:26 -070076 sync_needed = false;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070077 spin_lock_irqsave(&ds->irq_lock, irqflags);
78 for (i = 0; i < nkeys; i++, key_entry++, key_state++) {
79 debounce = key_state->debounce;
80 if (debounce & DEBOUNCE_WAIT_IRQ)
81 continue;
82 if (key_state->debounce & DEBOUNCE_UNSTABLE) {
83 debounce = key_state->debounce = DEBOUNCE_UNKNOWN;
84 enable_irq(gpio_to_irq(key_entry->gpio));
85 pr_info("gpio_keys_scan_keys: key %x-%x, %d "
86 "(%d) continue debounce\n",
87 ds->info->type, key_entry->code,
88 i, key_entry->gpio);
89 }
90 npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH);
91 pressed = gpio_get_value(key_entry->gpio) ^ npolarity;
92 if (debounce & DEBOUNCE_POLL) {
93 if (pressed == !(debounce & DEBOUNCE_PRESSED)) {
94 ds->debounce_count++;
95 key_state->debounce = DEBOUNCE_UNKNOWN;
96 if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
97 pr_info("gpio_keys_scan_keys: key %x-"
98 "%x, %d (%d) start debounce\n",
99 ds->info->type, key_entry->code,
100 i, key_entry->gpio);
101 }
102 continue;
103 }
104 if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) {
105 if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
106 pr_info("gpio_keys_scan_keys: key %x-%x, %d "
107 "(%d) debounce pressed 1\n",
108 ds->info->type, key_entry->code,
109 i, key_entry->gpio);
110 key_state->debounce = DEBOUNCE_PRESSED;
111 continue;
112 }
113 if (!pressed && (debounce & DEBOUNCE_PRESSED)) {
114 if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
115 pr_info("gpio_keys_scan_keys: key %x-%x, %d "
116 "(%d) debounce pressed 0\n",
117 ds->info->type, key_entry->code,
118 i, key_entry->gpio);
119 key_state->debounce = DEBOUNCE_NOTPRESSED;
120 continue;
121 }
122 /* key is stable */
123 ds->debounce_count--;
124 if (ds->use_irq)
125 key_state->debounce |= DEBOUNCE_WAIT_IRQ;
126 else
127 key_state->debounce |= DEBOUNCE_POLL;
128 if (gpio_flags & GPIOEDF_PRINT_KEYS)
129 pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) "
130 "changed to %d\n", ds->info->type,
131 key_entry->code, i, key_entry->gpio, pressed);
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700132 input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700133 key_entry->code, pressed);
Jeff Brown4700c542011-03-18 16:02:26 -0700134 sync_needed = true;
135 }
136 if (sync_needed) {
137 for (i = 0; i < ds->input_devs->count; i++)
138 input_sync(ds->input_devs->dev[i]);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700139 }
140
141#if 0
142 key_entry = kp->keys_info->keymap;
143 key_state = kp->key_state;
144 for (i = 0; i < nkeys; i++, key_entry++, key_state++) {
145 pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio,
146 gpio_read_detect_status(key_entry->gpio));
147 }
148#endif
149
150 if (ds->debounce_count)
151 hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL);
152 else if (!ds->use_irq)
153 hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL);
154 else
155 wake_unlock(&ds->wake_lock);
156
157 spin_unlock_irqrestore(&ds->irq_lock, irqflags);
158
159 return HRTIMER_NORESTART;
160}
161
162static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id)
163{
164 struct gpio_key_state *ks = dev_id;
165 struct gpio_input_state *ds = ks->ds;
166 int keymap_index = ks - ds->key_state;
167 const struct gpio_event_direct_entry *key_entry;
168 unsigned long irqflags;
169 int pressed;
170
171 if (!ds->use_irq)
172 return IRQ_HANDLED;
173
174 key_entry = &ds->info->keymap[keymap_index];
175
176 if (ds->info->debounce_time.tv64) {
177 spin_lock_irqsave(&ds->irq_lock, irqflags);
178 if (ks->debounce & DEBOUNCE_WAIT_IRQ) {
179 ks->debounce = DEBOUNCE_UNKNOWN;
180 if (ds->debounce_count++ == 0) {
181 wake_lock(&ds->wake_lock);
182 hrtimer_start(
183 &ds->timer, ds->info->debounce_time,
184 HRTIMER_MODE_REL);
185 }
186 if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
187 pr_info("gpio_event_input_irq_handler: "
188 "key %x-%x, %d (%d) start debounce\n",
189 ds->info->type, key_entry->code,
190 keymap_index, key_entry->gpio);
191 } else {
Arve Hjønnevåg9be7b632009-04-17 18:24:59 -0700192 disable_irq_nosync(irq);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700193 ks->debounce = DEBOUNCE_UNSTABLE;
194 }
195 spin_unlock_irqrestore(&ds->irq_lock, irqflags);
196 } else {
197 pressed = gpio_get_value(key_entry->gpio) ^
198 !(ds->info->flags & GPIOEDF_ACTIVE_HIGH);
199 if (ds->info->flags & GPIOEDF_PRINT_KEYS)
200 pr_info("gpio_event_input_irq_handler: key %x-%x, %d "
201 "(%d) changed to %d\n",
202 ds->info->type, key_entry->code, keymap_index,
203 key_entry->gpio, pressed);
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700204 input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700205 key_entry->code, pressed);
Jeff Brown4700c542011-03-18 16:02:26 -0700206 input_sync(ds->input_devs->dev[key_entry->dev]);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700207 }
208 return IRQ_HANDLED;
209}
210
211static int gpio_event_input_request_irqs(struct gpio_input_state *ds)
212{
213 int i;
214 int err;
215 unsigned int irq;
216 unsigned long req_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
217
218 for (i = 0; i < ds->info->keymap_size; i++) {
219 err = irq = gpio_to_irq(ds->info->keymap[i].gpio);
220 if (err < 0)
221 goto err_gpio_get_irq_num_failed;
222 err = request_irq(irq, gpio_event_input_irq_handler,
223 req_flags, "gpio_keys", &ds->key_state[i]);
224 if (err) {
225 pr_err("gpio_event_input_request_irqs: request_irq "
226 "failed for input %d, irq %d\n",
227 ds->info->keymap[i].gpio, irq);
228 goto err_request_irq_failed;
229 }
Mike J. Chen7cfb88f2010-10-14 18:04:03 -0700230 if (ds->info->info.no_suspend) {
231 err = enable_irq_wake(irq);
232 if (err) {
233 pr_err("gpio_event_input_request_irqs: "
234 "enable_irq_wake failed for input %d, "
235 "irq %d\n",
236 ds->info->keymap[i].gpio, irq);
237 goto err_enable_irq_wake_failed;
238 }
239 }
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700240 }
241 return 0;
242
243 for (i = ds->info->keymap_size - 1; i >= 0; i--) {
Mike J. Chen7cfb88f2010-10-14 18:04:03 -0700244 irq = gpio_to_irq(ds->info->keymap[i].gpio);
245 if (ds->info->info.no_suspend)
246 disable_irq_wake(irq);
247err_enable_irq_wake_failed:
248 free_irq(irq, &ds->key_state[i]);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700249err_request_irq_failed:
250err_gpio_get_irq_num_failed:
251 ;
252 }
253 return err;
254}
255
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700256int gpio_event_input_func(struct gpio_event_input_devs *input_devs,
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700257 struct gpio_event_info *info, void **data, int func)
258{
259 int ret;
260 int i;
261 unsigned long irqflags;
262 struct gpio_event_input_info *di;
263 struct gpio_input_state *ds = *data;
264
265 di = container_of(info, struct gpio_event_input_info, info);
266
267 if (func == GPIO_EVENT_FUNC_SUSPEND) {
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700268 if (ds->use_irq)
269 for (i = 0; i < di->keymap_size; i++)
270 disable_irq(gpio_to_irq(di->keymap[i].gpio));
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700271 hrtimer_cancel(&ds->timer);
272 return 0;
273 }
274 if (func == GPIO_EVENT_FUNC_RESUME) {
275 spin_lock_irqsave(&ds->irq_lock, irqflags);
276 if (ds->use_irq)
277 for (i = 0; i < di->keymap_size; i++)
278 enable_irq(gpio_to_irq(di->keymap[i].gpio));
279 hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
280 spin_unlock_irqrestore(&ds->irq_lock, irqflags);
281 return 0;
282 }
283
284 if (func == GPIO_EVENT_FUNC_INIT) {
285 if (ktime_to_ns(di->poll_time) <= 0)
286 di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC);
287
288 *data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) *
289 di->keymap_size, GFP_KERNEL);
290 if (ds == NULL) {
291 ret = -ENOMEM;
292 pr_err("gpio_event_input_func: "
293 "Failed to allocate private data\n");
294 goto err_ds_alloc_failed;
295 }
296 ds->debounce_count = di->keymap_size;
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700297 ds->input_devs = input_devs;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700298 ds->info = di;
299 wake_lock_init(&ds->wake_lock, WAKE_LOCK_SUSPEND, "gpio_input");
300 spin_lock_init(&ds->irq_lock);
301
302 for (i = 0; i < di->keymap_size; i++) {
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700303 int dev = di->keymap[i].dev;
304 if (dev >= input_devs->count) {
305 pr_err("gpio_event_input_func: bad device "
306 "index %d >= %d for key code %d\n",
307 dev, input_devs->count,
308 di->keymap[i].code);
309 ret = -EINVAL;
310 goto err_bad_keymap;
311 }
312 input_set_capability(input_devs->dev[dev], di->type,
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700313 di->keymap[i].code);
314 ds->key_state[i].ds = ds;
315 ds->key_state[i].debounce = DEBOUNCE_UNKNOWN;
316 }
317
318 for (i = 0; i < di->keymap_size; i++) {
319 ret = gpio_request(di->keymap[i].gpio, "gpio_kp_in");
320 if (ret) {
321 pr_err("gpio_event_input_func: gpio_request "
322 "failed for %d\n", di->keymap[i].gpio);
323 goto err_gpio_request_failed;
324 }
325 ret = gpio_direction_input(di->keymap[i].gpio);
326 if (ret) {
327 pr_err("gpio_event_input_func: "
328 "gpio_direction_input failed for %d\n",
329 di->keymap[i].gpio);
330 goto err_gpio_configure_failed;
331 }
332 }
333
334 ret = gpio_event_input_request_irqs(ds);
335
336 spin_lock_irqsave(&ds->irq_lock, irqflags);
337 ds->use_irq = ret == 0;
338
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700339 pr_info("GPIO Input Driver: Start gpio inputs for %s%s in %s "
340 "mode\n", input_devs->dev[0]->name,
341 (input_devs->count > 1) ? "..." : "",
342 ret == 0 ? "interrupt" : "polling");
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700343
344 hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
345 ds->timer.function = gpio_event_input_timer_func;
346 hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
347 spin_unlock_irqrestore(&ds->irq_lock, irqflags);
348 return 0;
349 }
350
351 ret = 0;
352 spin_lock_irqsave(&ds->irq_lock, irqflags);
353 hrtimer_cancel(&ds->timer);
354 if (ds->use_irq) {
355 for (i = di->keymap_size - 1; i >= 0; i--) {
Mike J. Chen7cfb88f2010-10-14 18:04:03 -0700356 int irq = gpio_to_irq(di->keymap[i].gpio);
357 if (ds->info->info.no_suspend)
358 disable_irq_wake(irq);
359 free_irq(irq, &ds->key_state[i]);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700360 }
361 }
362 spin_unlock_irqrestore(&ds->irq_lock, irqflags);
363
364 for (i = di->keymap_size - 1; i >= 0; i--) {
365err_gpio_configure_failed:
366 gpio_free(di->keymap[i].gpio);
367err_gpio_request_failed:
368 ;
369 }
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700370err_bad_keymap:
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700371 wake_lock_destroy(&ds->wake_lock);
372 kfree(ds);
373err_ds_alloc_failed:
374 return ret;
375}