linux/drivers/input/keyboard/gpio_keys.c
<<
>>
Prefs
   1/*
   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>
  12
  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>
  24#include <linux/gpio_keys.h>
  25#include <linux/workqueue.h>
  26
  27#include <asm/gpio.h>
  28
  29struct gpio_button_data {
  30        struct gpio_keys_button *button;
  31        struct input_dev *input;
  32        struct timer_list timer;
  33        struct work_struct work;
  34};
  35
  36struct gpio_keys_drvdata {
  37        struct input_dev *input;
  38        struct gpio_button_data data[0];
  39};
  40
  41static void gpio_keys_report_event(struct work_struct *work)
  42{
  43        struct gpio_button_data *bdata =
  44                container_of(work, struct gpio_button_data, work);
  45        struct gpio_keys_button *button = bdata->button;
  46        struct input_dev *input = bdata->input;
  47        unsigned int type = button->type ?: EV_KEY;
  48        int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
  49
  50        input_event(input, type, button->code, !!state);
  51        input_sync(input);
  52}
  53
  54static void gpio_keys_timer(unsigned long _data)
  55{
  56        struct gpio_button_data *data = (struct gpio_button_data *)_data;
  57
  58        schedule_work(&data->work);
  59}
  60
  61static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
  62{
  63        struct gpio_button_data *bdata = dev_id;
  64        struct gpio_keys_button *button = bdata->button;
  65
  66        BUG_ON(irq != gpio_to_irq(button->gpio));
  67
  68        if (button->debounce_interval)
  69                mod_timer(&bdata->timer,
  70                        jiffies + msecs_to_jiffies(button->debounce_interval));
  71        else
  72                schedule_work(&bdata->work);
  73
  74        return IRQ_HANDLED;
  75}
  76
  77static int __devinit gpio_keys_probe(struct platform_device *pdev)
  78{
  79        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  80        struct gpio_keys_drvdata *ddata;
  81        struct input_dev *input;
  82        int i, error;
  83        int wakeup = 0;
  84
  85        ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
  86                        pdata->nbuttons * sizeof(struct gpio_button_data),
  87                        GFP_KERNEL);
  88        input = input_allocate_device();
  89        if (!ddata || !input) {
  90                error = -ENOMEM;
  91                goto fail1;
  92        }
  93
  94        platform_set_drvdata(pdev, ddata);
  95
  96        input->name = pdev->name;
  97        input->phys = "gpio-keys/input0";
  98        input->dev.parent = &pdev->dev;
  99
 100        input->id.bustype = BUS_HOST;
 101        input->id.vendor = 0x0001;
 102        input->id.product = 0x0001;
 103        input->id.version = 0x0100;
 104
 105        /* Enable auto repeat feature of Linux input subsystem */
 106        if (pdata->rep)
 107                __set_bit(EV_REP, input->evbit);
 108
 109        ddata->input = input;
 110
 111        for (i = 0; i < pdata->nbuttons; i++) {
 112                struct gpio_keys_button *button = &pdata->buttons[i];
 113                struct gpio_button_data *bdata = &ddata->data[i];
 114                int irq;
 115                unsigned int type = button->type ?: EV_KEY;
 116
 117                bdata->input = input;
 118                bdata->button = button;
 119                setup_timer(&bdata->timer,
 120                            gpio_keys_timer, (unsigned long)bdata);
 121                INIT_WORK(&bdata->work, gpio_keys_report_event);
 122
 123                error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
 124                if (error < 0) {
 125                        pr_err("gpio-keys: failed to request GPIO %d,"
 126                                " error %d\n", button->gpio, error);
 127                        goto fail2;
 128                }
 129
 130                error = gpio_direction_input(button->gpio);
 131                if (error < 0) {
 132                        pr_err("gpio-keys: failed to configure input"
 133                                " direction for GPIO %d, error %d\n",
 134                                button->gpio, error);
 135                        gpio_free(button->gpio);
 136                        goto fail2;
 137                }
 138
 139                irq = gpio_to_irq(button->gpio);
 140                if (irq < 0) {
 141                        error = irq;
 142                        pr_err("gpio-keys: Unable to get irq number"
 143                                " for GPIO %d, error %d\n",
 144                                button->gpio, error);
 145                        gpio_free(button->gpio);
 146                        goto fail2;
 147                }
 148
 149                error = request_irq(irq, gpio_keys_isr,
 150                                    IRQF_SHARED |
 151                                    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 152                                    button->desc ? button->desc : "gpio_keys",
 153                                    bdata);
 154                if (error) {
 155                        pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
 156                                irq, error);
 157                        gpio_free(button->gpio);
 158                        goto fail2;
 159                }
 160
 161                if (button->wakeup)
 162                        wakeup = 1;
 163
 164                input_set_capability(input, type, button->code);
 165        }
 166
 167        error = input_register_device(input);
 168        if (error) {
 169                pr_err("gpio-keys: Unable to register input device, "
 170                        "error: %d\n", error);
 171                goto fail2;
 172        }
 173
 174        device_init_wakeup(&pdev->dev, wakeup);
 175
 176        return 0;
 177
 178 fail2:
 179        while (--i >= 0) {
 180                free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
 181                if (pdata->buttons[i].debounce_interval)
 182                        del_timer_sync(&ddata->data[i].timer);
 183                cancel_work_sync(&ddata->data[i].work);
 184                gpio_free(pdata->buttons[i].gpio);
 185        }
 186
 187        platform_set_drvdata(pdev, NULL);
 188 fail1:
 189        input_free_device(input);
 190        kfree(ddata);
 191
 192        return error;
 193}
 194
 195static int __devexit gpio_keys_remove(struct platform_device *pdev)
 196{
 197        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 198        struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
 199        struct input_dev *input = ddata->input;
 200        int i;
 201
 202        device_init_wakeup(&pdev->dev, 0);
 203
 204        for (i = 0; i < pdata->nbuttons; i++) {
 205                int irq = gpio_to_irq(pdata->buttons[i].gpio);
 206                free_irq(irq, &ddata->data[i]);
 207                if (pdata->buttons[i].debounce_interval)
 208                        del_timer_sync(&ddata->data[i].timer);
 209                cancel_work_sync(&ddata->data[i].work);
 210                gpio_free(pdata->buttons[i].gpio);
 211        }
 212
 213        input_unregister_device(input);
 214
 215        return 0;
 216}
 217
 218
 219#ifdef CONFIG_PM
 220static int gpio_keys_suspend(struct device *dev)
 221{
 222        struct platform_device *pdev = to_platform_device(dev);
 223        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 224        int i;
 225
 226        if (device_may_wakeup(&pdev->dev)) {
 227                for (i = 0; i < pdata->nbuttons; i++) {
 228                        struct gpio_keys_button *button = &pdata->buttons[i];
 229                        if (button->wakeup) {
 230                                int irq = gpio_to_irq(button->gpio);
 231                                enable_irq_wake(irq);
 232                        }
 233                }
 234        }
 235
 236        return 0;
 237}
 238
 239static int gpio_keys_resume(struct device *dev)
 240{
 241        struct platform_device *pdev = to_platform_device(dev);
 242        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 243        int i;
 244
 245        if (device_may_wakeup(&pdev->dev)) {
 246                for (i = 0; i < pdata->nbuttons; i++) {
 247                        struct gpio_keys_button *button = &pdata->buttons[i];
 248                        if (button->wakeup) {
 249                                int irq = gpio_to_irq(button->gpio);
 250                                disable_irq_wake(irq);
 251                        }
 252                }
 253        }
 254
 255        return 0;
 256}
 257
 258static const struct dev_pm_ops gpio_keys_pm_ops = {
 259        .suspend        = gpio_keys_suspend,
 260        .resume         = gpio_keys_resume,
 261};
 262#endif
 263
 264static struct platform_driver gpio_keys_device_driver = {
 265        .probe          = gpio_keys_probe,
 266        .remove         = __devexit_p(gpio_keys_remove),
 267        .driver         = {
 268                .name   = "gpio-keys",
 269                .owner  = THIS_MODULE,
 270#ifdef CONFIG_PM
 271                .pm     = &gpio_keys_pm_ops,
 272#endif
 273        }
 274};
 275
 276static int __init gpio_keys_init(void)
 277{
 278        return platform_driver_register(&gpio_keys_device_driver);
 279}
 280
 281static void __exit gpio_keys_exit(void)
 282{
 283        platform_driver_unregister(&gpio_keys_device_driver);
 284}
 285
 286module_init(gpio_keys_init);
 287module_exit(gpio_keys_exit);
 288
 289MODULE_LICENSE("GPL");
 290MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
 291MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
 292MODULE_ALIAS("platform:gpio-keys");
 293