gpio_keys.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. #include <linux/module.h>
  11. #include <linux/init.h>
  12. #include <linux/fs.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/irq.h>
  15. #include <linux/sched.h>
  16. #include <linux/pm.h>
  17. #include <linux/sysctl.h>
  18. #include <linux/proc_fs.h>
  19. #include <linux/delay.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/input.h>
  22. #include <linux/gpio_keys.h>
  23. #include <linux/workqueue.h>
  24. #include <asm/gpio.h>
  25. struct gpio_button_data {
  26. struct gpio_keys_button *button;
  27. struct input_dev *input;
  28. struct delayed_work work;
  29. };
  30. struct gpio_keys_drvdata {
  31. struct input_dev *input;
  32. struct gpio_button_data data[0];
  33. };
  34. static void gpio_keys_report_event(struct work_struct *work)
  35. {
  36. struct gpio_button_data *bdata =
  37. container_of(work, struct gpio_button_data, work.work);
  38. struct gpio_keys_button *button = bdata->button;
  39. struct input_dev *input = bdata->input;
  40. unsigned int type = button->type ?: EV_KEY;
  41. int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
  42. input_event(input, type, button->code, !!state);
  43. input_sync(input);
  44. }
  45. static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
  46. {
  47. struct gpio_button_data *bdata = dev_id;
  48. struct gpio_keys_button *button = bdata->button;
  49. unsigned long delay;
  50. BUG_ON(irq != gpio_to_irq(button->gpio));
  51. delay = button->debounce_interval ?
  52. msecs_to_jiffies(button->debounce_interval) : 0;
  53. schedule_delayed_work(&bdata->work, delay);
  54. return IRQ_HANDLED;
  55. }
  56. static int __devinit gpio_keys_probe(struct platform_device *pdev)
  57. {
  58. struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  59. struct gpio_keys_drvdata *ddata;
  60. struct input_dev *input;
  61. int i, error;
  62. int wakeup = 0;
  63. ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
  64. pdata->nbuttons * sizeof(struct gpio_button_data),
  65. GFP_KERNEL);
  66. input = input_allocate_device();
  67. if (!ddata || !input) {
  68. error = -ENOMEM;
  69. goto fail1;
  70. }
  71. platform_set_drvdata(pdev, ddata);
  72. input->name = pdev->name;
  73. input->phys = "gpio-keys/input0";
  74. input->dev.parent = &pdev->dev;
  75. input->id.bustype = BUS_HOST;
  76. input->id.vendor = 0x0001;
  77. input->id.product = 0x0001;
  78. input->id.version = 0x0100;
  79. /* Enable auto repeat feature of Linux input subsystem */
  80. if (pdata->rep)
  81. __set_bit(EV_REP, input->evbit);
  82. ddata->input = input;
  83. for (i = 0; i < pdata->nbuttons; i++) {
  84. struct gpio_keys_button *button = &pdata->buttons[i];
  85. struct gpio_button_data *bdata = &ddata->data[i];
  86. int irq;
  87. unsigned int type = button->type ?: EV_KEY;
  88. bdata->input = input;
  89. bdata->button = button;
  90. INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event);
  91. error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
  92. if (error < 0) {
  93. pr_err("gpio-keys: failed to request GPIO %d,"
  94. " error %d\n", button->gpio, error);
  95. goto fail2;
  96. }
  97. error = gpio_direction_input(button->gpio);
  98. if (error < 0) {
  99. pr_err("gpio-keys: failed to configure input"
  100. " direction for GPIO %d, error %d\n",
  101. button->gpio, error);
  102. gpio_free(button->gpio);
  103. goto fail2;
  104. }
  105. irq = gpio_to_irq(button->gpio);
  106. if (irq < 0) {
  107. error = irq;
  108. pr_err("gpio-keys: Unable to get irq number"
  109. " for GPIO %d, error %d\n",
  110. button->gpio, error);
  111. gpio_free(button->gpio);
  112. goto fail2;
  113. }
  114. error = request_irq(irq, gpio_keys_isr,
  115. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  116. button->desc ? button->desc : "gpio_keys",
  117. bdata);
  118. if (error) {
  119. pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
  120. irq, error);
  121. gpio_free(button->gpio);
  122. goto fail2;
  123. }
  124. if (button->wakeup)
  125. wakeup = 1;
  126. input_set_capability(input, type, button->code);
  127. }
  128. error = input_register_device(input);
  129. if (error) {
  130. pr_err("gpio-keys: Unable to register input device, "
  131. "error: %d\n", error);
  132. goto fail2;
  133. }
  134. device_init_wakeup(&pdev->dev, wakeup);
  135. return 0;
  136. fail2:
  137. while (--i >= 0) {
  138. free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
  139. cancel_delayed_work_sync(&ddata->data[i].work);
  140. gpio_free(pdata->buttons[i].gpio);
  141. }
  142. platform_set_drvdata(pdev, NULL);
  143. fail1:
  144. input_free_device(input);
  145. kfree(ddata);
  146. return error;
  147. }
  148. static int __devexit gpio_keys_remove(struct platform_device *pdev)
  149. {
  150. struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  151. struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
  152. struct input_dev *input = ddata->input;
  153. int i;
  154. device_init_wakeup(&pdev->dev, 0);
  155. for (i = 0; i < pdata->nbuttons; i++) {
  156. int irq = gpio_to_irq(pdata->buttons[i].gpio);
  157. free_irq(irq, &ddata->data[i]);
  158. cancel_delayed_work_sync(&ddata->data[i].work);
  159. gpio_free(pdata->buttons[i].gpio);
  160. }
  161. input_unregister_device(input);
  162. return 0;
  163. }
  164. #ifdef CONFIG_PM
  165. static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
  166. {
  167. struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  168. int i;
  169. if (device_may_wakeup(&pdev->dev)) {
  170. for (i = 0; i < pdata->nbuttons; i++) {
  171. struct gpio_keys_button *button = &pdata->buttons[i];
  172. if (button->wakeup) {
  173. int irq = gpio_to_irq(button->gpio);
  174. enable_irq_wake(irq);
  175. }
  176. }
  177. }
  178. return 0;
  179. }
  180. static int gpio_keys_resume(struct platform_device *pdev)
  181. {
  182. struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  183. int i;
  184. if (device_may_wakeup(&pdev->dev)) {
  185. for (i = 0; i < pdata->nbuttons; i++) {
  186. struct gpio_keys_button *button = &pdata->buttons[i];
  187. if (button->wakeup) {
  188. int irq = gpio_to_irq(button->gpio);
  189. disable_irq_wake(irq);
  190. }
  191. }
  192. }
  193. return 0;
  194. }
  195. #else
  196. #define gpio_keys_suspend NULL
  197. #define gpio_keys_resume NULL
  198. #endif
  199. static struct platform_driver gpio_keys_device_driver = {
  200. .probe = gpio_keys_probe,
  201. .remove = __devexit_p(gpio_keys_remove),
  202. .suspend = gpio_keys_suspend,
  203. .resume = gpio_keys_resume,
  204. .driver = {
  205. .name = "gpio-keys",
  206. .owner = THIS_MODULE,
  207. }
  208. };
  209. static int __init gpio_keys_init(void)
  210. {
  211. return platform_driver_register(&gpio_keys_device_driver);
  212. }
  213. static void __exit gpio_keys_exit(void)
  214. {
  215. platform_driver_unregister(&gpio_keys_device_driver);
  216. }
  217. module_init(gpio_keys_init);
  218. module_exit(gpio_keys_exit);
  219. MODULE_LICENSE("GPL");
  220. MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
  221. MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
  222. MODULE_ALIAS("platform:gpio-keys");