aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/i8042.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r--drivers/input/serio/i8042.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index bc56e52b945f..1df02d25aca5 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -609,6 +609,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
609 str = i8042_read_status(); 609 str = i8042_read_status();
610 if (str & I8042_STR_OBF) { 610 if (str & I8042_STR_OBF) {
611 data = i8042_read_data(); 611 data = i8042_read_data();
612 dbg("%02x <- i8042 (aux_test_irq, %s)",
613 data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
612 if (i8042_irq_being_tested && 614 if (i8042_irq_being_tested &&
613 data == 0xa5 && (str & I8042_STR_AUXDATA)) 615 data == 0xa5 && (str & I8042_STR_AUXDATA))
614 complete(&i8042_aux_irq_delivered); 616 complete(&i8042_aux_irq_delivered);
@@ -750,6 +752,7 @@ static int __init i8042_check_aux(void)
750 * AUX IRQ was never delivered so we need to flush the controller to 752 * AUX IRQ was never delivered so we need to flush the controller to
751 * get rid of the byte we put there; otherwise keyboard may not work. 753 * get rid of the byte we put there; otherwise keyboard may not work.
752 */ 754 */
755 dbg(" -- i8042 (aux irq test timeout)");
753 i8042_flush(); 756 i8042_flush();
754 retval = -1; 757 retval = -1;
755 } 758 }
@@ -833,17 +836,32 @@ static int i8042_controller_selftest(void)
833static int i8042_controller_init(void) 836static int i8042_controller_init(void)
834{ 837{
835 unsigned long flags; 838 unsigned long flags;
839 int n = 0;
840 unsigned char ctr[2];
836 841
837/* 842/*
838 * Save the CTR for restoral on unload / reboot. 843 * Save the CTR for restore on unload / reboot.
839 */ 844 */
840 845
841 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { 846 do {
842 printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); 847 if (n >= 10) {
843 return -EIO; 848 printk(KERN_ERR
844 } 849 "i8042.c: Unable to get stable CTR read.\n");
850 return -EIO;
851 }
852
853 if (n != 0)
854 udelay(50);
855
856 if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
857 printk(KERN_ERR
858 "i8042.c: Can't read CTR while initializing i8042.\n");
859 return -EIO;
860 }
845 861
846 i8042_initial_ctr = i8042_ctr; 862 } while (n < 2 || ctr[0] != ctr[1]);
863
864 i8042_initial_ctr = i8042_ctr = ctr[0];
847 865
848/* 866/*
849 * Disable the keyboard interface and interrupt. 867 * Disable the keyboard interface and interrupt.
@@ -892,6 +910,12 @@ static int i8042_controller_init(void)
892 return -EIO; 910 return -EIO;
893 } 911 }
894 912
913/*
914 * Flush whatever accumulated while we were disabling keyboard port.
915 */
916
917 i8042_flush();
918
895 return 0; 919 return 0;
896} 920}
897 921
@@ -911,7 +935,7 @@ static void i8042_controller_reset(void)
911 i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; 935 i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
912 i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); 936 i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
913 937
914 if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) 938 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
915 printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); 939 printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n");
916 940
917/* 941/*