aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-05-22 02:36:56 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-05-22 02:36:56 -0400
commitcf9b59e9d3e008591d1f54830f570982bb307a0d (patch)
tree113478ce8fd8c832ba726ffdf59b82cb46356476 /drivers/input/serio
parent44504b2bebf8b5823c59484e73096a7d6574471d (diff)
parentf4b87dee923342505e1ddba8d34ce9de33e75050 (diff)
Merge remote branch 'origin' into secretlab/next-devicetree
Merging in current state of Linus' tree to deal with merge conflicts and build failures in vio.c after merge. Conflicts: drivers/i2c/busses/i2c-cpm.c drivers/i2c/busses/i2c-mpc.c drivers/net/gianfar.c Also fixed up one line in arch/powerpc/kernel/vio.c to use the correct node pointer. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/input/serio')
-rw-r--r--drivers/input/serio/Kconfig16
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/ams_delta_serio.c177
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h14
4 files changed, 208 insertions, 0 deletions
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 7e319d65ec57..f34f1dbeb577 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -209,4 +209,20 @@ config SERIO_ALTERA_PS2
209 To compile this driver as a module, choose M here: the 209 To compile this driver as a module, choose M here: the
210 module will be called altera_ps2. 210 module will be called altera_ps2.
211 211
212config SERIO_AMS_DELTA
213 tristate "Amstrad Delta (E3) mailboard support"
214 depends on MACH_AMS_DELTA
215 default y
216 select AMS_DELTA_FIQ
217 ---help---
218 Say Y here if you have an E3 and want to use its mailboard,
219 or any standard AT keyboard connected to the mailboard port.
220
221 When used for the E3 mailboard, a non-standard key table
222 must be loaded from userspace, possibly using udev extras
223 provided keymap helper utility.
224
225 To compile this driver as a module, choose M here;
226 the module will be called ams_delta_serio.
227
212endif 228endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index bf945f789d05..84c80bf7185e 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -21,5 +21,6 @@ obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
21obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o 21obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
22obj-$(CONFIG_SERIO_LIBPS2) += libps2.o 22obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
23obj-$(CONFIG_SERIO_RAW) += serio_raw.o 23obj-$(CONFIG_SERIO_RAW) += serio_raw.o
24obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o
24obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o 25obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o
25obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o 26obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
new file mode 100644
index 000000000000..8f1770e1e08b
--- /dev/null
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -0,0 +1,177 @@
1/*
2 * Amstrad E3 (Delta) keyboard port driver
3 *
4 * Copyright (c) 2006 Matt Callow
5 * Copyright (c) 2010 Janusz Krzysztofik
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * Thanks to Cliff Lawson for his help
12 *
13 * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial
14 * transmission. The keyboard port is formed of two GPIO lines, for clock
15 * and data. Due to strict timing requirements of the interface,
16 * the serial data stream is read and processed by a FIQ handler.
17 * The resulting words are fetched by this driver from a circular buffer.
18 *
19 * Standard AT keyboard driver (atkbd) is used for handling the keyboard data.
20 * However, when used with the E3 mailboard that producecs non-standard
21 * scancodes, a custom key table must be prepared and loaded from userspace.
22 */
23#include <linux/gpio.h>
24#include <linux/irq.h>
25#include <linux/serio.h>
26#include <linux/slab.h>
27
28#include <asm/mach-types.h>
29#include <plat/board-ams-delta.h>
30
31#include <mach/ams-delta-fiq.h>
32
33MODULE_AUTHOR("Matt Callow");
34MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
35MODULE_LICENSE("GPL");
36
37static struct serio *ams_delta_serio;
38
39static int check_data(int data)
40{
41 int i, parity = 0;
42
43 /* check valid stop bit */
44 if (!(data & 0x400)) {
45 dev_warn(&ams_delta_serio->dev,
46 "invalid stop bit, data=0x%X\n",
47 data);
48 return SERIO_FRAME;
49 }
50 /* calculate the parity */
51 for (i = 1; i < 10; i++) {
52 if (data & (1 << i))
53 parity++;
54 }
55 /* it should be odd */
56 if (!(parity & 0x01)) {
57 dev_warn(&ams_delta_serio->dev,
58 "paritiy check failed, data=0x%X parity=0x%X\n",
59 data, parity);
60 return SERIO_PARITY;
61 }
62 return 0;
63}
64
65static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
66{
67 int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
68 int data, dfl;
69 u8 scancode;
70
71 fiq_buffer[FIQ_IRQ_PEND] = 0;
72
73 /*
74 * Read data from the circular buffer, check it
75 * and then pass it on the serio
76 */
77 while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
78
79 data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
80 fiq_buffer[FIQ_KEYS_CNT]--;
81 if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
82 fiq_buffer[FIQ_HEAD_OFFSET] = 0;
83
84 dfl = check_data(data);
85 scancode = (u8) (data >> 1) & 0xFF;
86 serio_interrupt(ams_delta_serio, scancode, dfl);
87 }
88 return IRQ_HANDLED;
89}
90
91static int ams_delta_serio_open(struct serio *serio)
92{
93 /* enable keyboard */
94 ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR,
95 AMD_DELTA_LATCH2_KEYBRD_PWR);
96
97 return 0;
98}
99
100static void ams_delta_serio_close(struct serio *serio)
101{
102 /* disable keyboard */
103 ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, 0);
104}
105
106static int __init ams_delta_serio_init(void)
107{
108 int err;
109
110 if (!machine_is_ams_delta())
111 return -ENODEV;
112
113 ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
114 if (!ams_delta_serio)
115 return -ENOMEM;
116
117 ams_delta_serio->id.type = SERIO_8042;
118 ams_delta_serio->open = ams_delta_serio_open;
119 ams_delta_serio->close = ams_delta_serio_close;
120 strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
121 sizeof(ams_delta_serio->name));
122 strlcpy(ams_delta_serio->phys, "GPIO/serio0",
123 sizeof(ams_delta_serio->phys));
124
125 err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_DATA, "serio-data");
126 if (err) {
127 pr_err("ams_delta_serio: Couldn't request gpio pin for data\n");
128 goto serio;
129 }
130 gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
131
132 err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_CLK, "serio-clock");
133 if (err) {
134 pr_err("ams_delta_serio: couldn't request gpio pin for clock\n");
135 goto gpio_data;
136 }
137 gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
138
139 err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
140 ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
141 "ams-delta-serio", 0);
142 if (err < 0) {
143 pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
144 gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
145 goto gpio_clk;
146 }
147 /*
148 * Since GPIO register handling for keyboard clock pin is performed
149 * at FIQ level, switch back from edge to simple interrupt handler
150 * to avoid bad interaction.
151 */
152 set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
153 handle_simple_irq);
154
155 serio_register_port(ams_delta_serio);
156 dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
157
158 return 0;
159gpio_clk:
160 gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
161gpio_data:
162 gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
163serio:
164 kfree(ams_delta_serio);
165 return err;
166}
167module_init(ams_delta_serio_init);
168
169static void __exit ams_delta_serio_exit(void)
170{
171 serio_unregister_port(ams_delta_serio);
172 free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
173 gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
174 gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
175 kfree(ams_delta_serio);
176}
177module_exit(ams_delta_serio_exit);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index ead0494721d0..6168469ad1a6 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -660,8 +660,21 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
660} 660}
661 661
662static struct pnp_device_id pnp_kbd_devids[] = { 662static struct pnp_device_id pnp_kbd_devids[] = {
663 { .id = "PNP0300", .driver_data = 0 },
664 { .id = "PNP0301", .driver_data = 0 },
665 { .id = "PNP0302", .driver_data = 0 },
663 { .id = "PNP0303", .driver_data = 0 }, 666 { .id = "PNP0303", .driver_data = 0 },
667 { .id = "PNP0304", .driver_data = 0 },
668 { .id = "PNP0305", .driver_data = 0 },
669 { .id = "PNP0306", .driver_data = 0 },
670 { .id = "PNP0309", .driver_data = 0 },
671 { .id = "PNP030a", .driver_data = 0 },
664 { .id = "PNP030b", .driver_data = 0 }, 672 { .id = "PNP030b", .driver_data = 0 },
673 { .id = "PNP0320", .driver_data = 0 },
674 { .id = "PNP0343", .driver_data = 0 },
675 { .id = "PNP0344", .driver_data = 0 },
676 { .id = "PNP0345", .driver_data = 0 },
677 { .id = "CPQA0D7", .driver_data = 0 },
665 { .id = "", }, 678 { .id = "", },
666}; 679};
667 680
@@ -672,6 +685,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
672}; 685};
673 686
674static struct pnp_device_id pnp_aux_devids[] = { 687static struct pnp_device_id pnp_aux_devids[] = {
688 { .id = "AUI0200", .driver_data = 0 },
675 { .id = "FJC6000", .driver_data = 0 }, 689 { .id = "FJC6000", .driver_data = 0 },
676 { .id = "FJC6001", .driver_data = 0 }, 690 { .id = "FJC6001", .driver_data = 0 },
677 { .id = "PNP0f03", .driver_data = 0 }, 691 { .id = "PNP0f03", .driver_data = 0 },