diff options
author | Phil Blundell <pb@handhelds.org> | 2007-01-18 00:44:09 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-01-18 00:44:09 -0500 |
commit | 78a56aab11234e53b7e94e5a255cc3d27ab0a62b (patch) | |
tree | cf71989a69933ad51d38a5725727212d0b11656a /drivers/input/keyboard | |
parent | 285b0b62bc8f1a3cb18ce3f2d9806f1d99736784 (diff) |
Input: gpio-keys - keyboard driver for GPIO buttons
This is an interrupt-driven keyboard driver for simple buttons
connected directly to CPU GPIO lines of embedded ARM systems.
It supports pxa architectures and is used by a number of PDAs
and PocketPC phones in the handhelds.org kernel. Support for
other architectures, such as sa11xx and sc2410, will be added
once generic GPIO API is available.
Signed-off-by: Paul Sokolovsky <pmiscml@gmail.com>
Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 19 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 5 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 147 |
3 files changed, 166 insertions, 5 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 049f2f544e75..1b81a72e19d9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -135,12 +135,12 @@ config KEYBOARD_STOWAWAY | |||
135 | config KEYBOARD_CORGI | 135 | config KEYBOARD_CORGI |
136 | tristate "Corgi keyboard" | 136 | tristate "Corgi keyboard" |
137 | depends on PXA_SHARPSL | 137 | depends on PXA_SHARPSL |
138 | default y | 138 | default y |
139 | help | 139 | help |
140 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | 140 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx |
141 | series of PDAs. | 141 | series of PDAs. |
142 | 142 | ||
143 | To compile this driver as a module, choose M here: the | 143 | To compile this driver as a module, choose M here: the |
144 | module will be called corgikbd. | 144 | module will be called corgikbd. |
145 | 145 | ||
146 | config KEYBOARD_SPITZ | 146 | config KEYBOARD_SPITZ |
@@ -214,4 +214,17 @@ config KEYBOARD_AAED2000 | |||
214 | To compile this driver as a module, choose M here: the | 214 | To compile this driver as a module, choose M here: the |
215 | module will be called aaed2000_kbd. | 215 | module will be called aaed2000_kbd. |
216 | 216 | ||
217 | config KEYBOARD_GPIO | ||
218 | tristate "Buttons on CPU GPIOs (PXA)" | ||
219 | depends on ARCH_PXA | ||
220 | help | ||
221 | This driver implements support for buttons connected | ||
222 | directly to GPIO pins of PXA CPUs. | ||
223 | |||
224 | Say Y here if your device has buttons connected | ||
225 | directly to GPIO pins of the CPU. | ||
226 | |||
227 | To compile this driver as a module, choose M here: the | ||
228 | module will be called gpio-keys. | ||
229 | |||
217 | endif | 230 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 568797907347..586a0fe53be6 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | |||
16 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 16 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
18 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
19 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 19 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
20 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 20 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
21 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | ||
21 | 22 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c new file mode 100644 index 000000000000..3a8f1b427a7f --- /dev/null +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -0,0 +1,147 @@ | |||
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 | #include <linux/version.h> | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/sysctl.h> | ||
21 | #include <linux/proc_fs.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/irq.h> | ||
26 | |||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include <asm/arch/hardware.h> | ||
29 | |||
30 | #include <asm/hardware/gpio_keys.h> | ||
31 | |||
32 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | ||
33 | { | ||
34 | int i; | ||
35 | struct platform_device *pdev = dev_id; | ||
36 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
37 | struct input_dev *input = platform_get_drvdata(pdev); | ||
38 | |||
39 | for (i = 0; i < pdata->nbuttons; i++) { | ||
40 | int gpio = pdata->buttons[i].gpio; | ||
41 | if (irq == IRQ_GPIO(gpio)) { | ||
42 | int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) ^ (pdata->buttons[i].active_low); | ||
43 | |||
44 | input_report_key(input, pdata->buttons[i].keycode, state); | ||
45 | input_sync(input); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return IRQ_HANDLED; | ||
50 | } | ||
51 | |||
52 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | ||
53 | { | ||
54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
55 | struct input_dev *input; | ||
56 | int i, error; | ||
57 | |||
58 | input = input_allocate_device(); | ||
59 | if (!input) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | platform_set_drvdata(pdev, input); | ||
63 | |||
64 | input->evbit[0] = BIT(EV_KEY); | ||
65 | |||
66 | input->name = pdev->name; | ||
67 | input->phys = "gpio-keys/input0"; | ||
68 | input->cdev.dev = &pdev->dev; | ||
69 | input->private = pdata; | ||
70 | |||
71 | input->id.bustype = BUS_HOST; | ||
72 | input->id.vendor = 0x0001; | ||
73 | input->id.product = 0x0001; | ||
74 | input->id.version = 0x0100; | ||
75 | |||
76 | for (i = 0; i < pdata->nbuttons; i++) { | ||
77 | int code = pdata->buttons[i].keycode; | ||
78 | int irq = IRQ_GPIO(pdata->buttons[i].gpio); | ||
79 | |||
80 | set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); | ||
81 | error = request_irq(irq, gpio_keys_isr, SA_SAMPLE_RANDOM, | ||
82 | pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys", | ||
83 | pdev); | ||
84 | if (error) { | ||
85 | printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, ret); | ||
86 | goto fail; | ||
87 | } | ||
88 | set_bit(code, input->keybit); | ||
89 | } | ||
90 | |||
91 | error = input_register_device(input); | ||
92 | if (error) { | ||
93 | printk(KERN_ERR "Unable to register gpio-keys input device\n"); | ||
94 | goto fail; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | |||
99 | fail: | ||
100 | for (i = i - 1; i >= 0; i--) | ||
101 | free_irq(IRQ_GPIO(pdata->buttons[i].gpio), pdev); | ||
102 | |||
103 | input_free_device(input); | ||
104 | |||
105 | return error; | ||
106 | } | ||
107 | |||
108 | static int __devexit gpio_keys_remove(struct platform_device *pdev) | ||
109 | { | ||
110 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
111 | struct input_dev *input = platform_get_drvdata(pdev); | ||
112 | int i; | ||
113 | |||
114 | for (i = 0; i < pdata->nbuttons; i++) { | ||
115 | int irq = IRQ_GPIO(pdata->buttons[i].gpio); | ||
116 | free_irq(irq, pdev); | ||
117 | } | ||
118 | |||
119 | input_unregister_device(input); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | struct platform_driver gpio_keys_device_driver = { | ||
125 | .probe = gpio_keys_probe, | ||
126 | .remove = __devexit_p(gpio_keys_remove), | ||
127 | .driver = { | ||
128 | .name = "gpio-keys", | ||
129 | } | ||
130 | }; | ||
131 | |||
132 | static int __init gpio_keys_init(void) | ||
133 | { | ||
134 | return platform_driver_register(&gpio_keys_device_driver); | ||
135 | } | ||
136 | |||
137 | static void __exit gpio_keys_exit(void) | ||
138 | { | ||
139 | platform_driver_unregister(&gpio_keys_device_driver); | ||
140 | } | ||
141 | |||
142 | module_init(gpio_keys_init); | ||
143 | module_exit(gpio_keys_exit); | ||
144 | |||
145 | MODULE_LICENSE("GPL"); | ||
146 | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); | ||
147 | MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); | ||