diff options
Diffstat (limited to 'drivers/staging/dream/gpio_input.c')
-rw-r--r-- | drivers/staging/dream/gpio_input.c | 337 |
1 files changed, 0 insertions, 337 deletions
diff --git a/drivers/staging/dream/gpio_input.c b/drivers/staging/dream/gpio_input.c deleted file mode 100644 index ca29e5eb070a..000000000000 --- a/drivers/staging/dream/gpio_input.c +++ /dev/null @@ -1,337 +0,0 @@ -/* drivers/input/misc/gpio_input.c - * - * Copyright (C) 2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/kernel.h> -#include <linux/gpio.h> -#include <linux/gpio_event.h> -#include <linux/hrtimer.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/slab.h> - -enum { - DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */ - DEBOUNCE_PRESSED = BIT(1), - DEBOUNCE_NOTPRESSED = BIT(2), - DEBOUNCE_WAIT_IRQ = BIT(3), /* Stable irq state */ - DEBOUNCE_POLL = BIT(4), /* Stable polling state */ - - DEBOUNCE_UNKNOWN = - DEBOUNCE_PRESSED | DEBOUNCE_NOTPRESSED, -}; - -struct gpio_key_state { - struct gpio_input_state *ds; - uint8_t debounce; -}; - -struct gpio_input_state { - struct input_dev *input_dev; - const struct gpio_event_input_info *info; - struct hrtimer timer; - int use_irq; - int debounce_count; - spinlock_t irq_lock; - struct gpio_key_state key_state[0]; -}; - -static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) -{ - int i; - int pressed; - struct gpio_input_state *ds = - container_of(timer, struct gpio_input_state, timer); - unsigned gpio_flags = ds->info->flags; - unsigned npolarity; - int nkeys = ds->info->keymap_size; - const struct gpio_event_direct_entry *key_entry; - struct gpio_key_state *key_state; - unsigned long irqflags; - uint8_t debounce; - -#if 0 - key_entry = kp->keys_info->keymap; - key_state = kp->key_state; - for (i = 0; i < nkeys; i++, key_entry++, key_state++) - pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, - gpio_read_detect_status(key_entry->gpio)); -#endif - key_entry = ds->info->keymap; - key_state = ds->key_state; - spin_lock_irqsave(&ds->irq_lock, irqflags); - for (i = 0; i < nkeys; i++, key_entry++, key_state++) { - debounce = key_state->debounce; - if (debounce & DEBOUNCE_WAIT_IRQ) - continue; - if (key_state->debounce & DEBOUNCE_UNSTABLE) { - debounce = key_state->debounce = DEBOUNCE_UNKNOWN; - enable_irq(gpio_to_irq(key_entry->gpio)); - pr_info("gpio_keys_scan_keys: key %x-%x, %d " - "(%d) continue debounce\n", - ds->info->type, key_entry->code, - i, key_entry->gpio); - } - npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); - pressed = gpio_get_value(key_entry->gpio) ^ npolarity; - if (debounce & DEBOUNCE_POLL) { - if (pressed == !(debounce & DEBOUNCE_PRESSED)) { - ds->debounce_count++; - key_state->debounce = DEBOUNCE_UNKNOWN; - if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) - pr_info("gpio_keys_scan_keys: key %x-" - "%x, %d (%d) start debounce\n", - ds->info->type, key_entry->code, - i, key_entry->gpio); - } - continue; - } - if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { - if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) - pr_info("gpio_keys_scan_keys: key %x-%x, %d " - "(%d) debounce pressed 1\n", - ds->info->type, key_entry->code, - i, key_entry->gpio); - key_state->debounce = DEBOUNCE_PRESSED; - continue; - } - if (!pressed && (debounce & DEBOUNCE_PRESSED)) { - if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) - pr_info("gpio_keys_scan_keys: key %x-%x, %d " - "(%d) debounce pressed 0\n", - ds->info->type, key_entry->code, - i, key_entry->gpio); - key_state->debounce = DEBOUNCE_NOTPRESSED; - continue; - } - /* key is stable */ - ds->debounce_count--; - if (ds->use_irq) - key_state->debounce |= DEBOUNCE_WAIT_IRQ; - else - key_state->debounce |= DEBOUNCE_POLL; - if (gpio_flags & GPIOEDF_PRINT_KEYS) - pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) " - "changed to %d\n", ds->info->type, - key_entry->code, i, key_entry->gpio, pressed); - input_event(ds->input_dev, ds->info->type, - key_entry->code, pressed); - } - -#if 0 - key_entry = kp->keys_info->keymap; - key_state = kp->key_state; - for (i = 0; i < nkeys; i++, key_entry++, key_state++) { - pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, - gpio_read_detect_status(key_entry->gpio)); - } -#endif - - if (ds->debounce_count) - hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL); - else if (!ds->use_irq) - hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL); - - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - - return HRTIMER_NORESTART; -} - -static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id) -{ - struct gpio_key_state *ks = dev_id; - struct gpio_input_state *ds = ks->ds; - int keymap_index = ks - ds->key_state; - const struct gpio_event_direct_entry *key_entry; - unsigned long irqflags; - int pressed; - - if (!ds->use_irq) - return IRQ_HANDLED; - - key_entry = &ds->info->keymap[keymap_index]; - - if (ds->info->debounce_time.tv64) { - spin_lock_irqsave(&ds->irq_lock, irqflags); - if (ks->debounce & DEBOUNCE_WAIT_IRQ) { - ks->debounce = DEBOUNCE_UNKNOWN; - if (ds->debounce_count++ == 0) { - hrtimer_start( - &ds->timer, ds->info->debounce_time, - HRTIMER_MODE_REL); - } - if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE) - pr_info("gpio_event_input_irq_handler: " - "key %x-%x, %d (%d) start debounce\n", - ds->info->type, key_entry->code, - keymap_index, key_entry->gpio); - } else { - disable_irq(irq); - ks->debounce = DEBOUNCE_UNSTABLE; - } - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - } else { - pressed = gpio_get_value(key_entry->gpio) ^ - !(ds->info->flags & GPIOEDF_ACTIVE_HIGH); - if (ds->info->flags & GPIOEDF_PRINT_KEYS) - pr_info("gpio_event_input_irq_handler: key %x-%x, %d " - "(%d) changed to %d\n", - ds->info->type, key_entry->code, keymap_index, - key_entry->gpio, pressed); - input_event(ds->input_dev, ds->info->type, - key_entry->code, pressed); - } - return IRQ_HANDLED; -} - -static int gpio_event_input_request_irqs(struct gpio_input_state *ds) -{ - int i; - int err; - unsigned int irq; - unsigned long req_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; - - for (i = 0; i < ds->info->keymap_size; i++) { - err = irq = gpio_to_irq(ds->info->keymap[i].gpio); - if (err < 0) - goto err_gpio_get_irq_num_failed; - err = request_irq(irq, gpio_event_input_irq_handler, - req_flags, "gpio_keys", &ds->key_state[i]); - if (err) { - pr_err("gpio_event_input_request_irqs: request_irq " - "failed for input %d, irq %d\n", - ds->info->keymap[i].gpio, irq); - goto err_request_irq_failed; - } - enable_irq_wake(irq); - } - return 0; - - for (i = ds->info->keymap_size - 1; i >= 0; i--) { - free_irq(gpio_to_irq(ds->info->keymap[i].gpio), - &ds->key_state[i]); -err_request_irq_failed: -err_gpio_get_irq_num_failed: - ; - } - return err; -} - -int gpio_event_input_func(struct input_dev *input_dev, - struct gpio_event_info *info, void **data, int func) -{ - int ret; - int i; - unsigned long irqflags; - struct gpio_event_input_info *di; - struct gpio_input_state *ds = *data; - - di = container_of(info, struct gpio_event_input_info, info); - - if (func == GPIO_EVENT_FUNC_SUSPEND) { - spin_lock_irqsave(&ds->irq_lock, irqflags); - if (ds->use_irq) - for (i = 0; i < di->keymap_size; i++) - disable_irq(gpio_to_irq(di->keymap[i].gpio)); - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - hrtimer_cancel(&ds->timer); - return 0; - } - if (func == GPIO_EVENT_FUNC_RESUME) { - spin_lock_irqsave(&ds->irq_lock, irqflags); - if (ds->use_irq) - for (i = 0; i < di->keymap_size; i++) - enable_irq(gpio_to_irq(di->keymap[i].gpio)); - hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL); - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - return 0; - } - - if (func == GPIO_EVENT_FUNC_INIT) { - if (ktime_to_ns(di->poll_time) <= 0) - di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC); - - *data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) * - di->keymap_size, GFP_KERNEL); - if (ds == NULL) { - ret = -ENOMEM; - pr_err("gpio_event_input_func: " - "Failed to allocate private data\n"); - goto err_ds_alloc_failed; - } - ds->debounce_count = di->keymap_size; - ds->input_dev = input_dev; - ds->info = di; - spin_lock_init(&ds->irq_lock); - - for (i = 0; i < di->keymap_size; i++) { - input_set_capability(input_dev, di->type, - di->keymap[i].code); - ds->key_state[i].ds = ds; - ds->key_state[i].debounce = DEBOUNCE_UNKNOWN; - } - - for (i = 0; i < di->keymap_size; i++) { - ret = gpio_request(di->keymap[i].gpio, "gpio_kp_in"); - if (ret) { - pr_err("gpio_event_input_func: gpio_request " - "failed for %d\n", di->keymap[i].gpio); - goto err_gpio_request_failed; - } - ret = gpio_direction_input(di->keymap[i].gpio); - if (ret) { - pr_err("gpio_event_input_func: " - "gpio_direction_input failed for %d\n", - di->keymap[i].gpio); - goto err_gpio_configure_failed; - } - } - - ret = gpio_event_input_request_irqs(ds); - - spin_lock_irqsave(&ds->irq_lock, irqflags); - ds->use_irq = ret == 0; - - pr_info("GPIO Input Driver: Start gpio inputs for %s in %s " - "mode\n", - input_dev->name, ret == 0 ? "interrupt" : "polling"); - - hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ds->timer.function = gpio_event_input_timer_func; - hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL); - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - return 0; - } - - ret = 0; - spin_lock_irqsave(&ds->irq_lock, irqflags); - hrtimer_cancel(&ds->timer); - if (ds->use_irq) { - for (i = di->keymap_size - 1; i >= 0; i--) { - free_irq(gpio_to_irq(di->keymap[i].gpio), - &ds->key_state[i]); - } - } - spin_unlock_irqrestore(&ds->irq_lock, irqflags); - - for (i = di->keymap_size - 1; i >= 0; i--) { -err_gpio_configure_failed: - gpio_free(di->keymap[i].gpio); -err_gpio_request_failed: - ; - } - kfree(ds); -err_ds_alloc_failed: - return ret; -} |