diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/Kconfig | 13 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 34 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 79 | ||||
-rw-r--r-- | drivers/input/serio/libps2.c | 29 | ||||
-rw-r--r-- | drivers/input/serio/serio_raw.c | 1 | ||||
-rw-r--r-- | drivers/input/serio/serport.c | 1 |
6 files changed, 139 insertions, 18 deletions
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index c4b3fbd1a80f..aa533ceffe34 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -4,7 +4,7 @@ config SERIO tristate "Serial I/O support" if EMBEDDED || !X86 default y - ---help--- + help Say Yes here if you have any input device that uses serial I/O to communicate with the system. This includes the * standard AT keyboard and PS/2 mouse * @@ -22,7 +22,7 @@ config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN - ---help--- + help i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, you'll need to say Y here. @@ -35,7 +35,7 @@ config SERIO_I8042 config SERIO_SERPORT tristate "Serial port line discipline" default y - ---help--- + help Say Y here if you plan to use an input device (mouse, joystick, tablet, 6dof) that communicates over the RS232 serial (COM) port. @@ -49,7 +49,7 @@ config SERIO_SERPORT config SERIO_CT82C710 tristate "ct82c710 Aux port controller" depends on X86 - ---help--- + help Say Y here if you have a Texas Instruments TravelMate notebook equipped with the ct82c710 chip and want to use a mouse connected to the "QuickPort". @@ -66,7 +66,7 @@ config SERIO_Q40KBD config SERIO_PARKBD tristate "Parallel port keyboard adapter" depends on PARPORT - ---help--- + help Say Y here if you built a simple parallel port adapter to attach an additional AT keyboard, XT keyboard or PS/2 mouse. @@ -124,7 +124,7 @@ config HP_SDC tristate "HP System Device Controller i8042 Support" depends on (GSC || HP300) && SERIO default y - ---help--- + help This option enables support for the "System Device Controller", an i8042 carrying microcode to manage a few miscellaneous devices on some Hewlett Packard systems. @@ -168,6 +168,7 @@ config SERIO_MACEPS2 config SERIO_LIBPS2 tristate "PS/2 driver library" if EMBEDDED + depends on SERIO_I8042 || SERIO_I8042=n help Say Y here if you are using a driver for device connected to a PS/2 port, such as PS/2 mouse or standard AT keyboard. diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index a39bc4eb902b..2bcf1ace27c0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -327,6 +327,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, }, { + /* + * Reset and GET ID commands issued via KBD port are + * sometimes being delivered to AUX3. + */ + .ident = "Sony Vaio FZ-240E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"), + }, + }, + { .ident = "Amoi M636/A737", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), @@ -436,6 +447,27 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "N10"), }, }, + { + .ident = "Dell Vostro 1320", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), + }, + }, + { + .ident = "Dell Vostro 1520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), + }, + }, + { + .ident = "Dell Vostro 1720", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), + }, + }, { } }; @@ -661,7 +693,7 @@ static void i8042_pnp_exit(void) static int __init i8042_pnp_init(void) { char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; - int pnp_data_busted = false; + bool pnp_data_busted = false; int err; #ifdef CONFIG_X86 diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index eb3ff94af58c..1df02d25aca5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -87,8 +87,22 @@ static bool i8042_bypass_aux_irq_test; #include "i8042.h" +/* + * i8042_lock protects serialization between i8042_command and + * the interrupt handler. + */ static DEFINE_SPINLOCK(i8042_lock); +/* + * Writers to AUX and KBD ports as well as users issuing i8042_command + * directly should acquire i8042_mutex (by means of calling + * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that + * they do not disturb each other (unfortunately in many i8042 + * implementations write to one of the ports will immediately abort + * command that is being processed by another port). + */ +static DEFINE_MUTEX(i8042_mutex); + struct i8042_port { struct serio *serio; int irq; @@ -113,6 +127,18 @@ static struct platform_device *i8042_platform_device; static irqreturn_t i8042_interrupt(int irq, void *dev_id); +void i8042_lock_chip(void) +{ + mutex_lock(&i8042_mutex); +} +EXPORT_SYMBOL(i8042_lock_chip); + +void i8042_unlock_chip(void) +{ + mutex_unlock(&i8042_mutex); +} +EXPORT_SYMBOL(i8042_unlock_chip); + /* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * be ready for reading values from it / writing values to it. @@ -583,6 +609,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) str = i8042_read_status(); if (str & I8042_STR_OBF) { data = i8042_read_data(); + dbg("%02x <- i8042 (aux_test_irq, %s)", + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); if (i8042_irq_being_tested && data == 0xa5 && (str & I8042_STR_AUXDATA)) complete(&i8042_aux_irq_delivered); @@ -724,6 +752,7 @@ static int __init i8042_check_aux(void) * AUX IRQ was never delivered so we need to flush the controller to * get rid of the byte we put there; otherwise keyboard may not work. */ + dbg(" -- i8042 (aux irq test timeout)"); i8042_flush(); retval = -1; } @@ -807,17 +836,32 @@ static int i8042_controller_selftest(void) static int i8042_controller_init(void) { unsigned long flags; + int n = 0; + unsigned char ctr[2]; /* - * Save the CTR for restoral on unload / reboot. + * Save the CTR for restore on unload / reboot. */ - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { - printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); - return -EIO; - } + do { + if (n >= 10) { + printk(KERN_ERR + "i8042.c: Unable to get stable CTR read.\n"); + return -EIO; + } + + if (n != 0) + udelay(50); + + if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { + printk(KERN_ERR + "i8042.c: Can't read CTR while initializing i8042.\n"); + return -EIO; + } + + } while (n < 2 || ctr[0] != ctr[1]); - i8042_initial_ctr = i8042_ctr; + i8042_initial_ctr = i8042_ctr = ctr[0]; /* * Disable the keyboard interface and interrupt. @@ -866,6 +910,12 @@ static int i8042_controller_init(void) return -EIO; } +/* + * Flush whatever accumulated while we were disabling keyboard port. + */ + + i8042_flush(); + return 0; } @@ -885,7 +935,7 @@ static void i8042_controller_reset(void) i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); - if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); /* @@ -1161,6 +1211,21 @@ static void __devexit i8042_unregister_ports(void) } } +/* + * Checks whether port belongs to i8042 controller. + */ +bool i8042_check_port_owner(const struct serio *port) +{ + int i; + + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_ports[i].serio == port) + return true; + + return false; +} +EXPORT_SYMBOL(i8042_check_port_owner); + static void i8042_free_irqs(void) { if (i8042_aux_irq_registered) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3a95b508bf27..f3876acc3e83 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -13,10 +13,12 @@ #include <linux/delay.h> #include <linux/module.h> +#include <linux/sched.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/serio.h> +#include <linux/i8042.h> #include <linux/init.h> #include <linux/libps2.h> @@ -54,6 +56,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) } EXPORT_SYMBOL(ps2_sendbyte); +void ps2_begin_command(struct ps2dev *ps2dev) +{ + mutex_lock(&ps2dev->cmd_mutex); + + if (i8042_check_port_owner(ps2dev->serio)) + i8042_lock_chip(); +} +EXPORT_SYMBOL(ps2_begin_command); + +void ps2_end_command(struct ps2dev *ps2dev) +{ + if (i8042_check_port_owner(ps2dev->serio)) + i8042_unlock_chip(); + + mutex_unlock(&ps2dev->cmd_mutex); +} +EXPORT_SYMBOL(ps2_end_command); + /* * ps2_drain() waits for device to transmit requested number of bytes * and discards them. @@ -66,7 +86,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) maxbytes = sizeof(ps2dev->cmdbuf); } - mutex_lock(&ps2dev->cmd_mutex); + ps2_begin_command(ps2dev); serio_pause_rx(ps2dev->serio); ps2dev->flags = PS2_FLAG_CMD; @@ -76,7 +96,8 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), msecs_to_jiffies(timeout)); - mutex_unlock(&ps2dev->cmd_mutex); + + ps2_end_command(ps2dev); } EXPORT_SYMBOL(ps2_drain); @@ -237,9 +258,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) { int rc; - mutex_lock(&ps2dev->cmd_mutex); + ps2_begin_command(ps2dev); rc = __ps2_command(ps2dev, param, command); - mutex_unlock(&ps2dev->cmd_mutex); + ps2_end_command(ps2dev); return rc; } diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index b03009bb7468..27fdaaffbb40 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -9,6 +9,7 @@ * the Free Software Foundation. */ +#include <linux/sched.h> #include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/poll.h> diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index b9694b6445d0..6d345112bcb7 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -15,6 +15,7 @@ #include <asm/uaccess.h> #include <linux/kernel.h> +#include <linux/sched.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/init.h> |