diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
commit | eda3d8f5604860aae1bb9996bb5efc4213778369 (patch) | |
tree | 9d3887d2665bcc5f5abf200758794545c7b2c69b /drivers/input/serio | |
parent | 87a9f704658a40940e740b1d73d861667e9164d3 (diff) | |
parent | 8be1a6d6c77ab4532e4476fdb8177030ef48b52c (diff) |
Merge commit 'upstream/master'
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/serio/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/serio/ct82c710.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/hil_mlc.c | 6 | ||||
-rw-r--r-- | drivers/input/serio/hp_sdc.c | 11 | ||||
-rw-r--r-- | drivers/input/serio/hp_sdc_mlc.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 67 | ||||
-rw-r--r-- | drivers/input/serio/libps2.c | 52 | ||||
-rw-r--r-- | drivers/input/serio/q40kbd.c | 4 | ||||
-rw-r--r-- | drivers/input/serio/rpckbd.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/serio.c | 9 | ||||
-rw-r--r-- | drivers/input/serio/serport.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/xilinx_ps2.c | 380 |
13 files changed, 469 insertions, 79 deletions
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index ec4b6610f730..27d70d326ff3 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -190,4 +190,14 @@ config SERIO_RAW | |||
190 | To compile this driver as a module, choose M here: the | 190 | To compile this driver as a module, choose M here: the |
191 | module will be called serio_raw. | 191 | module will be called serio_raw. |
192 | 192 | ||
193 | config SERIO_XILINX_XPS_PS2 | ||
194 | tristate "Xilinx XPS PS/2 Controller Support" | ||
195 | depends on PPC | ||
196 | help | ||
197 | This driver supports XPS PS/2 IP from the Xilinx EDK on | ||
198 | PowerPC platform. | ||
199 | |||
200 | To compile this driver as a module, choose M here: the | ||
201 | module will be called xilinx_ps2. | ||
202 | |||
193 | endif | 203 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 38b886887cbc..9b6c8135955f 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
@@ -21,3 +21,4 @@ obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o | |||
21 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o | 21 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o |
22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o | 22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o |
23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o | 23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o |
24 | obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o | ||
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 0d35018c23a9..d1380fc72cc6 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 2 | * Copyright (c) 1999-2001 Vojtech Pavlik |
5 | */ | 3 | */ |
6 | 4 | ||
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 93a1a6ba216a..37586a68d345 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
@@ -76,7 +76,7 @@ static struct timer_list hil_mlcs_kicker; | |||
76 | static int hil_mlcs_probe; | 76 | static int hil_mlcs_probe; |
77 | 77 | ||
78 | static void hil_mlcs_process(unsigned long unused); | 78 | static void hil_mlcs_process(unsigned long unused); |
79 | DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); | 79 | static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); |
80 | 80 | ||
81 | 81 | ||
82 | /* #define HIL_MLC_DEBUG */ | 82 | /* #define HIL_MLC_DEBUG */ |
@@ -459,7 +459,7 @@ static int hilse_operate(hil_mlc *mlc, int repoll) | |||
459 | #define OUT_LAST(pack) \ | 459 | #define OUT_LAST(pack) \ |
460 | { HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 }, | 460 | { HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 }, |
461 | 461 | ||
462 | const struct hilse_node hil_mlc_se[HILSEN_END] = { | 462 | static const struct hilse_node hil_mlc_se[HILSEN_END] = { |
463 | 463 | ||
464 | /* 0 HILSEN_START */ | 464 | /* 0 HILSEN_START */ |
465 | FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) | 465 | FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) |
@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused) | |||
784 | 784 | ||
785 | /************************* Keepalive timer task *********************/ | 785 | /************************* Keepalive timer task *********************/ |
786 | 786 | ||
787 | void hil_mlcs_timer(unsigned long data) | 787 | static void hil_mlcs_timer(unsigned long data) |
788 | { | 788 | { |
789 | hil_mlcs_probe = 1; | 789 | hil_mlcs_probe = 1; |
790 | tasklet_schedule(&hil_mlcs_tasklet); | 790 | tasklet_schedule(&hil_mlcs_tasklet); |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index edfedd9a166c..0d395979b2d1 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -67,9 +67,9 @@ | |||
67 | #include <linux/module.h> | 67 | #include <linux/module.h> |
68 | #include <linux/ioport.h> | 68 | #include <linux/ioport.h> |
69 | #include <linux/time.h> | 69 | #include <linux/time.h> |
70 | #include <linux/semaphore.h> | ||
70 | #include <linux/slab.h> | 71 | #include <linux/slab.h> |
71 | #include <linux/hil.h> | 72 | #include <linux/hil.h> |
72 | #include <linux/semaphore.h> | ||
73 | #include <asm/io.h> | 73 | #include <asm/io.h> |
74 | #include <asm/system.h> | 74 | #include <asm/system.h> |
75 | 75 | ||
@@ -105,6 +105,10 @@ EXPORT_SYMBOL(__hp_sdc_enqueue_transaction); | |||
105 | EXPORT_SYMBOL(hp_sdc_enqueue_transaction); | 105 | EXPORT_SYMBOL(hp_sdc_enqueue_transaction); |
106 | EXPORT_SYMBOL(hp_sdc_dequeue_transaction); | 106 | EXPORT_SYMBOL(hp_sdc_dequeue_transaction); |
107 | 107 | ||
108 | static unsigned int hp_sdc_disabled; | ||
109 | module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0); | ||
110 | MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver."); | ||
111 | |||
108 | static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ | 112 | static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ |
109 | 113 | ||
110 | /*************** primitives for use in any context *********************/ | 114 | /*************** primitives for use in any context *********************/ |
@@ -980,6 +984,11 @@ static int __init hp_sdc_register(void) | |||
980 | unsigned char i; | 984 | unsigned char i; |
981 | #endif | 985 | #endif |
982 | 986 | ||
987 | if (hp_sdc_disabled) { | ||
988 | printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n"); | ||
989 | return -ENODEV; | ||
990 | } | ||
991 | |||
983 | hp_sdc.dev = NULL; | 992 | hp_sdc.dev = NULL; |
984 | hp_sdc.dev_err = 0; | 993 | hp_sdc.dev_err = 0; |
985 | #if defined(__hppa__) | 994 | #if defined(__hppa__) |
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index 587398f5c9df..b587e2d576ac 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c | |||
@@ -50,7 +50,7 @@ MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | |||
50 | MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines"); | 50 | MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines"); |
51 | MODULE_LICENSE("Dual BSD/GPL"); | 51 | MODULE_LICENSE("Dual BSD/GPL"); |
52 | 52 | ||
53 | struct hp_sdc_mlc_priv_s { | 53 | static struct hp_sdc_mlc_priv_s { |
54 | int emtestmode; | 54 | int emtestmode; |
55 | hp_sdc_transaction trans; | 55 | hp_sdc_transaction trans; |
56 | u8 tseq[16]; | 56 | u8 tseq[16]; |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 78eb7841174c..fe732a574ec2 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -63,13 +63,22 @@ static inline void i8042_write_command(int val) | |||
63 | outb(val, I8042_COMMAND_REG); | 63 | outb(val, I8042_COMMAND_REG); |
64 | } | 64 | } |
65 | 65 | ||
66 | #if defined(__i386__) || defined(__x86_64__) | 66 | #ifdef CONFIG_X86 |
67 | 67 | ||
68 | #include <linux/dmi.h> | 68 | #include <linux/dmi.h> |
69 | 69 | ||
70 | static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | 70 | static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { |
71 | { | 71 | { |
72 | /* AUX LOOP command does not raise AUX IRQ */ | 72 | /* AUX LOOP command does not raise AUX IRQ */ |
73 | .ident = "Arima-Rioworks HDAMB", | ||
74 | .matches = { | ||
75 | DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), | ||
76 | DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), | ||
77 | DMI_MATCH(DMI_BOARD_VERSION, "Rev E"), | ||
78 | }, | ||
79 | }, | ||
80 | { | ||
81 | /* AUX LOOP command does not raise AUX IRQ */ | ||
73 | .ident = "ASUS P65UP5", | 82 | .ident = "ASUS P65UP5", |
74 | .matches = { | 83 | .matches = { |
75 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | 84 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
@@ -118,6 +127,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
118 | DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), | 127 | DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), |
119 | }, | 128 | }, |
120 | }, | 129 | }, |
130 | { | ||
131 | .ident = "Medion MAM 2070", | ||
132 | .matches = { | ||
133 | DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), | ||
134 | DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), | ||
135 | DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), | ||
136 | }, | ||
137 | }, | ||
121 | { } | 138 | { } |
122 | }; | 139 | }; |
123 | 140 | ||
@@ -291,17 +308,36 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
291 | DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), | 308 | DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), |
292 | }, | 309 | }, |
293 | }, | 310 | }, |
311 | { | ||
312 | .ident = "Acer Aspire 1360", | ||
313 | .matches = { | ||
314 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
315 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), | ||
316 | }, | ||
317 | }, | ||
318 | { | ||
319 | .ident = "Gericom Bellagio", | ||
320 | .matches = { | ||
321 | DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), | ||
322 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), | ||
323 | }, | ||
324 | }, | ||
294 | { } | 325 | { } |
295 | }; | 326 | }; |
296 | 327 | ||
297 | 328 | #ifdef CONFIG_PNP | |
298 | 329 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |
330 | { | ||
331 | .ident = "Intel MBO Desktop D845PESV", | ||
332 | .matches = { | ||
333 | DMI_MATCH(DMI_BOARD_NAME, "D845PESV"), | ||
334 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | ||
335 | }, | ||
336 | }, | ||
337 | { } | ||
338 | }; | ||
299 | #endif | 339 | #endif |
300 | 340 | ||
301 | #ifdef CONFIG_X86 | ||
302 | |||
303 | #include <linux/dmi.h> | ||
304 | |||
305 | /* | 341 | /* |
306 | * Some Wistron based laptops need us to explicitly enable the 'Dritek | 342 | * Some Wistron based laptops need us to explicitly enable the 'Dritek |
307 | * keyboard extension' to make their extra keys start generating scancodes. | 343 | * keyboard extension' to make their extra keys start generating scancodes. |
@@ -331,6 +367,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
331 | }, | 367 | }, |
332 | }, | 368 | }, |
333 | { | 369 | { |
370 | .ident = "Acer Aspire 5720", | ||
371 | .matches = { | ||
372 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
373 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), | ||
374 | }, | ||
375 | }, | ||
376 | { | ||
334 | .ident = "Acer Aspire 9110", | 377 | .ident = "Acer Aspire 9110", |
335 | .matches = { | 378 | .matches = { |
336 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 379 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
@@ -356,7 +399,6 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
356 | 399 | ||
357 | #endif /* CONFIG_X86 */ | 400 | #endif /* CONFIG_X86 */ |
358 | 401 | ||
359 | |||
360 | #ifdef CONFIG_PNP | 402 | #ifdef CONFIG_PNP |
361 | #include <linux/pnp.h> | 403 | #include <linux/pnp.h> |
362 | 404 | ||
@@ -466,6 +508,11 @@ static int __init i8042_pnp_init(void) | |||
466 | int pnp_data_busted = 0; | 508 | int pnp_data_busted = 0; |
467 | int err; | 509 | int err; |
468 | 510 | ||
511 | #ifdef CONFIG_X86 | ||
512 | if (dmi_check_system(i8042_dmi_nopnp_table)) | ||
513 | i8042_nopnp = 1; | ||
514 | #endif | ||
515 | |||
469 | if (i8042_nopnp) { | 516 | if (i8042_nopnp) { |
470 | printk(KERN_INFO "i8042: PNP detection disabled\n"); | 517 | printk(KERN_INFO "i8042: PNP detection disabled\n"); |
471 | return 0; | 518 | return 0; |
@@ -591,15 +638,13 @@ static int __init i8042_platform_init(void) | |||
591 | i8042_reset = 1; | 638 | i8042_reset = 1; |
592 | #endif | 639 | #endif |
593 | 640 | ||
594 | #if defined(__i386__) || defined(__x86_64__) | 641 | #ifdef CONFIG_X86 |
595 | if (dmi_check_system(i8042_dmi_noloop_table)) | 642 | if (dmi_check_system(i8042_dmi_noloop_table)) |
596 | i8042_noloop = 1; | 643 | i8042_noloop = 1; |
597 | 644 | ||
598 | if (dmi_check_system(i8042_dmi_nomux_table)) | 645 | if (dmi_check_system(i8042_dmi_nomux_table)) |
599 | i8042_nomux = 1; | 646 | i8042_nomux = 1; |
600 | #endif | ||
601 | 647 | ||
602 | #ifdef CONFIG_X86 | ||
603 | if (dmi_check_system(i8042_dmi_dritek_table)) | 648 | if (dmi_check_system(i8042_dmi_dritek_table)) |
604 | i8042_dritek = 1; | 649 | i8042_dritek = 1; |
605 | #endif /* CONFIG_X86 */ | 650 | #endif /* CONFIG_X86 */ |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index b819239d74dc..2b304c22c200 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -26,15 +26,6 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | |||
26 | MODULE_DESCRIPTION("PS/2 driver library"); | 26 | MODULE_DESCRIPTION("PS/2 driver library"); |
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | 28 | ||
29 | /* Work structure to schedule execution of a command */ | ||
30 | struct ps2work { | ||
31 | struct work_struct work; | ||
32 | struct ps2dev *ps2dev; | ||
33 | int command; | ||
34 | unsigned char param[0]; | ||
35 | }; | ||
36 | |||
37 | |||
38 | /* | 29 | /* |
39 | * ps2_sendbyte() sends a byte to the device and waits for acknowledge. | 30 | * ps2_sendbyte() sends a byte to the device and waits for acknowledge. |
40 | * It doesn't handle retransmission, though it could - because if there | 31 | * It doesn't handle retransmission, though it could - because if there |
@@ -246,49 +237,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
246 | EXPORT_SYMBOL(ps2_command); | 237 | EXPORT_SYMBOL(ps2_command); |
247 | 238 | ||
248 | /* | 239 | /* |
249 | * ps2_execute_scheduled_command() sends a command, previously scheduled by | ||
250 | * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.) | ||
251 | */ | ||
252 | |||
253 | static void ps2_execute_scheduled_command(struct work_struct *work) | ||
254 | { | ||
255 | struct ps2work *ps2work = container_of(work, struct ps2work, work); | ||
256 | |||
257 | ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command); | ||
258 | kfree(ps2work); | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * ps2_schedule_command() allows to schedule delayed execution of a PS/2 | ||
263 | * command and can be used to issue a command from an interrupt or softirq | ||
264 | * context. | ||
265 | */ | ||
266 | |||
267 | int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command) | ||
268 | { | ||
269 | struct ps2work *ps2work; | ||
270 | int send = (command >> 12) & 0xf; | ||
271 | int receive = (command >> 8) & 0xf; | ||
272 | |||
273 | if (!(ps2work = kmalloc(sizeof(struct ps2work) + max(send, receive), GFP_ATOMIC))) | ||
274 | return -1; | ||
275 | |||
276 | memset(ps2work, 0, sizeof(struct ps2work)); | ||
277 | ps2work->ps2dev = ps2dev; | ||
278 | ps2work->command = command; | ||
279 | memcpy(ps2work->param, param, send); | ||
280 | INIT_WORK(&ps2work->work, ps2_execute_scheduled_command); | ||
281 | |||
282 | if (!schedule_work(&ps2work->work)) { | ||
283 | kfree(ps2work); | ||
284 | return -1; | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | EXPORT_SYMBOL(ps2_schedule_command); | ||
290 | |||
291 | /* | ||
292 | * ps2_init() initializes ps2dev structure | 240 | * ps2_init() initializes ps2dev structure |
293 | */ | 241 | */ |
294 | 242 | ||
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index d962a8d78b14..e36a0901646c 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 2 | * Copyright (c) 2000-2001 Vojtech Pavlik |
5 | * | 3 | * |
6 | * Based on the work of: | 4 | * Based on the work of: |
@@ -49,7 +47,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
49 | MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); | 47 | MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); |
50 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
51 | 49 | ||
52 | DEFINE_SPINLOCK(q40kbd_lock); | 50 | static DEFINE_SPINLOCK(q40kbd_lock); |
53 | static struct serio *q40kbd_port; | 51 | static struct serio *q40kbd_port; |
54 | static struct platform_device *q40kbd_device; | 52 | static struct platform_device *q40kbd_device; |
55 | 53 | ||
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 34c59d9c6205..1567b7782478 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 2 | * Copyright (c) 2000-2001 Vojtech Pavlik |
5 | * Copyright (c) 2002 Russell King | 3 | * Copyright (c) 2002 Russell King |
6 | */ | 4 | */ |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 7f5293828fbf..78f2abb5c11b 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -331,9 +331,10 @@ static void serio_handle_event(void) | |||
331 | } | 331 | } |
332 | 332 | ||
333 | /* | 333 | /* |
334 | * Remove all events that have been submitted for a given serio port. | 334 | * Remove all events that have been submitted for a given |
335 | * object, be it serio port or driver. | ||
335 | */ | 336 | */ |
336 | static void serio_remove_pending_events(struct serio *serio) | 337 | static void serio_remove_pending_events(void *object) |
337 | { | 338 | { |
338 | struct list_head *node, *next; | 339 | struct list_head *node, *next; |
339 | struct serio_event *event; | 340 | struct serio_event *event; |
@@ -343,7 +344,7 @@ static void serio_remove_pending_events(struct serio *serio) | |||
343 | 344 | ||
344 | list_for_each_safe(node, next, &serio_event_list) { | 345 | list_for_each_safe(node, next, &serio_event_list) { |
345 | event = list_entry(node, struct serio_event, node); | 346 | event = list_entry(node, struct serio_event, node); |
346 | if (event->object == serio) { | 347 | if (event->object == object) { |
347 | list_del_init(node); | 348 | list_del_init(node); |
348 | serio_free_event(event); | 349 | serio_free_event(event); |
349 | } | 350 | } |
@@ -837,7 +838,9 @@ void serio_unregister_driver(struct serio_driver *drv) | |||
837 | struct serio *serio; | 838 | struct serio *serio; |
838 | 839 | ||
839 | mutex_lock(&serio_mutex); | 840 | mutex_lock(&serio_mutex); |
841 | |||
840 | drv->manual_bind = 1; /* so serio_find_driver ignores it */ | 842 | drv->manual_bind = 1; /* so serio_find_driver ignores it */ |
843 | serio_remove_pending_events(drv); | ||
841 | 844 | ||
842 | start_over: | 845 | start_over: |
843 | list_for_each_entry(serio, &serio_list, node) { | 846 | list_for_each_entry(serio, &serio_list, node) { |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 7ff71ba7b7c9..b9694b6445d0 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -216,7 +216,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty) | |||
216 | * The line discipline structure. | 216 | * The line discipline structure. |
217 | */ | 217 | */ |
218 | 218 | ||
219 | static struct tty_ldisc serport_ldisc = { | 219 | static struct tty_ldisc_ops serport_ldisc = { |
220 | .owner = THIS_MODULE, | 220 | .owner = THIS_MODULE, |
221 | .name = "input", | 221 | .name = "input", |
222 | .open = serport_ldisc_open, | 222 | .open = serport_ldisc_open, |
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c new file mode 100644 index 000000000000..0ed044d5e685 --- /dev/null +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Xilinx XPS PS/2 device driver | ||
3 | * | ||
4 | * (c) 2005 MontaVista Software, Inc. | ||
5 | * (c) 2008 Xilinx, Inc. | ||
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 as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License along | ||
13 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
14 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/serio.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/of_platform.h> | ||
28 | |||
29 | #define DRIVER_NAME "xilinx_ps2" | ||
30 | |||
31 | /* Register offsets for the xps2 device */ | ||
32 | #define XPS2_SRST_OFFSET 0x00000000 /* Software Reset register */ | ||
33 | #define XPS2_STATUS_OFFSET 0x00000004 /* Status register */ | ||
34 | #define XPS2_RX_DATA_OFFSET 0x00000008 /* Receive Data register */ | ||
35 | #define XPS2_TX_DATA_OFFSET 0x0000000C /* Transmit Data register */ | ||
36 | #define XPS2_GIER_OFFSET 0x0000002C /* Global Interrupt Enable reg */ | ||
37 | #define XPS2_IPISR_OFFSET 0x00000030 /* Interrupt Status register */ | ||
38 | #define XPS2_IPIER_OFFSET 0x00000038 /* Interrupt Enable register */ | ||
39 | |||
40 | /* Reset Register Bit Definitions */ | ||
41 | #define XPS2_SRST_RESET 0x0000000A /* Software Reset */ | ||
42 | |||
43 | /* Status Register Bit Positions */ | ||
44 | #define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */ | ||
45 | #define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */ | ||
46 | |||
47 | /* Bit definitions for ISR/IER registers. Both the registers have the same bit | ||
48 | * definitions and are only defined once. */ | ||
49 | #define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */ | ||
50 | #define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */ | ||
51 | #define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */ | ||
52 | #define XPS2_IPIXR_RX_OVF 0x00000008 /* Receive Overflow Interrupt */ | ||
53 | #define XPS2_IPIXR_RX_ERR 0x00000010 /* Receive Error Interrupt */ | ||
54 | #define XPS2_IPIXR_RX_FULL 0x00000020 /* Receive Data Interrupt */ | ||
55 | |||
56 | /* Mask for all the Transmit Interrupts */ | ||
57 | #define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK) | ||
58 | |||
59 | /* Mask for all the Receive Interrupts */ | ||
60 | #define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \ | ||
61 | XPS2_IPIXR_RX_FULL) | ||
62 | |||
63 | /* Mask for all the Interrupts */ | ||
64 | #define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \ | ||
65 | XPS2_IPIXR_WDT_TOUT) | ||
66 | |||
67 | /* Global Interrupt Enable mask */ | ||
68 | #define XPS2_GIER_GIE_MASK 0x80000000 | ||
69 | |||
70 | struct xps2data { | ||
71 | int irq; | ||
72 | u32 phys_addr; | ||
73 | u32 remap_size; | ||
74 | spinlock_t lock; | ||
75 | u8 rxb; /* Rx buffer */ | ||
76 | void __iomem *base_address; /* virt. address of control registers */ | ||
77 | unsigned int dfl; | ||
78 | struct serio serio; /* serio */ | ||
79 | }; | ||
80 | |||
81 | /************************************/ | ||
82 | /* XPS PS/2 data transmission calls */ | ||
83 | /************************************/ | ||
84 | |||
85 | /* | ||
86 | * xps2_recv() will attempt to receive a byte of data from the PS/2 port. | ||
87 | */ | ||
88 | static int xps2_recv(struct xps2data *drvdata, u8 *byte) | ||
89 | { | ||
90 | u32 sr; | ||
91 | int status = -1; | ||
92 | |||
93 | /* If there is data available in the PS/2 receiver, read it */ | ||
94 | sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET); | ||
95 | if (sr & XPS2_STATUS_RX_FULL) { | ||
96 | *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET); | ||
97 | status = 0; | ||
98 | } | ||
99 | |||
100 | return status; | ||
101 | } | ||
102 | |||
103 | /*********************/ | ||
104 | /* Interrupt handler */ | ||
105 | /*********************/ | ||
106 | static irqreturn_t xps2_interrupt(int irq, void *dev_id) | ||
107 | { | ||
108 | struct xps2data *drvdata = dev_id; | ||
109 | u32 intr_sr; | ||
110 | u8 c; | ||
111 | int status; | ||
112 | |||
113 | /* Get the PS/2 interrupts and clear them */ | ||
114 | intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET); | ||
115 | out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr); | ||
116 | |||
117 | /* Check which interrupt is active */ | ||
118 | if (intr_sr & XPS2_IPIXR_RX_OVF) | ||
119 | printk(KERN_WARNING "%s: receive overrun error\n", | ||
120 | drvdata->serio.name); | ||
121 | |||
122 | if (intr_sr & XPS2_IPIXR_RX_ERR) | ||
123 | drvdata->dfl |= SERIO_PARITY; | ||
124 | |||
125 | if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT)) | ||
126 | drvdata->dfl |= SERIO_TIMEOUT; | ||
127 | |||
128 | if (intr_sr & XPS2_IPIXR_RX_FULL) { | ||
129 | status = xps2_recv(drvdata, &drvdata->rxb); | ||
130 | |||
131 | /* Error, if a byte is not received */ | ||
132 | if (status) { | ||
133 | printk(KERN_ERR | ||
134 | "%s: wrong rcvd byte count (%d)\n", | ||
135 | drvdata->serio.name, status); | ||
136 | } else { | ||
137 | c = drvdata->rxb; | ||
138 | serio_interrupt(&drvdata->serio, c, drvdata->dfl); | ||
139 | drvdata->dfl = 0; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | if (intr_sr & XPS2_IPIXR_TX_ACK) | ||
144 | drvdata->dfl = 0; | ||
145 | |||
146 | return IRQ_HANDLED; | ||
147 | } | ||
148 | |||
149 | /*******************/ | ||
150 | /* serio callbacks */ | ||
151 | /*******************/ | ||
152 | |||
153 | /* | ||
154 | * sxps2_write() sends a byte out through the PS/2 interface. | ||
155 | */ | ||
156 | static int sxps2_write(struct serio *pserio, unsigned char c) | ||
157 | { | ||
158 | struct xps2data *drvdata = pserio->port_data; | ||
159 | unsigned long flags; | ||
160 | u32 sr; | ||
161 | int status = -1; | ||
162 | |||
163 | spin_lock_irqsave(&drvdata->lock, flags); | ||
164 | |||
165 | /* If the PS/2 transmitter is empty send a byte of data */ | ||
166 | sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET); | ||
167 | if (!(sr & XPS2_STATUS_TX_FULL)) { | ||
168 | out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c); | ||
169 | status = 0; | ||
170 | } | ||
171 | |||
172 | spin_unlock_irqrestore(&drvdata->lock, flags); | ||
173 | |||
174 | return status; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * sxps2_open() is called when a port is open by the higher layer. | ||
179 | */ | ||
180 | static int sxps2_open(struct serio *pserio) | ||
181 | { | ||
182 | struct xps2data *drvdata = pserio->port_data; | ||
183 | int retval; | ||
184 | |||
185 | retval = request_irq(drvdata->irq, &xps2_interrupt, 0, | ||
186 | DRIVER_NAME, drvdata); | ||
187 | if (retval) { | ||
188 | printk(KERN_ERR | ||
189 | "%s: Couldn't allocate interrupt %d\n", | ||
190 | drvdata->serio.name, drvdata->irq); | ||
191 | return retval; | ||
192 | } | ||
193 | |||
194 | /* start reception by enabling the interrupts */ | ||
195 | out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK); | ||
196 | out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL); | ||
197 | (void)xps2_recv(drvdata, &drvdata->rxb); | ||
198 | |||
199 | return 0; /* success */ | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * sxps2_close() frees the interrupt. | ||
204 | */ | ||
205 | static void sxps2_close(struct serio *pserio) | ||
206 | { | ||
207 | struct xps2data *drvdata = pserio->port_data; | ||
208 | |||
209 | /* Disable the PS2 interrupts */ | ||
210 | out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00); | ||
211 | out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00); | ||
212 | free_irq(drvdata->irq, drvdata); | ||
213 | } | ||
214 | |||
215 | /*********************/ | ||
216 | /* Device setup code */ | ||
217 | /*********************/ | ||
218 | |||
219 | static int xps2_setup(struct device *dev, struct resource *regs_res, | ||
220 | struct resource *irq_res) | ||
221 | { | ||
222 | struct xps2data *drvdata; | ||
223 | struct serio *serio; | ||
224 | unsigned long remap_size; | ||
225 | int retval; | ||
226 | |||
227 | if (!dev) | ||
228 | return -EINVAL; | ||
229 | |||
230 | if (!regs_res || !irq_res) { | ||
231 | dev_err(dev, "IO resource(s) not found\n"); | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); | ||
236 | if (!drvdata) { | ||
237 | dev_err(dev, "Couldn't allocate device private record\n"); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | dev_set_drvdata(dev, drvdata); | ||
242 | |||
243 | spin_lock_init(&drvdata->lock); | ||
244 | drvdata->irq = irq_res->start; | ||
245 | |||
246 | remap_size = regs_res->end - regs_res->start + 1; | ||
247 | if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) { | ||
248 | dev_err(dev, "Couldn't lock memory region at 0x%08X\n", | ||
249 | (unsigned int)regs_res->start); | ||
250 | retval = -EBUSY; | ||
251 | goto failed1; | ||
252 | } | ||
253 | |||
254 | /* Fill in configuration data and add them to the list */ | ||
255 | drvdata->phys_addr = regs_res->start; | ||
256 | drvdata->remap_size = remap_size; | ||
257 | drvdata->base_address = ioremap(regs_res->start, remap_size); | ||
258 | if (drvdata->base_address == NULL) { | ||
259 | dev_err(dev, "Couldn't ioremap memory at 0x%08X\n", | ||
260 | (unsigned int)regs_res->start); | ||
261 | retval = -EFAULT; | ||
262 | goto failed2; | ||
263 | } | ||
264 | |||
265 | /* Disable all the interrupts, just in case */ | ||
266 | out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0); | ||
267 | |||
268 | /* Reset the PS2 device and abort any current transaction, to make sure | ||
269 | * we have the PS2 in a good state */ | ||
270 | out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); | ||
271 | |||
272 | dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n", | ||
273 | drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq); | ||
274 | |||
275 | serio = &drvdata->serio; | ||
276 | serio->id.type = SERIO_8042; | ||
277 | serio->write = sxps2_write; | ||
278 | serio->open = sxps2_open; | ||
279 | serio->close = sxps2_close; | ||
280 | serio->port_data = drvdata; | ||
281 | serio->dev.parent = dev; | ||
282 | snprintf(serio->name, sizeof(serio->name), | ||
283 | "Xilinx XPS PS/2 at %08X", drvdata->phys_addr); | ||
284 | snprintf(serio->phys, sizeof(serio->phys), | ||
285 | "xilinxps2/serio at %08X", drvdata->phys_addr); | ||
286 | serio_register_port(serio); | ||
287 | |||
288 | return 0; /* success */ | ||
289 | |||
290 | failed2: | ||
291 | release_mem_region(regs_res->start, remap_size); | ||
292 | failed1: | ||
293 | kfree(drvdata); | ||
294 | dev_set_drvdata(dev, NULL); | ||
295 | |||
296 | return retval; | ||
297 | } | ||
298 | |||
299 | /***************************/ | ||
300 | /* OF Platform Bus Support */ | ||
301 | /***************************/ | ||
302 | |||
303 | static int __devinit xps2_of_probe(struct of_device *ofdev, const struct | ||
304 | of_device_id * match) | ||
305 | { | ||
306 | struct resource r_irq; /* Interrupt resources */ | ||
307 | struct resource r_mem; /* IO mem resources */ | ||
308 | int rc = 0; | ||
309 | |||
310 | printk(KERN_INFO "Device Tree Probing \'%s\'\n", | ||
311 | ofdev->node->name); | ||
312 | |||
313 | /* Get iospace for the device */ | ||
314 | rc = of_address_to_resource(ofdev->node, 0, &r_mem); | ||
315 | if (rc) { | ||
316 | dev_err(&ofdev->dev, "invalid address\n"); | ||
317 | return rc; | ||
318 | } | ||
319 | |||
320 | /* Get IRQ for the device */ | ||
321 | rc = of_irq_to_resource(ofdev->node, 0, &r_irq); | ||
322 | if (rc == NO_IRQ) { | ||
323 | dev_err(&ofdev->dev, "no IRQ found\n"); | ||
324 | return rc; | ||
325 | } | ||
326 | |||
327 | return xps2_setup(&ofdev->dev, &r_mem, &r_irq); | ||
328 | } | ||
329 | |||
330 | static int __devexit xps2_of_remove(struct of_device *of_dev) | ||
331 | { | ||
332 | struct device *dev = &of_dev->dev; | ||
333 | struct xps2data *drvdata; | ||
334 | |||
335 | if (!dev) | ||
336 | return -EINVAL; | ||
337 | |||
338 | drvdata = dev_get_drvdata(dev); | ||
339 | |||
340 | serio_unregister_port(&drvdata->serio); | ||
341 | iounmap(drvdata->base_address); | ||
342 | release_mem_region(drvdata->phys_addr, drvdata->remap_size); | ||
343 | kfree(drvdata); | ||
344 | |||
345 | dev_set_drvdata(dev, NULL); | ||
346 | |||
347 | return 0; /* success */ | ||
348 | } | ||
349 | |||
350 | /* Match table for of_platform binding */ | ||
351 | static struct of_device_id xps2_of_match[] __devinitdata = { | ||
352 | { .compatible = "xlnx,xps-ps2-1.00.a", }, | ||
353 | { /* end of list */ }, | ||
354 | }; | ||
355 | MODULE_DEVICE_TABLE(of, xps2_of_match); | ||
356 | |||
357 | static struct of_platform_driver xps2_of_driver = { | ||
358 | .name = DRIVER_NAME, | ||
359 | .match_table = xps2_of_match, | ||
360 | .probe = xps2_of_probe, | ||
361 | .remove = __devexit_p(xps2_of_remove), | ||
362 | }; | ||
363 | |||
364 | static int __init xps2_init(void) | ||
365 | { | ||
366 | return of_register_platform_driver(&xps2_of_driver); | ||
367 | } | ||
368 | |||
369 | static void __exit xps2_cleanup(void) | ||
370 | { | ||
371 | of_unregister_platform_driver(&xps2_of_driver); | ||
372 | } | ||
373 | |||
374 | module_init(xps2_init); | ||
375 | module_exit(xps2_cleanup); | ||
376 | |||
377 | MODULE_AUTHOR("Xilinx, Inc."); | ||
378 | MODULE_DESCRIPTION("Xilinx XPS PS/2 driver"); | ||
379 | MODULE_LICENSE("GPL"); | ||
380 | |||