• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/dream/
1/* 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
24enum {
25	DEBOUNCE_UNSTABLE     = BIT(0),	/* Got irq, while debouncing */
26	DEBOUNCE_PRESSED      = BIT(1),
27	DEBOUNCE_NOTPRESSED   = BIT(2),
28	DEBOUNCE_WAIT_IRQ     = BIT(3),	/* Stable irq state */
29	DEBOUNCE_POLL         = BIT(4),	/* Stable polling state */
30
31	DEBOUNCE_UNKNOWN =
32		DEBOUNCE_PRESSED | DEBOUNCE_NOTPRESSED,
33};
34
35struct gpio_key_state {
36	struct gpio_input_state *ds;
37	uint8_t debounce;
38};
39
40struct gpio_input_state {
41	struct input_dev *input_dev;
42	const struct gpio_event_input_info *info;
43	struct hrtimer timer;
44	int use_irq;
45	int debounce_count;
46	spinlock_t irq_lock;
47	struct gpio_key_state key_state[0];
48};
49
50static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer)
51{
52	int i;
53	int pressed;
54	struct gpio_input_state *ds =
55		container_of(timer, struct gpio_input_state, timer);
56	unsigned gpio_flags = ds->info->flags;
57	unsigned npolarity;
58	int nkeys = ds->info->keymap_size;
59	const struct gpio_event_direct_entry *key_entry;
60	struct gpio_key_state *key_state;
61	unsigned long irqflags;
62	uint8_t debounce;
63
64	key_entry = ds->info->keymap;
65	key_state = ds->key_state;
66	spin_lock_irqsave(&ds->irq_lock, irqflags);
67	for (i = 0; i < nkeys; i++, key_entry++, key_state++) {
68		debounce = key_state->debounce;
69		if (debounce & DEBOUNCE_WAIT_IRQ)
70			continue;
71		if (key_state->debounce & DEBOUNCE_UNSTABLE) {
72			debounce = key_state->debounce = DEBOUNCE_UNKNOWN;
73			enable_irq(gpio_to_irq(key_entry->gpio));
74			pr_info("gpio_keys_scan_keys: key %x-%x, %d "
75				"(%d) continue debounce\n",
76				ds->info->type, key_entry->code,
77				i, key_entry->gpio);
78		}
79		npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH);
80		pressed = gpio_get_value(key_entry->gpio) ^ npolarity;
81		if (debounce & DEBOUNCE_POLL) {
82			if (pressed == !(debounce & DEBOUNCE_PRESSED)) {
83				ds->debounce_count++;
84				key_state->debounce = DEBOUNCE_UNKNOWN;
85				if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
86					pr_info("gpio_keys_scan_keys: key %x-"
87						"%x, %d (%d) start debounce\n",
88						ds->info->type, key_entry->code,
89						i, key_entry->gpio);
90			}
91			continue;
92		}
93		if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) {
94			if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
95				pr_info("gpio_keys_scan_keys: key %x-%x, %d "
96					"(%d) debounce pressed 1\n",
97					ds->info->type, key_entry->code,
98					i, key_entry->gpio);
99			key_state->debounce = DEBOUNCE_PRESSED;
100			continue;
101		}
102		if (!pressed && (debounce & DEBOUNCE_PRESSED)) {
103			if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
104				pr_info("gpio_keys_scan_keys: key %x-%x, %d "
105					"(%d) debounce pressed 0\n",
106					ds->info->type, key_entry->code,
107					i, key_entry->gpio);
108			key_state->debounce = DEBOUNCE_NOTPRESSED;
109			continue;
110		}
111		/* key is stable */
112		ds->debounce_count--;
113		if (ds->use_irq)
114			key_state->debounce |= DEBOUNCE_WAIT_IRQ;
115		else
116			key_state->debounce |= DEBOUNCE_POLL;
117		if (gpio_flags & GPIOEDF_PRINT_KEYS)
118			pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) "
119				"changed to %d\n", ds->info->type,
120				key_entry->code, i, key_entry->gpio, pressed);
121		input_event(ds->input_dev, ds->info->type,
122			    key_entry->code, pressed);
123	}
124
125
126	if (ds->debounce_count)
127		hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL);
128	else if (!ds->use_irq)
129		hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL);
130
131	spin_unlock_irqrestore(&ds->irq_lock, irqflags);
132
133	return HRTIMER_NORESTART;
134}
135
136static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id)
137{
138	struct gpio_key_state *ks = dev_id;
139	struct gpio_input_state *ds = ks->ds;
140	int keymap_index = ks - ds->key_state;
141	const struct gpio_event_direct_entry *key_entry;
142	unsigned long irqflags;
143	int pressed;
144
145	if (!ds->use_irq)
146		return IRQ_HANDLED;
147
148	key_entry = &ds->info->keymap[keymap_index];
149
150	if (ds->info->debounce_time.tv64) {
151		spin_lock_irqsave(&ds->irq_lock, irqflags);
152		if (ks->debounce & DEBOUNCE_WAIT_IRQ) {
153			ks->debounce = DEBOUNCE_UNKNOWN;
154			if (ds->debounce_count++ == 0) {
155				hrtimer_start(
156					&ds->timer, ds->info->debounce_time,
157					HRTIMER_MODE_REL);
158			}
159			if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
160				pr_info("gpio_event_input_irq_handler: "
161					"key %x-%x, %d (%d) start debounce\n",
162					ds->info->type, key_entry->code,
163					keymap_index, key_entry->gpio);
164		} else {
165			disable_irq(irq);
166			ks->debounce = DEBOUNCE_UNSTABLE;
167		}
168		spin_unlock_irqrestore(&ds->irq_lock, irqflags);
169	} else {
170		pressed = gpio_get_value(key_entry->gpio) ^
171			!(ds->info->flags & GPIOEDF_ACTIVE_HIGH);
172		if (ds->info->flags & GPIOEDF_PRINT_KEYS)
173			pr_info("gpio_event_input_irq_handler: key %x-%x, %d "
174				"(%d) changed to %d\n",
175				ds->info->type, key_entry->code, keymap_index,
176				key_entry->gpio, pressed);
177		input_event(ds->input_dev, ds->info->type,
178			    key_entry->code, pressed);
179	}
180	return IRQ_HANDLED;
181}
182
183static int gpio_event_input_request_irqs(struct gpio_input_state *ds)
184{
185	int i;
186	int err;
187	unsigned int irq;
188	unsigned long req_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
189
190	for (i = 0; i < ds->info->keymap_size; i++) {
191		err = irq = gpio_to_irq(ds->info->keymap[i].gpio);
192		if (err < 0)
193			goto err_gpio_get_irq_num_failed;
194		err = request_irq(irq, gpio_event_input_irq_handler,
195				  req_flags, "gpio_keys", &ds->key_state[i]);
196		if (err) {
197			pr_err("gpio_event_input_request_irqs: request_irq "
198				"failed for input %d, irq %d\n",
199				ds->info->keymap[i].gpio, irq);
200			goto err_request_irq_failed;
201		}
202		enable_irq_wake(irq);
203	}
204	return 0;
205
206	for (i = ds->info->keymap_size - 1; i >= 0; i--) {
207		free_irq(gpio_to_irq(ds->info->keymap[i].gpio),
208			 &ds->key_state[i]);
209err_request_irq_failed:
210err_gpio_get_irq_num_failed:
211		;
212	}
213	return err;
214}
215
216int gpio_event_input_func(struct input_dev *input_dev,
217			struct gpio_event_info *info, void **data, int func)
218{
219	int ret;
220	int i;
221	unsigned long irqflags;
222	struct gpio_event_input_info *di;
223	struct gpio_input_state *ds = *data;
224
225	di = container_of(info, struct gpio_event_input_info, info);
226
227	if (func == GPIO_EVENT_FUNC_SUSPEND) {
228		spin_lock_irqsave(&ds->irq_lock, irqflags);
229		if (ds->use_irq)
230			for (i = 0; i < di->keymap_size; i++)
231				disable_irq(gpio_to_irq(di->keymap[i].gpio));
232		spin_unlock_irqrestore(&ds->irq_lock, irqflags);
233		hrtimer_cancel(&ds->timer);
234		return 0;
235	}
236	if (func == GPIO_EVENT_FUNC_RESUME) {
237		spin_lock_irqsave(&ds->irq_lock, irqflags);
238		if (ds->use_irq)
239			for (i = 0; i < di->keymap_size; i++)
240				enable_irq(gpio_to_irq(di->keymap[i].gpio));
241		hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
242		spin_unlock_irqrestore(&ds->irq_lock, irqflags);
243		return 0;
244	}
245
246	if (func == GPIO_EVENT_FUNC_INIT) {
247		if (ktime_to_ns(di->poll_time) <= 0)
248			di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC);
249
250		*data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) *
251					di->keymap_size, GFP_KERNEL);
252		if (ds == NULL) {
253			ret = -ENOMEM;
254			pr_err("gpio_event_input_func: "
255				"Failed to allocate private data\n");
256			goto err_ds_alloc_failed;
257		}
258		ds->debounce_count = di->keymap_size;
259		ds->input_dev = input_dev;
260		ds->info = di;
261		spin_lock_init(&ds->irq_lock);
262
263		for (i = 0; i < di->keymap_size; i++) {
264			input_set_capability(input_dev, di->type,
265					     di->keymap[i].code);
266			ds->key_state[i].ds = ds;
267			ds->key_state[i].debounce = DEBOUNCE_UNKNOWN;
268		}
269
270		for (i = 0; i < di->keymap_size; i++) {
271			ret = gpio_request(di->keymap[i].gpio, "gpio_kp_in");
272			if (ret) {
273				pr_err("gpio_event_input_func: gpio_request "
274					"failed for %d\n", di->keymap[i].gpio);
275				goto err_gpio_request_failed;
276			}
277			ret = gpio_direction_input(di->keymap[i].gpio);
278			if (ret) {
279				pr_err("gpio_event_input_func: "
280					"gpio_direction_input failed for %d\n",
281					di->keymap[i].gpio);
282				goto err_gpio_configure_failed;
283			}
284		}
285
286		ret = gpio_event_input_request_irqs(ds);
287
288		spin_lock_irqsave(&ds->irq_lock, irqflags);
289		ds->use_irq = ret == 0;
290
291		pr_info("GPIO Input Driver: Start gpio inputs for %s in %s "
292			"mode\n",
293			input_dev->name, ret == 0 ? "interrupt" : "polling");
294
295		hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
296		ds->timer.function = gpio_event_input_timer_func;
297		hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
298		spin_unlock_irqrestore(&ds->irq_lock, irqflags);
299		return 0;
300	}
301
302	ret = 0;
303	spin_lock_irqsave(&ds->irq_lock, irqflags);
304	hrtimer_cancel(&ds->timer);
305	if (ds->use_irq) {
306		for (i = di->keymap_size - 1; i >= 0; i--) {
307			free_irq(gpio_to_irq(di->keymap[i].gpio),
308				 &ds->key_state[i]);
309		}
310	}
311	spin_unlock_irqrestore(&ds->irq_lock, irqflags);
312
313	for (i = di->keymap_size - 1; i >= 0; i--) {
314err_gpio_configure_failed:
315		gpio_free(di->keymap[i].gpio);
316err_gpio_request_failed:
317		;
318	}
319	kfree(ds);
320err_ds_alloc_failed:
321	return ret;
322}
323