11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * i8042 keyboard and mouse controller driver for Linux 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 1999-2004 Vojtech Pavlik 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds /* 81da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 91da177e4SLinus Torvalds * under the terms of the GNU General Public License version 2 as published by 101da177e4SLinus Torvalds * the Free Software Foundation. 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 134eb3c30bSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 144eb3c30bSJoe Perches 157e044e05SDmitry Torokhov #include <linux/types.h> 161da177e4SLinus Torvalds #include <linux/delay.h> 171da177e4SLinus Torvalds #include <linux/module.h> 181da177e4SLinus Torvalds #include <linux/interrupt.h> 191da177e4SLinus Torvalds #include <linux/ioport.h> 201da177e4SLinus Torvalds #include <linux/init.h> 211da177e4SLinus Torvalds #include <linux/serio.h> 221da177e4SLinus Torvalds #include <linux/err.h> 231da177e4SLinus Torvalds #include <linux/rcupdate.h> 24d052d1beSRussell King #include <linux/platform_device.h> 25553a05b8SMárton Németh #include <linux/i8042.h> 265a0e3ad6STejun Heo #include <linux/slab.h> 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <asm/io.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); 311da177e4SLinus Torvalds MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); 321da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 331da177e4SLinus Torvalds 34386b3849SDmitry Torokhov static bool i8042_nokbd; 35945ef0d4SDmitry Torokhov module_param_named(nokbd, i8042_nokbd, bool, 0); 36945ef0d4SDmitry Torokhov MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); 37945ef0d4SDmitry Torokhov 38386b3849SDmitry Torokhov static bool i8042_noaux; 391da177e4SLinus Torvalds module_param_named(noaux, i8042_noaux, bool, 0); 401da177e4SLinus Torvalds MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); 411da177e4SLinus Torvalds 42*e55a3366SDmitry Torokhov static bool i8042_nomux; 431da177e4SLinus Torvalds module_param_named(nomux, i8042_nomux, bool, 0); 442c860a11SDominik Brodowski MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing controller is present."); 451da177e4SLinus Torvalds 46386b3849SDmitry Torokhov static bool i8042_unlock; 471da177e4SLinus Torvalds module_param_named(unlock, i8042_unlock, bool, 0); 481da177e4SLinus Torvalds MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); 491da177e4SLinus Torvalds 50386b3849SDmitry Torokhov static bool i8042_reset; 511da177e4SLinus Torvalds module_param_named(reset, i8042_reset, bool, 0); 521da177e4SLinus Torvalds MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); 531da177e4SLinus Torvalds 54386b3849SDmitry Torokhov static bool i8042_direct; 551da177e4SLinus Torvalds module_param_named(direct, i8042_direct, bool, 0); 561da177e4SLinus Torvalds MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); 571da177e4SLinus Torvalds 58386b3849SDmitry Torokhov static bool i8042_dumbkbd; 591da177e4SLinus Torvalds module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); 601da177e4SLinus Torvalds MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); 611da177e4SLinus Torvalds 62386b3849SDmitry Torokhov static bool i8042_noloop; 631da177e4SLinus Torvalds module_param_named(noloop, i8042_noloop, bool, 0); 641da177e4SLinus Torvalds MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); 651da177e4SLinus Torvalds 66f8313ef1SJiri Kosina static bool i8042_notimeout; 67f8313ef1SJiri Kosina module_param_named(notimeout, i8042_notimeout, bool, 0); 68f8313ef1SJiri Kosina MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); 69f8313ef1SJiri Kosina 708987fec0SCarlos Corbacho #ifdef CONFIG_X86 71386b3849SDmitry Torokhov static bool i8042_dritek; 728987fec0SCarlos Corbacho module_param_named(dritek, i8042_dritek, bool, 0); 738987fec0SCarlos Corbacho MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); 748987fec0SCarlos Corbacho #endif 758987fec0SCarlos Corbacho 761da177e4SLinus Torvalds #ifdef CONFIG_PNP 77386b3849SDmitry Torokhov static bool i8042_nopnp; 781da177e4SLinus Torvalds module_param_named(nopnp, i8042_nopnp, bool, 0); 791da177e4SLinus Torvalds MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); 801da177e4SLinus Torvalds #endif 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds #define DEBUG 831da177e4SLinus Torvalds #ifdef DEBUG 84386b3849SDmitry Torokhov static bool i8042_debug; 851da177e4SLinus Torvalds module_param_named(debug, i8042_debug, bool, 0600); 861da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); 871da177e4SLinus Torvalds #endif 881da177e4SLinus Torvalds 891c7827aeSDmitry Torokhov static bool i8042_bypass_aux_irq_test; 90a7c5868cSHans de Goede static char i8042_kbd_firmware_id[128]; 91a7c5868cSHans de Goede static char i8042_aux_firmware_id[128]; 921c7827aeSDmitry Torokhov 931da177e4SLinus Torvalds #include "i8042.h" 941da177e4SLinus Torvalds 95181d683dSDmitry Torokhov /* 96181d683dSDmitry Torokhov * i8042_lock protects serialization between i8042_command and 97181d683dSDmitry Torokhov * the interrupt handler. 98181d683dSDmitry Torokhov */ 991da177e4SLinus Torvalds static DEFINE_SPINLOCK(i8042_lock); 1001da177e4SLinus Torvalds 101181d683dSDmitry Torokhov /* 102181d683dSDmitry Torokhov * Writers to AUX and KBD ports as well as users issuing i8042_command 103181d683dSDmitry Torokhov * directly should acquire i8042_mutex (by means of calling 104181d683dSDmitry Torokhov * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that 105181d683dSDmitry Torokhov * they do not disturb each other (unfortunately in many i8042 106181d683dSDmitry Torokhov * implementations write to one of the ports will immediately abort 107181d683dSDmitry Torokhov * command that is being processed by another port). 108181d683dSDmitry Torokhov */ 109181d683dSDmitry Torokhov static DEFINE_MUTEX(i8042_mutex); 110181d683dSDmitry Torokhov 1111da177e4SLinus Torvalds struct i8042_port { 1121da177e4SLinus Torvalds struct serio *serio; 1131da177e4SLinus Torvalds int irq; 114386b3849SDmitry Torokhov bool exists; 1151da177e4SLinus Torvalds signed char mux; 1161da177e4SLinus Torvalds }; 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds #define I8042_KBD_PORT_NO 0 1191da177e4SLinus Torvalds #define I8042_AUX_PORT_NO 1 1201da177e4SLinus Torvalds #define I8042_MUX_PORT_NO 2 1211da177e4SLinus Torvalds #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) 122de9ce703SDmitry Torokhov 123de9ce703SDmitry Torokhov static struct i8042_port i8042_ports[I8042_NUM_PORTS]; 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds static unsigned char i8042_initial_ctr; 1261da177e4SLinus Torvalds static unsigned char i8042_ctr; 127386b3849SDmitry Torokhov static bool i8042_mux_present; 128386b3849SDmitry Torokhov static bool i8042_kbd_irq_registered; 129386b3849SDmitry Torokhov static bool i8042_aux_irq_registered; 130817e6ba3SDmitry Torokhov static unsigned char i8042_suppress_kbd_ack; 1311da177e4SLinus Torvalds static struct platform_device *i8042_platform_device; 1321da177e4SLinus Torvalds 1337d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id); 134967c9ef9SMatthew Garrett static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, 135967c9ef9SMatthew Garrett struct serio *serio); 1361da177e4SLinus Torvalds 137181d683dSDmitry Torokhov void i8042_lock_chip(void) 138181d683dSDmitry Torokhov { 139181d683dSDmitry Torokhov mutex_lock(&i8042_mutex); 140181d683dSDmitry Torokhov } 141181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_lock_chip); 142181d683dSDmitry Torokhov 143181d683dSDmitry Torokhov void i8042_unlock_chip(void) 144181d683dSDmitry Torokhov { 145181d683dSDmitry Torokhov mutex_unlock(&i8042_mutex); 146181d683dSDmitry Torokhov } 147181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_unlock_chip); 148181d683dSDmitry Torokhov 149967c9ef9SMatthew Garrett int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 150967c9ef9SMatthew Garrett struct serio *serio)) 151967c9ef9SMatthew Garrett { 152967c9ef9SMatthew Garrett unsigned long flags; 153967c9ef9SMatthew Garrett int ret = 0; 154967c9ef9SMatthew Garrett 155967c9ef9SMatthew Garrett spin_lock_irqsave(&i8042_lock, flags); 156967c9ef9SMatthew Garrett 157967c9ef9SMatthew Garrett if (i8042_platform_filter) { 158967c9ef9SMatthew Garrett ret = -EBUSY; 159967c9ef9SMatthew Garrett goto out; 160967c9ef9SMatthew Garrett } 161967c9ef9SMatthew Garrett 162967c9ef9SMatthew Garrett i8042_platform_filter = filter; 163967c9ef9SMatthew Garrett 164967c9ef9SMatthew Garrett out: 165967c9ef9SMatthew Garrett spin_unlock_irqrestore(&i8042_lock, flags); 166967c9ef9SMatthew Garrett return ret; 167967c9ef9SMatthew Garrett } 168967c9ef9SMatthew Garrett EXPORT_SYMBOL(i8042_install_filter); 169967c9ef9SMatthew Garrett 170967c9ef9SMatthew Garrett int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 171967c9ef9SMatthew Garrett struct serio *port)) 172967c9ef9SMatthew Garrett { 173967c9ef9SMatthew Garrett unsigned long flags; 174967c9ef9SMatthew Garrett int ret = 0; 175967c9ef9SMatthew Garrett 176967c9ef9SMatthew Garrett spin_lock_irqsave(&i8042_lock, flags); 177967c9ef9SMatthew Garrett 178967c9ef9SMatthew Garrett if (i8042_platform_filter != filter) { 179967c9ef9SMatthew Garrett ret = -EINVAL; 180967c9ef9SMatthew Garrett goto out; 181967c9ef9SMatthew Garrett } 182967c9ef9SMatthew Garrett 183967c9ef9SMatthew Garrett i8042_platform_filter = NULL; 184967c9ef9SMatthew Garrett 185967c9ef9SMatthew Garrett out: 186967c9ef9SMatthew Garrett spin_unlock_irqrestore(&i8042_lock, flags); 187967c9ef9SMatthew Garrett return ret; 188967c9ef9SMatthew Garrett } 189967c9ef9SMatthew Garrett EXPORT_SYMBOL(i8042_remove_filter); 190967c9ef9SMatthew Garrett 1911da177e4SLinus Torvalds /* 1921da177e4SLinus Torvalds * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to 1931da177e4SLinus Torvalds * be ready for reading values from it / writing values to it. 1941da177e4SLinus Torvalds * Called always with i8042_lock held. 1951da177e4SLinus Torvalds */ 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds static int i8042_wait_read(void) 1981da177e4SLinus Torvalds { 1991da177e4SLinus Torvalds int i = 0; 200de9ce703SDmitry Torokhov 2011da177e4SLinus Torvalds while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { 2021da177e4SLinus Torvalds udelay(50); 2031da177e4SLinus Torvalds i++; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 2061da177e4SLinus Torvalds } 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds static int i8042_wait_write(void) 2091da177e4SLinus Torvalds { 2101da177e4SLinus Torvalds int i = 0; 211de9ce703SDmitry Torokhov 2121da177e4SLinus Torvalds while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { 2131da177e4SLinus Torvalds udelay(50); 2141da177e4SLinus Torvalds i++; 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 2171da177e4SLinus Torvalds } 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds /* 2201da177e4SLinus Torvalds * i8042_flush() flushes all data that may be in the keyboard and mouse buffers 2211da177e4SLinus Torvalds * of the i8042 down the toilet. 2221da177e4SLinus Torvalds */ 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds static int i8042_flush(void) 2251da177e4SLinus Torvalds { 2261da177e4SLinus Torvalds unsigned long flags; 2271da177e4SLinus Torvalds unsigned char data, str; 2282f0d2604SAndrey Moiseev int count = 0; 2292f0d2604SAndrey Moiseev int retval = 0; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 2321da177e4SLinus Torvalds 2332f0d2604SAndrey Moiseev while ((str = i8042_read_status()) & I8042_STR_OBF) { 2342f0d2604SAndrey Moiseev if (count++ < I8042_BUFFER_SIZE) { 2351da177e4SLinus Torvalds udelay(50); 2361da177e4SLinus Torvalds data = i8042_read_data(); 2374eb3c30bSJoe Perches dbg("%02x <- i8042 (flush, %s)\n", 2384eb3c30bSJoe Perches data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 2392f0d2604SAndrey Moiseev } else { 2402f0d2604SAndrey Moiseev retval = -EIO; 2412f0d2604SAndrey Moiseev break; 2422f0d2604SAndrey Moiseev } 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 2461da177e4SLinus Torvalds 2472f0d2604SAndrey Moiseev return retval; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /* 2511da177e4SLinus Torvalds * i8042_command() executes a command on the i8042. It also sends the input 2521da177e4SLinus Torvalds * parameter(s) of the commands to it, and receives the output value(s). The 2531da177e4SLinus Torvalds * parameters are to be stored in the param array, and the output is placed 2541da177e4SLinus Torvalds * into the same array. The number of the parameters and output values is 2551da177e4SLinus Torvalds * encoded in bits 8-11 of the command number. 2561da177e4SLinus Torvalds */ 2571da177e4SLinus Torvalds 258de9ce703SDmitry Torokhov static int __i8042_command(unsigned char *param, int command) 2591da177e4SLinus Torvalds { 260de9ce703SDmitry Torokhov int i, error; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds if (i8042_noloop && command == I8042_CMD_AUX_LOOP) 2631da177e4SLinus Torvalds return -1; 2641da177e4SLinus Torvalds 265de9ce703SDmitry Torokhov error = i8042_wait_write(); 266de9ce703SDmitry Torokhov if (error) 267de9ce703SDmitry Torokhov return error; 268463a4f76SDmitry Torokhov 2694eb3c30bSJoe Perches dbg("%02x -> i8042 (command)\n", command & 0xff); 2701da177e4SLinus Torvalds i8042_write_command(command & 0xff); 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds for (i = 0; i < ((command >> 12) & 0xf); i++) { 273de9ce703SDmitry Torokhov error = i8042_wait_write(); 274de9ce703SDmitry Torokhov if (error) 275de9ce703SDmitry Torokhov return error; 2764eb3c30bSJoe Perches dbg("%02x -> i8042 (parameter)\n", param[i]); 2771da177e4SLinus Torvalds i8042_write_data(param[i]); 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds for (i = 0; i < ((command >> 8) & 0xf); i++) { 281de9ce703SDmitry Torokhov error = i8042_wait_read(); 282de9ce703SDmitry Torokhov if (error) { 2834eb3c30bSJoe Perches dbg(" -- i8042 (timeout)\n"); 284de9ce703SDmitry Torokhov return error; 285de9ce703SDmitry Torokhov } 286463a4f76SDmitry Torokhov 287463a4f76SDmitry Torokhov if (command == I8042_CMD_AUX_LOOP && 288463a4f76SDmitry Torokhov !(i8042_read_status() & I8042_STR_AUXDATA)) { 2894eb3c30bSJoe Perches dbg(" -- i8042 (auxerr)\n"); 290de9ce703SDmitry Torokhov return -1; 291463a4f76SDmitry Torokhov } 292463a4f76SDmitry Torokhov 2931da177e4SLinus Torvalds param[i] = i8042_read_data(); 2944eb3c30bSJoe Perches dbg("%02x <- i8042 (return)\n", param[i]); 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 297de9ce703SDmitry Torokhov return 0; 298de9ce703SDmitry Torokhov } 2991da177e4SLinus Torvalds 300553a05b8SMárton Németh int i8042_command(unsigned char *param, int command) 301de9ce703SDmitry Torokhov { 302de9ce703SDmitry Torokhov unsigned long flags; 303de9ce703SDmitry Torokhov int retval; 304de9ce703SDmitry Torokhov 305de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 306de9ce703SDmitry Torokhov retval = __i8042_command(param, command); 307463a4f76SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 308de9ce703SDmitry Torokhov 3091da177e4SLinus Torvalds return retval; 3101da177e4SLinus Torvalds } 311553a05b8SMárton Németh EXPORT_SYMBOL(i8042_command); 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds /* 3141da177e4SLinus Torvalds * i8042_kbd_write() sends a byte out through the keyboard interface. 3151da177e4SLinus Torvalds */ 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds static int i8042_kbd_write(struct serio *port, unsigned char c) 3181da177e4SLinus Torvalds { 3191da177e4SLinus Torvalds unsigned long flags; 3201da177e4SLinus Torvalds int retval = 0; 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds if (!(retval = i8042_wait_write())) { 3254eb3c30bSJoe Perches dbg("%02x -> i8042 (kbd-data)\n", c); 3261da177e4SLinus Torvalds i8042_write_data(c); 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds return retval; 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds /* 3351da177e4SLinus Torvalds * i8042_aux_write() sends a byte out through the aux interface. 3361da177e4SLinus Torvalds */ 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds static int i8042_aux_write(struct serio *serio, unsigned char c) 3391da177e4SLinus Torvalds { 3401da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 3411da177e4SLinus Torvalds 342f4e3c711SDmitry Torokhov return i8042_command(&c, port->mux == -1 ? 343f4e3c711SDmitry Torokhov I8042_CMD_AUX_SEND : 344f4e3c711SDmitry Torokhov I8042_CMD_MUX_SEND + port->mux); 3451da177e4SLinus Torvalds } 3461da177e4SLinus Torvalds 3475ddbc77cSDmitry Torokhov 3485ddbc77cSDmitry Torokhov /* 3495ddbc77cSDmitry Torokhov * i8042_aux_close attempts to clear AUX or KBD port state by disabling 3505ddbc77cSDmitry Torokhov * and then re-enabling it. 3515ddbc77cSDmitry Torokhov */ 3525ddbc77cSDmitry Torokhov 3535ddbc77cSDmitry Torokhov static void i8042_port_close(struct serio *serio) 3545ddbc77cSDmitry Torokhov { 3555ddbc77cSDmitry Torokhov int irq_bit; 3565ddbc77cSDmitry Torokhov int disable_bit; 3575ddbc77cSDmitry Torokhov const char *port_name; 3585ddbc77cSDmitry Torokhov 3595ddbc77cSDmitry Torokhov if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { 3605ddbc77cSDmitry Torokhov irq_bit = I8042_CTR_AUXINT; 3615ddbc77cSDmitry Torokhov disable_bit = I8042_CTR_AUXDIS; 3625ddbc77cSDmitry Torokhov port_name = "AUX"; 3635ddbc77cSDmitry Torokhov } else { 3645ddbc77cSDmitry Torokhov irq_bit = I8042_CTR_KBDINT; 3655ddbc77cSDmitry Torokhov disable_bit = I8042_CTR_KBDDIS; 3665ddbc77cSDmitry Torokhov port_name = "KBD"; 3675ddbc77cSDmitry Torokhov } 3685ddbc77cSDmitry Torokhov 3695ddbc77cSDmitry Torokhov i8042_ctr &= ~irq_bit; 3705ddbc77cSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 3714eb3c30bSJoe Perches pr_warn("Can't write CTR while closing %s port\n", port_name); 3725ddbc77cSDmitry Torokhov 3735ddbc77cSDmitry Torokhov udelay(50); 3745ddbc77cSDmitry Torokhov 3755ddbc77cSDmitry Torokhov i8042_ctr &= ~disable_bit; 3765ddbc77cSDmitry Torokhov i8042_ctr |= irq_bit; 3775ddbc77cSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 3784eb3c30bSJoe Perches pr_err("Can't reactivate %s port\n", port_name); 3795ddbc77cSDmitry Torokhov 3805ddbc77cSDmitry Torokhov /* 3815ddbc77cSDmitry Torokhov * See if there is any data appeared while we were messing with 3825ddbc77cSDmitry Torokhov * port state. 3835ddbc77cSDmitry Torokhov */ 3845ddbc77cSDmitry Torokhov i8042_interrupt(0, NULL); 3855ddbc77cSDmitry Torokhov } 3865ddbc77cSDmitry Torokhov 3871da177e4SLinus Torvalds /* 3881da177e4SLinus Torvalds * i8042_start() is called by serio core when port is about to finish 3891da177e4SLinus Torvalds * registering. It will mark port as existing so i8042_interrupt can 3901da177e4SLinus Torvalds * start sending data through it. 3911da177e4SLinus Torvalds */ 3921da177e4SLinus Torvalds static int i8042_start(struct serio *serio) 3931da177e4SLinus Torvalds { 3941da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 3951da177e4SLinus Torvalds 396386b3849SDmitry Torokhov port->exists = true; 3971da177e4SLinus Torvalds mb(); 3981da177e4SLinus Torvalds return 0; 3991da177e4SLinus Torvalds } 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds /* 4021da177e4SLinus Torvalds * i8042_stop() marks serio port as non-existing so i8042_interrupt 4031da177e4SLinus Torvalds * will not try to send data to the port that is about to go away. 4041da177e4SLinus Torvalds * The function is called by serio core as part of unregister procedure. 4051da177e4SLinus Torvalds */ 4061da177e4SLinus Torvalds static void i8042_stop(struct serio *serio) 4071da177e4SLinus Torvalds { 4081da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 4091da177e4SLinus Torvalds 410386b3849SDmitry Torokhov port->exists = false; 411a8399c51SDmitry Torokhov 412a8399c51SDmitry Torokhov /* 413a8399c51SDmitry Torokhov * We synchronize with both AUX and KBD IRQs because there is 414a8399c51SDmitry Torokhov * a (very unlikely) chance that AUX IRQ is raised for KBD port 415a8399c51SDmitry Torokhov * and vice versa. 416a8399c51SDmitry Torokhov */ 417a8399c51SDmitry Torokhov synchronize_irq(I8042_AUX_IRQ); 418a8399c51SDmitry Torokhov synchronize_irq(I8042_KBD_IRQ); 4191da177e4SLinus Torvalds port->serio = NULL; 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds /* 4234e8d340dSDmitry Torokhov * i8042_filter() filters out unwanted bytes from the input data stream. 4244e8d340dSDmitry Torokhov * It is called from i8042_interrupt and thus is running with interrupts 4254e8d340dSDmitry Torokhov * off and i8042_lock held. 4264e8d340dSDmitry Torokhov */ 427967c9ef9SMatthew Garrett static bool i8042_filter(unsigned char data, unsigned char str, 428967c9ef9SMatthew Garrett struct serio *serio) 4294e8d340dSDmitry Torokhov { 4304e8d340dSDmitry Torokhov if (unlikely(i8042_suppress_kbd_ack)) { 4314e8d340dSDmitry Torokhov if ((~str & I8042_STR_AUXDATA) && 4324e8d340dSDmitry Torokhov (data == 0xfa || data == 0xfe)) { 4334e8d340dSDmitry Torokhov i8042_suppress_kbd_ack--; 4344e8d340dSDmitry Torokhov dbg("Extra keyboard ACK - filtered out\n"); 4354e8d340dSDmitry Torokhov return true; 4364e8d340dSDmitry Torokhov } 4374e8d340dSDmitry Torokhov } 4384e8d340dSDmitry Torokhov 439967c9ef9SMatthew Garrett if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { 4400747e3bcSStefan Weil dbg("Filtered out by platform filter\n"); 441967c9ef9SMatthew Garrett return true; 442967c9ef9SMatthew Garrett } 443967c9ef9SMatthew Garrett 4444e8d340dSDmitry Torokhov return false; 4454e8d340dSDmitry Torokhov } 4464e8d340dSDmitry Torokhov 4474e8d340dSDmitry Torokhov /* 4481da177e4SLinus Torvalds * i8042_interrupt() is the most important function in this driver - 4491da177e4SLinus Torvalds * it handles the interrupts from the i8042, and sends incoming bytes 4501da177e4SLinus Torvalds * to the upper layers. 4511da177e4SLinus Torvalds */ 4521da177e4SLinus Torvalds 4537d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id) 4541da177e4SLinus Torvalds { 4551da177e4SLinus Torvalds struct i8042_port *port; 456967c9ef9SMatthew Garrett struct serio *serio; 4571da177e4SLinus Torvalds unsigned long flags; 4581da177e4SLinus Torvalds unsigned char str, data; 4591da177e4SLinus Torvalds unsigned int dfl; 4601da177e4SLinus Torvalds unsigned int port_no; 4614e8d340dSDmitry Torokhov bool filtered; 462817e6ba3SDmitry Torokhov int ret = 1; 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 4654e8d340dSDmitry Torokhov 4661da177e4SLinus Torvalds str = i8042_read_status(); 4671da177e4SLinus Torvalds if (unlikely(~str & I8042_STR_OBF)) { 4681da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 4694eb3c30bSJoe Perches if (irq) 4704eb3c30bSJoe Perches dbg("Interrupt %d, without any data\n", irq); 4711da177e4SLinus Torvalds ret = 0; 4721da177e4SLinus Torvalds goto out; 4731da177e4SLinus Torvalds } 4744e8d340dSDmitry Torokhov 4751da177e4SLinus Torvalds data = i8042_read_data(); 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 4781da177e4SLinus Torvalds static unsigned long last_transmit; 4791da177e4SLinus Torvalds static unsigned char last_str; 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds dfl = 0; 4821da177e4SLinus Torvalds if (str & I8042_STR_MUXERR) { 4834eb3c30bSJoe Perches dbg("MUX error, status is %02x, data is %02x\n", 4844eb3c30bSJoe Perches str, data); 4851da177e4SLinus Torvalds /* 4861da177e4SLinus Torvalds * When MUXERR condition is signalled the data register can only contain 4871da177e4SLinus Torvalds * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately 488a216a4b6SDmitry Torokhov * it is not always the case. Some KBCs also report 0xfc when there is 489a216a4b6SDmitry Torokhov * nothing connected to the port while others sometimes get confused which 490a216a4b6SDmitry Torokhov * port the data came from and signal error leaving the data intact. They 491a216a4b6SDmitry Torokhov * _do not_ revert to legacy mode (actually I've never seen KBC reverting 492a216a4b6SDmitry Torokhov * to legacy mode yet, when we see one we'll add proper handling). 493a216a4b6SDmitry Torokhov * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the 494a216a4b6SDmitry Torokhov * rest assume that the data came from the same serio last byte 4951da177e4SLinus Torvalds * was transmitted (if transmission happened not too long ago). 4961da177e4SLinus Torvalds */ 497a216a4b6SDmitry Torokhov 498a216a4b6SDmitry Torokhov switch (data) { 499a216a4b6SDmitry Torokhov default: 5001da177e4SLinus Torvalds if (time_before(jiffies, last_transmit + HZ/10)) { 5011da177e4SLinus Torvalds str = last_str; 5021da177e4SLinus Torvalds break; 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds /* fall through - report timeout */ 505a216a4b6SDmitry Torokhov case 0xfc: 5061da177e4SLinus Torvalds case 0xfd: 5071da177e4SLinus Torvalds case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; 5081da177e4SLinus Torvalds case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); 5131da177e4SLinus Torvalds last_str = str; 5141da177e4SLinus Torvalds last_transmit = jiffies; 5151da177e4SLinus Torvalds } else { 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | 518f8313ef1SJiri Kosina ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds port_no = (str & I8042_STR_AUXDATA) ? 5211da177e4SLinus Torvalds I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; 5221da177e4SLinus Torvalds } 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds port = &i8042_ports[port_no]; 525967c9ef9SMatthew Garrett serio = port->exists ? port->serio : NULL; 5261da177e4SLinus Torvalds 5274eb3c30bSJoe Perches dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n", 528de9ce703SDmitry Torokhov data, port_no, irq, 5291da177e4SLinus Torvalds dfl & SERIO_PARITY ? ", bad parity" : "", 5301da177e4SLinus Torvalds dfl & SERIO_TIMEOUT ? ", timeout" : ""); 5311da177e4SLinus Torvalds 532967c9ef9SMatthew Garrett filtered = i8042_filter(data, str, serio); 533817e6ba3SDmitry Torokhov 5344e8d340dSDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 5354e8d340dSDmitry Torokhov 5364e8d340dSDmitry Torokhov if (likely(port->exists && !filtered)) 537967c9ef9SMatthew Garrett serio_interrupt(serio, data, dfl); 5381da177e4SLinus Torvalds 5391da177e4SLinus Torvalds out: 5401da177e4SLinus Torvalds return IRQ_RETVAL(ret); 5411da177e4SLinus Torvalds } 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds /* 5445ddbc77cSDmitry Torokhov * i8042_enable_kbd_port enables keyboard port on chip 545de9ce703SDmitry Torokhov */ 546de9ce703SDmitry Torokhov 547de9ce703SDmitry Torokhov static int i8042_enable_kbd_port(void) 548de9ce703SDmitry Torokhov { 549de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_KBDDIS; 550de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_KBDINT; 551de9ce703SDmitry Torokhov 552de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 553018db6bbSMarkus Armbruster i8042_ctr &= ~I8042_CTR_KBDINT; 554018db6bbSMarkus Armbruster i8042_ctr |= I8042_CTR_KBDDIS; 5554eb3c30bSJoe Perches pr_err("Failed to enable KBD port\n"); 556de9ce703SDmitry Torokhov return -EIO; 557de9ce703SDmitry Torokhov } 558de9ce703SDmitry Torokhov 559de9ce703SDmitry Torokhov return 0; 560de9ce703SDmitry Torokhov } 561de9ce703SDmitry Torokhov 562de9ce703SDmitry Torokhov /* 563de9ce703SDmitry Torokhov * i8042_enable_aux_port enables AUX (mouse) port on chip 564de9ce703SDmitry Torokhov */ 565de9ce703SDmitry Torokhov 566de9ce703SDmitry Torokhov static int i8042_enable_aux_port(void) 567de9ce703SDmitry Torokhov { 568de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXDIS; 569de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXINT; 570de9ce703SDmitry Torokhov 571de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 572018db6bbSMarkus Armbruster i8042_ctr &= ~I8042_CTR_AUXINT; 573018db6bbSMarkus Armbruster i8042_ctr |= I8042_CTR_AUXDIS; 5744eb3c30bSJoe Perches pr_err("Failed to enable AUX port\n"); 575de9ce703SDmitry Torokhov return -EIO; 576de9ce703SDmitry Torokhov } 577de9ce703SDmitry Torokhov 578de9ce703SDmitry Torokhov return 0; 579de9ce703SDmitry Torokhov } 580de9ce703SDmitry Torokhov 581de9ce703SDmitry Torokhov /* 582de9ce703SDmitry Torokhov * i8042_enable_mux_ports enables 4 individual AUX ports after 583de9ce703SDmitry Torokhov * the controller has been switched into Multiplexed mode 584de9ce703SDmitry Torokhov */ 585de9ce703SDmitry Torokhov 586de9ce703SDmitry Torokhov static int i8042_enable_mux_ports(void) 587de9ce703SDmitry Torokhov { 588de9ce703SDmitry Torokhov unsigned char param; 589de9ce703SDmitry Torokhov int i; 590de9ce703SDmitry Torokhov 591de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 592de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_MUX_PFX + i); 593de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_AUX_ENABLE); 594de9ce703SDmitry Torokhov } 595de9ce703SDmitry Torokhov 596de9ce703SDmitry Torokhov return i8042_enable_aux_port(); 597de9ce703SDmitry Torokhov } 598de9ce703SDmitry Torokhov 599de9ce703SDmitry Torokhov /* 600386b3849SDmitry Torokhov * i8042_set_mux_mode checks whether the controller has an 601386b3849SDmitry Torokhov * active multiplexor and puts the chip into Multiplexed (true) 602386b3849SDmitry Torokhov * or Legacy (false) mode. 6031da177e4SLinus Torvalds */ 6041da177e4SLinus Torvalds 605386b3849SDmitry Torokhov static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) 6061da177e4SLinus Torvalds { 6071da177e4SLinus Torvalds 608386b3849SDmitry Torokhov unsigned char param, val; 6091da177e4SLinus Torvalds /* 6101da177e4SLinus Torvalds * Get rid of bytes in the queue. 6111da177e4SLinus Torvalds */ 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds i8042_flush(); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds /* 6161da177e4SLinus Torvalds * Internal loopback test - send three bytes, they should come back from the 617de9ce703SDmitry Torokhov * mouse interface, the last should be version. 6181da177e4SLinus Torvalds */ 6191da177e4SLinus Torvalds 620386b3849SDmitry Torokhov param = val = 0xf0; 621386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) 6221da177e4SLinus Torvalds return -1; 623386b3849SDmitry Torokhov param = val = multiplex ? 0x56 : 0xf6; 624386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) 6251da177e4SLinus Torvalds return -1; 626386b3849SDmitry Torokhov param = val = multiplex ? 0xa4 : 0xa5; 627386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) 628386b3849SDmitry Torokhov return -1; 629386b3849SDmitry Torokhov 630386b3849SDmitry Torokhov /* 631386b3849SDmitry Torokhov * Workaround for interference with USB Legacy emulation 632386b3849SDmitry Torokhov * that causes a v10.12 MUX to be found. 633386b3849SDmitry Torokhov */ 634386b3849SDmitry Torokhov if (param == 0xac) 6351da177e4SLinus Torvalds return -1; 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds if (mux_version) 638463a4f76SDmitry Torokhov *mux_version = param; 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds return 0; 6411da177e4SLinus Torvalds } 6421da177e4SLinus Torvalds 6431da177e4SLinus Torvalds /* 6441da177e4SLinus Torvalds * i8042_check_mux() checks whether the controller supports the PS/2 Active 6451da177e4SLinus Torvalds * Multiplexing specification by Synaptics, Phoenix, Insyde and 6461da177e4SLinus Torvalds * LCS/Telegraphics. 6471da177e4SLinus Torvalds */ 6481da177e4SLinus Torvalds 649f8113416SDmitry Torokhov static int __init i8042_check_mux(void) 6501da177e4SLinus Torvalds { 6511da177e4SLinus Torvalds unsigned char mux_version; 6521da177e4SLinus Torvalds 653386b3849SDmitry Torokhov if (i8042_set_mux_mode(true, &mux_version)) 6541da177e4SLinus Torvalds return -1; 6551da177e4SLinus Torvalds 6564eb3c30bSJoe Perches pr_info("Detected active multiplexing controller, rev %d.%d\n", 6571da177e4SLinus Torvalds (mux_version >> 4) & 0xf, mux_version & 0xf); 6581da177e4SLinus Torvalds 659de9ce703SDmitry Torokhov /* 660de9ce703SDmitry Torokhov * Disable all muxed ports by disabling AUX. 661de9ce703SDmitry Torokhov */ 662de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS; 663de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXINT; 664de9ce703SDmitry Torokhov 665de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 6664eb3c30bSJoe Perches pr_err("Failed to disable AUX port, can't use MUX\n"); 667de9ce703SDmitry Torokhov return -EIO; 668de9ce703SDmitry Torokhov } 6691da177e4SLinus Torvalds 670386b3849SDmitry Torokhov i8042_mux_present = true; 671de9ce703SDmitry Torokhov 6721da177e4SLinus Torvalds return 0; 6731da177e4SLinus Torvalds } 6741da177e4SLinus Torvalds 675de9ce703SDmitry Torokhov /* 676de9ce703SDmitry Torokhov * The following is used to test AUX IRQ delivery. 677de9ce703SDmitry Torokhov */ 678f8113416SDmitry Torokhov static struct completion i8042_aux_irq_delivered __initdata; 679f8113416SDmitry Torokhov static bool i8042_irq_being_tested __initdata; 680de9ce703SDmitry Torokhov 681f8113416SDmitry Torokhov static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) 682de9ce703SDmitry Torokhov { 683de9ce703SDmitry Torokhov unsigned long flags; 684de9ce703SDmitry Torokhov unsigned char str, data; 685e3758b2aSFernando Luis Vázquez Cao int ret = 0; 686de9ce703SDmitry Torokhov 687de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 688de9ce703SDmitry Torokhov str = i8042_read_status(); 689de9ce703SDmitry Torokhov if (str & I8042_STR_OBF) { 690de9ce703SDmitry Torokhov data = i8042_read_data(); 6914eb3c30bSJoe Perches dbg("%02x <- i8042 (aux_test_irq, %s)\n", 692d3d2dfe2SDmitry Torokhov data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 693de9ce703SDmitry Torokhov if (i8042_irq_being_tested && 694de9ce703SDmitry Torokhov data == 0xa5 && (str & I8042_STR_AUXDATA)) 695de9ce703SDmitry Torokhov complete(&i8042_aux_irq_delivered); 696e3758b2aSFernando Luis Vázquez Cao ret = 1; 697de9ce703SDmitry Torokhov } 698de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 699de9ce703SDmitry Torokhov 700e3758b2aSFernando Luis Vázquez Cao return IRQ_RETVAL(ret); 701de9ce703SDmitry Torokhov } 702de9ce703SDmitry Torokhov 703d2ada559SRoland Scheidegger /* 704d2ada559SRoland Scheidegger * i8042_toggle_aux - enables or disables AUX port on i8042 via command and 705d2ada559SRoland Scheidegger * verifies success by readinng CTR. Used when testing for presence of AUX 706d2ada559SRoland Scheidegger * port. 707d2ada559SRoland Scheidegger */ 708f8113416SDmitry Torokhov static int __init i8042_toggle_aux(bool on) 709d2ada559SRoland Scheidegger { 710d2ada559SRoland Scheidegger unsigned char param; 711d2ada559SRoland Scheidegger int i; 712d2ada559SRoland Scheidegger 713d2ada559SRoland Scheidegger if (i8042_command(¶m, 714d2ada559SRoland Scheidegger on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE)) 715d2ada559SRoland Scheidegger return -1; 716d2ada559SRoland Scheidegger 717d2ada559SRoland Scheidegger /* some chips need some time to set the I8042_CTR_AUXDIS bit */ 718d2ada559SRoland Scheidegger for (i = 0; i < 100; i++) { 719d2ada559SRoland Scheidegger udelay(50); 720d2ada559SRoland Scheidegger 721d2ada559SRoland Scheidegger if (i8042_command(¶m, I8042_CMD_CTL_RCTR)) 722d2ada559SRoland Scheidegger return -1; 723d2ada559SRoland Scheidegger 724d2ada559SRoland Scheidegger if (!(param & I8042_CTR_AUXDIS) == on) 725d2ada559SRoland Scheidegger return 0; 726d2ada559SRoland Scheidegger } 727d2ada559SRoland Scheidegger 728d2ada559SRoland Scheidegger return -1; 729d2ada559SRoland Scheidegger } 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds /* 7321da177e4SLinus Torvalds * i8042_check_aux() applies as much paranoia as it can at detecting 7331da177e4SLinus Torvalds * the presence of an AUX interface. 7341da177e4SLinus Torvalds */ 7351da177e4SLinus Torvalds 736f8113416SDmitry Torokhov static int __init i8042_check_aux(void) 7371da177e4SLinus Torvalds { 738de9ce703SDmitry Torokhov int retval = -1; 739386b3849SDmitry Torokhov bool irq_registered = false; 740386b3849SDmitry Torokhov bool aux_loop_broken = false; 741de9ce703SDmitry Torokhov unsigned long flags; 7421da177e4SLinus Torvalds unsigned char param; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds /* 7451da177e4SLinus Torvalds * Get rid of bytes in the queue. 7461da177e4SLinus Torvalds */ 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds i8042_flush(); 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds /* 7511da177e4SLinus Torvalds * Internal loopback test - filters out AT-type i8042's. Unfortunately 7521da177e4SLinus Torvalds * SiS screwed up and their 5597 doesn't support the LOOP command even 7531da177e4SLinus Torvalds * though it has an AUX port. 7541da177e4SLinus Torvalds */ 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds param = 0x5a; 7573ca5de6dSDmitry Torokhov retval = i8042_command(¶m, I8042_CMD_AUX_LOOP); 7583ca5de6dSDmitry Torokhov if (retval || param != 0x5a) { 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds /* 7611da177e4SLinus Torvalds * External connection test - filters out AT-soldered PS/2 i8042's 7621da177e4SLinus Torvalds * 0x00 - no error, 0x01-0x03 - clock/data stuck, 0xff - general error 7631da177e4SLinus Torvalds * 0xfa - no error on some notebooks which ignore the spec 7641da177e4SLinus Torvalds * Because it's common for chipsets to return error on perfectly functioning 7651da177e4SLinus Torvalds * AUX ports, we test for this only when the LOOP command failed. 7661da177e4SLinus Torvalds */ 7671da177e4SLinus Torvalds 768de9ce703SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_TEST) || 769de9ce703SDmitry Torokhov (param && param != 0xfa && param != 0xff)) 7701da177e4SLinus Torvalds return -1; 7711e4865f8SDmitry Torokhov 7723ca5de6dSDmitry Torokhov /* 7733ca5de6dSDmitry Torokhov * If AUX_LOOP completed without error but returned unexpected data 7743ca5de6dSDmitry Torokhov * mark it as broken 7753ca5de6dSDmitry Torokhov */ 7763ca5de6dSDmitry Torokhov if (!retval) 777386b3849SDmitry Torokhov aux_loop_broken = true; 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds /* 7811da177e4SLinus Torvalds * Bit assignment test - filters out PS/2 i8042's in AT mode 7821da177e4SLinus Torvalds */ 7831da177e4SLinus Torvalds 784386b3849SDmitry Torokhov if (i8042_toggle_aux(false)) { 7854eb3c30bSJoe Perches pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); 7864eb3c30bSJoe Perches pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n"); 7871da177e4SLinus Torvalds } 7881da177e4SLinus Torvalds 789386b3849SDmitry Torokhov if (i8042_toggle_aux(true)) 7901da177e4SLinus Torvalds return -1; 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds /* 793de9ce703SDmitry Torokhov * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and 794de9ce703SDmitry Torokhov * used it for a PCI card or somethig else. 795de9ce703SDmitry Torokhov */ 796de9ce703SDmitry Torokhov 7971c7827aeSDmitry Torokhov if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { 798de9ce703SDmitry Torokhov /* 799de9ce703SDmitry Torokhov * Without LOOP command we can't test AUX IRQ delivery. Assume the port 800de9ce703SDmitry Torokhov * is working and hope we are right. 801de9ce703SDmitry Torokhov */ 802de9ce703SDmitry Torokhov retval = 0; 803de9ce703SDmitry Torokhov goto out; 804de9ce703SDmitry Torokhov } 805de9ce703SDmitry Torokhov 806de9ce703SDmitry Torokhov if (request_irq(I8042_AUX_IRQ, i8042_aux_test_irq, IRQF_SHARED, 807de9ce703SDmitry Torokhov "i8042", i8042_platform_device)) 808de9ce703SDmitry Torokhov goto out; 809de9ce703SDmitry Torokhov 810386b3849SDmitry Torokhov irq_registered = true; 811de9ce703SDmitry Torokhov 812de9ce703SDmitry Torokhov if (i8042_enable_aux_port()) 813de9ce703SDmitry Torokhov goto out; 814de9ce703SDmitry Torokhov 815de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 816de9ce703SDmitry Torokhov 817de9ce703SDmitry Torokhov init_completion(&i8042_aux_irq_delivered); 818386b3849SDmitry Torokhov i8042_irq_being_tested = true; 819de9ce703SDmitry Torokhov 820de9ce703SDmitry Torokhov param = 0xa5; 821de9ce703SDmitry Torokhov retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); 822de9ce703SDmitry Torokhov 823de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 824de9ce703SDmitry Torokhov 825de9ce703SDmitry Torokhov if (retval) 826de9ce703SDmitry Torokhov goto out; 827de9ce703SDmitry Torokhov 828de9ce703SDmitry Torokhov if (wait_for_completion_timeout(&i8042_aux_irq_delivered, 829de9ce703SDmitry Torokhov msecs_to_jiffies(250)) == 0) { 830de9ce703SDmitry Torokhov /* 831de9ce703SDmitry Torokhov * AUX IRQ was never delivered so we need to flush the controller to 832de9ce703SDmitry Torokhov * get rid of the byte we put there; otherwise keyboard may not work. 833de9ce703SDmitry Torokhov */ 8344eb3c30bSJoe Perches dbg(" -- i8042 (aux irq test timeout)\n"); 835de9ce703SDmitry Torokhov i8042_flush(); 836de9ce703SDmitry Torokhov retval = -1; 837de9ce703SDmitry Torokhov } 838de9ce703SDmitry Torokhov 839de9ce703SDmitry Torokhov out: 840de9ce703SDmitry Torokhov 841de9ce703SDmitry Torokhov /* 8421da177e4SLinus Torvalds * Disable the interface. 8431da177e4SLinus Torvalds */ 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_AUXDIS; 8461da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_AUXINT; 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 849de9ce703SDmitry Torokhov retval = -1; 850de9ce703SDmitry Torokhov 851de9ce703SDmitry Torokhov if (irq_registered) 852de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 853de9ce703SDmitry Torokhov 854de9ce703SDmitry Torokhov return retval; 855de9ce703SDmitry Torokhov } 856de9ce703SDmitry Torokhov 857de9ce703SDmitry Torokhov static int i8042_controller_check(void) 858de9ce703SDmitry Torokhov { 8592f0d2604SAndrey Moiseev if (i8042_flush()) { 8604eb3c30bSJoe Perches pr_err("No controller found\n"); 861de9ce703SDmitry Torokhov return -ENODEV; 862de9ce703SDmitry Torokhov } 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds return 0; 8651da177e4SLinus Torvalds } 8661da177e4SLinus Torvalds 867de9ce703SDmitry Torokhov static int i8042_controller_selftest(void) 8682673c836SVojtech Pavlik { 8692673c836SVojtech Pavlik unsigned char param; 8705ea2fc64SArjan van de Ven int i = 0; 8712673c836SVojtech Pavlik 8725ea2fc64SArjan van de Ven /* 8735ea2fc64SArjan van de Ven * We try this 5 times; on some really fragile systems this does not 8745ea2fc64SArjan van de Ven * take the first time... 8755ea2fc64SArjan van de Ven */ 8765ea2fc64SArjan van de Ven do { 8775ea2fc64SArjan van de Ven 8782673c836SVojtech Pavlik if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { 8794eb3c30bSJoe Perches pr_err("i8042 controller selftest timeout\n"); 880de9ce703SDmitry Torokhov return -ENODEV; 8812673c836SVojtech Pavlik } 8822673c836SVojtech Pavlik 8835ea2fc64SArjan van de Ven if (param == I8042_RET_CTL_TEST) 8845ea2fc64SArjan van de Ven return 0; 8855ea2fc64SArjan van de Ven 886a2a94e73SPaul Bolle dbg("i8042 controller selftest: %#x != %#x\n", 8872673c836SVojtech Pavlik param, I8042_RET_CTL_TEST); 8885ea2fc64SArjan van de Ven msleep(50); 8895ea2fc64SArjan van de Ven } while (i++ < 5); 8902673c836SVojtech Pavlik 8915ea2fc64SArjan van de Ven #ifdef CONFIG_X86 8925ea2fc64SArjan van de Ven /* 8935ea2fc64SArjan van de Ven * On x86, we don't fail entire i8042 initialization if controller 8945ea2fc64SArjan van de Ven * reset fails in hopes that keyboard port will still be functional 8955ea2fc64SArjan van de Ven * and user will still get a working keyboard. This is especially 8965ea2fc64SArjan van de Ven * important on netbooks. On other arches we trust hardware more. 8975ea2fc64SArjan van de Ven */ 8984eb3c30bSJoe Perches pr_info("giving up on controller selftest, continuing anyway...\n"); 8992673c836SVojtech Pavlik return 0; 9005ea2fc64SArjan van de Ven #else 901a2a94e73SPaul Bolle pr_err("i8042 controller selftest failed\n"); 9025ea2fc64SArjan van de Ven return -EIO; 9035ea2fc64SArjan van de Ven #endif 9042673c836SVojtech Pavlik } 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds /* 9071da177e4SLinus Torvalds * i8042_controller init initializes the i8042 controller, and, 9081da177e4SLinus Torvalds * most importantly, sets it into non-xlated mode if that's 9091da177e4SLinus Torvalds * desired. 9101da177e4SLinus Torvalds */ 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds static int i8042_controller_init(void) 9131da177e4SLinus Torvalds { 9141da177e4SLinus Torvalds unsigned long flags; 915ee1e82ceSDmitry Torokhov int n = 0; 916ee1e82ceSDmitry Torokhov unsigned char ctr[2]; 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds /* 919ee1e82ceSDmitry Torokhov * Save the CTR for restore on unload / reboot. 9201da177e4SLinus Torvalds */ 9211da177e4SLinus Torvalds 922ee1e82ceSDmitry Torokhov do { 923ee1e82ceSDmitry Torokhov if (n >= 10) { 9244eb3c30bSJoe Perches pr_err("Unable to get stable CTR read\n"); 925de9ce703SDmitry Torokhov return -EIO; 9261da177e4SLinus Torvalds } 9271da177e4SLinus Torvalds 928ee1e82ceSDmitry Torokhov if (n != 0) 929ee1e82ceSDmitry Torokhov udelay(50); 930ee1e82ceSDmitry Torokhov 931ee1e82ceSDmitry Torokhov if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { 9324eb3c30bSJoe Perches pr_err("Can't read CTR while initializing i8042\n"); 933ee1e82ceSDmitry Torokhov return -EIO; 934ee1e82ceSDmitry Torokhov } 935ee1e82ceSDmitry Torokhov 936ee1e82ceSDmitry Torokhov } while (n < 2 || ctr[0] != ctr[1]); 937ee1e82ceSDmitry Torokhov 938ee1e82ceSDmitry Torokhov i8042_initial_ctr = i8042_ctr = ctr[0]; 9391da177e4SLinus Torvalds 9401da177e4SLinus Torvalds /* 9411da177e4SLinus Torvalds * Disable the keyboard interface and interrupt. 9421da177e4SLinus Torvalds */ 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_KBDDIS; 9451da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_KBDINT; 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds /* 9481da177e4SLinus Torvalds * Handle keylock. 9491da177e4SLinus Torvalds */ 9501da177e4SLinus Torvalds 9511da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 9521da177e4SLinus Torvalds if (~i8042_read_status() & I8042_STR_KEYLOCK) { 9531da177e4SLinus Torvalds if (i8042_unlock) 9541da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_IGNKEYLOCK; 9551da177e4SLinus Torvalds else 9564eb3c30bSJoe Perches pr_warn("Warning: Keylock active\n"); 9571da177e4SLinus Torvalds } 9581da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds /* 9611da177e4SLinus Torvalds * If the chip is configured into nontranslated mode by the BIOS, don't 9621da177e4SLinus Torvalds * bother enabling translating and be happy. 9631da177e4SLinus Torvalds */ 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds if (~i8042_ctr & I8042_CTR_XLATE) 966386b3849SDmitry Torokhov i8042_direct = true; 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds /* 9691da177e4SLinus Torvalds * Set nontranslated mode for the kbd interface if requested by an option. 9701da177e4SLinus Torvalds * After this the kbd interface becomes a simple serial in/out, like the aux 9711da177e4SLinus Torvalds * interface is. We don't do this by default, since it can confuse notebook 9721da177e4SLinus Torvalds * BIOSes. 9731da177e4SLinus Torvalds */ 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds if (i8042_direct) 9761da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_XLATE; 9771da177e4SLinus Torvalds 9781da177e4SLinus Torvalds /* 9791da177e4SLinus Torvalds * Write CTR back. 9801da177e4SLinus Torvalds */ 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 9834eb3c30bSJoe Perches pr_err("Can't write CTR while initializing i8042\n"); 984de9ce703SDmitry Torokhov return -EIO; 9851da177e4SLinus Torvalds } 9861da177e4SLinus Torvalds 987ee1e82ceSDmitry Torokhov /* 988ee1e82ceSDmitry Torokhov * Flush whatever accumulated while we were disabling keyboard port. 989ee1e82ceSDmitry Torokhov */ 990ee1e82ceSDmitry Torokhov 991ee1e82ceSDmitry Torokhov i8042_flush(); 992ee1e82ceSDmitry Torokhov 9931da177e4SLinus Torvalds return 0; 9941da177e4SLinus Torvalds } 9951da177e4SLinus Torvalds 9961da177e4SLinus Torvalds 9971da177e4SLinus Torvalds /* 998de9ce703SDmitry Torokhov * Reset the controller and reset CRT to the original value set by BIOS. 9991da177e4SLinus Torvalds */ 10001da177e4SLinus Torvalds 10011729ad1fSDmitry Torokhov static void i8042_controller_reset(bool force_reset) 1002de9ce703SDmitry Torokhov { 1003de9ce703SDmitry Torokhov i8042_flush(); 10041da177e4SLinus Torvalds 10051da177e4SLinus Torvalds /* 10068d04ddb6SDmitry Torokhov * Disable both KBD and AUX interfaces so they don't get in the way 10078d04ddb6SDmitry Torokhov */ 10088d04ddb6SDmitry Torokhov 10098d04ddb6SDmitry Torokhov i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; 10108d04ddb6SDmitry Torokhov i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); 10118d04ddb6SDmitry Torokhov 1012ee1e82ceSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 10134eb3c30bSJoe Perches pr_warn("Can't write CTR while resetting\n"); 10145ddbc77cSDmitry Torokhov 10158d04ddb6SDmitry Torokhov /* 10161da177e4SLinus Torvalds * Disable MUX mode if present. 10171da177e4SLinus Torvalds */ 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds if (i8042_mux_present) 1020386b3849SDmitry Torokhov i8042_set_mux_mode(false, NULL); 10211da177e4SLinus Torvalds 10221da177e4SLinus Torvalds /* 1023de9ce703SDmitry Torokhov * Reset the controller if requested. 1024de9ce703SDmitry Torokhov */ 1025de9ce703SDmitry Torokhov 10261729ad1fSDmitry Torokhov if (i8042_reset || force_reset) 1027de9ce703SDmitry Torokhov i8042_controller_selftest(); 1028de9ce703SDmitry Torokhov 1029de9ce703SDmitry Torokhov /* 10301da177e4SLinus Torvalds * Restore the original control register setting. 10311da177e4SLinus Torvalds */ 10321da177e4SLinus Torvalds 1033de9ce703SDmitry Torokhov if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) 10344eb3c30bSJoe Perches pr_warn("Can't restore CTR\n"); 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds 10381da177e4SLinus Torvalds /* 1039c7ff0d9cSTAMUKI Shoichi * i8042_panic_blink() will turn the keyboard LEDs on or off and is called 1040c7ff0d9cSTAMUKI Shoichi * when kernel panics. Flashing LEDs is useful for users running X who may 1041aa5e5dc2SMichael Opdenacker * not see the console and will help distinguishing panics from "real" 10421da177e4SLinus Torvalds * lockups. 10431da177e4SLinus Torvalds * 10441da177e4SLinus Torvalds * Note that DELAY has a limit of 10ms so we will not get stuck here 10451da177e4SLinus Torvalds * waiting for KBC to free up even if KBD interrupt is off 10461da177e4SLinus Torvalds */ 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) 10491da177e4SLinus Torvalds 1050c7ff0d9cSTAMUKI Shoichi static long i8042_panic_blink(int state) 10511da177e4SLinus Torvalds { 10521da177e4SLinus Torvalds long delay = 0; 1053c7ff0d9cSTAMUKI Shoichi char led; 10541da177e4SLinus Torvalds 1055c7ff0d9cSTAMUKI Shoichi led = (state) ? 0x01 | 0x04 : 0; 10561da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 10571da177e4SLinus Torvalds DELAY; 10584eb3c30bSJoe Perches dbg("%02x -> i8042 (panic blink)\n", 0xed); 105919f3c3e3SDmitry Torokhov i8042_suppress_kbd_ack = 2; 10601da177e4SLinus Torvalds i8042_write_data(0xed); /* set leds */ 10611da177e4SLinus Torvalds DELAY; 10621da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 10631da177e4SLinus Torvalds DELAY; 10641da177e4SLinus Torvalds DELAY; 10654eb3c30bSJoe Perches dbg("%02x -> i8042 (panic blink)\n", led); 10661da177e4SLinus Torvalds i8042_write_data(led); 10671da177e4SLinus Torvalds DELAY; 10681da177e4SLinus Torvalds return delay; 10691da177e4SLinus Torvalds } 10701da177e4SLinus Torvalds 10711da177e4SLinus Torvalds #undef DELAY 10721da177e4SLinus Torvalds 1073d35895dbSBruno Prémont #ifdef CONFIG_X86 1074d35895dbSBruno Prémont static void i8042_dritek_enable(void) 1075d35895dbSBruno Prémont { 1076594d6363SChristoph Fritz unsigned char param = 0x90; 1077d35895dbSBruno Prémont int error; 1078d35895dbSBruno Prémont 1079d35895dbSBruno Prémont error = i8042_command(¶m, 0x1059); 1080d35895dbSBruno Prémont if (error) 10814eb3c30bSJoe Perches pr_warn("Failed to enable DRITEK extension: %d\n", error); 1082d35895dbSBruno Prémont } 1083d35895dbSBruno Prémont #endif 1084d35895dbSBruno Prémont 108582dd9effSDmitry Torokhov #ifdef CONFIG_PM 10867e044e05SDmitry Torokhov 10871da177e4SLinus Torvalds /* 1088ebd7768dSDmitry Torokhov * Here we try to reset everything back to a state we had 1089ebd7768dSDmitry Torokhov * before suspending. 10901da177e4SLinus Torvalds */ 10911da177e4SLinus Torvalds 10921ca56e51SDmitry Torokhov static int i8042_controller_resume(bool force_reset) 10931da177e4SLinus Torvalds { 1094de9ce703SDmitry Torokhov int error; 10951da177e4SLinus Torvalds 1096de9ce703SDmitry Torokhov error = i8042_controller_check(); 1097de9ce703SDmitry Torokhov if (error) 1098de9ce703SDmitry Torokhov return error; 10992673c836SVojtech Pavlik 11001ca56e51SDmitry Torokhov if (i8042_reset || force_reset) { 1101de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 1102de9ce703SDmitry Torokhov if (error) 1103de9ce703SDmitry Torokhov return error; 11041ca56e51SDmitry Torokhov } 1105de9ce703SDmitry Torokhov 1106de9ce703SDmitry Torokhov /* 110782dd9effSDmitry Torokhov * Restore original CTR value and disable all ports 1108de9ce703SDmitry Torokhov */ 1109de9ce703SDmitry Torokhov 111082dd9effSDmitry Torokhov i8042_ctr = i8042_initial_ctr; 111182dd9effSDmitry Torokhov if (i8042_direct) 111282dd9effSDmitry Torokhov i8042_ctr &= ~I8042_CTR_XLATE; 1113de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; 1114de9ce703SDmitry Torokhov i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); 11152673c836SVojtech Pavlik if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 11164eb3c30bSJoe Perches pr_warn("Can't write CTR to resume, retrying...\n"); 11172f6a77d5SJiri Kosina msleep(50); 11182f6a77d5SJiri Kosina if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 11194eb3c30bSJoe Perches pr_err("CTR write retry failed\n"); 1120de9ce703SDmitry Torokhov return -EIO; 11211da177e4SLinus Torvalds } 11222f6a77d5SJiri Kosina } 11231da177e4SLinus Torvalds 1124d35895dbSBruno Prémont 1125d35895dbSBruno Prémont #ifdef CONFIG_X86 1126d35895dbSBruno Prémont if (i8042_dritek) 1127d35895dbSBruno Prémont i8042_dritek_enable(); 1128d35895dbSBruno Prémont #endif 1129d35895dbSBruno Prémont 1130de9ce703SDmitry Torokhov if (i8042_mux_present) { 1131386b3849SDmitry Torokhov if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) 11324eb3c30bSJoe Perches pr_warn("failed to resume active multiplexor, mouse won't work\n"); 1133de9ce703SDmitry Torokhov } else if (i8042_ports[I8042_AUX_PORT_NO].serio) 1134de9ce703SDmitry Torokhov i8042_enable_aux_port(); 11351da177e4SLinus Torvalds 1136de9ce703SDmitry Torokhov if (i8042_ports[I8042_KBD_PORT_NO].serio) 1137de9ce703SDmitry Torokhov i8042_enable_kbd_port(); 11381da177e4SLinus Torvalds 11397d12e780SDavid Howells i8042_interrupt(0, NULL); 11401da177e4SLinus Torvalds 11411da177e4SLinus Torvalds return 0; 11421da177e4SLinus Torvalds } 1143ebd7768dSDmitry Torokhov 11441ca56e51SDmitry Torokhov /* 11451ca56e51SDmitry Torokhov * Here we try to restore the original BIOS settings to avoid 11461ca56e51SDmitry Torokhov * upsetting it. 11471ca56e51SDmitry Torokhov */ 11481ca56e51SDmitry Torokhov 11491729ad1fSDmitry Torokhov static int i8042_pm_suspend(struct device *dev) 11501ca56e51SDmitry Torokhov { 11511729ad1fSDmitry Torokhov i8042_controller_reset(true); 11521ca56e51SDmitry Torokhov 11531ca56e51SDmitry Torokhov return 0; 11541ca56e51SDmitry Torokhov } 11551ca56e51SDmitry Torokhov 11561ca56e51SDmitry Torokhov static int i8042_pm_resume(struct device *dev) 11571ca56e51SDmitry Torokhov { 11581ca56e51SDmitry Torokhov /* 11591ca56e51SDmitry Torokhov * On resume from S2R we always try to reset the controller 11601ca56e51SDmitry Torokhov * to bring it in a sane state. (In case of S2D we expect 11611ca56e51SDmitry Torokhov * BIOS to reset the controller for us.) 11621ca56e51SDmitry Torokhov */ 11631ca56e51SDmitry Torokhov return i8042_controller_resume(true); 11641ca56e51SDmitry Torokhov } 11651ca56e51SDmitry Torokhov 1166c2d1a2a1SAlan Jenkins static int i8042_pm_thaw(struct device *dev) 1167c2d1a2a1SAlan Jenkins { 1168c2d1a2a1SAlan Jenkins i8042_interrupt(0, NULL); 1169c2d1a2a1SAlan Jenkins 1170c2d1a2a1SAlan Jenkins return 0; 1171c2d1a2a1SAlan Jenkins } 1172c2d1a2a1SAlan Jenkins 11731729ad1fSDmitry Torokhov static int i8042_pm_reset(struct device *dev) 11741729ad1fSDmitry Torokhov { 11751729ad1fSDmitry Torokhov i8042_controller_reset(false); 11761729ad1fSDmitry Torokhov 11771729ad1fSDmitry Torokhov return 0; 11781729ad1fSDmitry Torokhov } 11791729ad1fSDmitry Torokhov 11801ca56e51SDmitry Torokhov static int i8042_pm_restore(struct device *dev) 11811ca56e51SDmitry Torokhov { 11821ca56e51SDmitry Torokhov return i8042_controller_resume(false); 11831ca56e51SDmitry Torokhov } 11841ca56e51SDmitry Torokhov 1185ebd7768dSDmitry Torokhov static const struct dev_pm_ops i8042_pm_ops = { 11861729ad1fSDmitry Torokhov .suspend = i8042_pm_suspend, 11871ca56e51SDmitry Torokhov .resume = i8042_pm_resume, 1188c2d1a2a1SAlan Jenkins .thaw = i8042_pm_thaw, 1189ebd7768dSDmitry Torokhov .poweroff = i8042_pm_reset, 1190ebd7768dSDmitry Torokhov .restore = i8042_pm_restore, 1191ebd7768dSDmitry Torokhov }; 1192ebd7768dSDmitry Torokhov 119382dd9effSDmitry Torokhov #endif /* CONFIG_PM */ 11941da177e4SLinus Torvalds 11951da177e4SLinus Torvalds /* 11961da177e4SLinus Torvalds * We need to reset the 8042 back to original mode on system shutdown, 11971da177e4SLinus Torvalds * because otherwise BIOSes will be confused. 11981da177e4SLinus Torvalds */ 11991da177e4SLinus Torvalds 12003ae5eaecSRussell King static void i8042_shutdown(struct platform_device *dev) 12011da177e4SLinus Torvalds { 12021729ad1fSDmitry Torokhov i8042_controller_reset(false); 12031da177e4SLinus Torvalds } 12041da177e4SLinus Torvalds 1205f8113416SDmitry Torokhov static int __init i8042_create_kbd_port(void) 12061da177e4SLinus Torvalds { 12071da177e4SLinus Torvalds struct serio *serio; 12081da177e4SLinus Torvalds struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; 12091da177e4SLinus Torvalds 1210d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 12110854e52dSDmitry Torokhov if (!serio) 12120854e52dSDmitry Torokhov return -ENOMEM; 12130854e52dSDmitry Torokhov 12141da177e4SLinus Torvalds serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; 12151da177e4SLinus Torvalds serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; 12161da177e4SLinus Torvalds serio->start = i8042_start; 12171da177e4SLinus Torvalds serio->stop = i8042_stop; 12185ddbc77cSDmitry Torokhov serio->close = i8042_port_close; 12191da177e4SLinus Torvalds serio->port_data = port; 12201da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 1221de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); 12221da177e4SLinus Torvalds strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 1223a7c5868cSHans de Goede strlcpy(serio->firmware_id, i8042_kbd_firmware_id, 1224a7c5868cSHans de Goede sizeof(serio->firmware_id)); 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds port->serio = serio; 1227de9ce703SDmitry Torokhov port->irq = I8042_KBD_IRQ; 12280854e52dSDmitry Torokhov 1229de9ce703SDmitry Torokhov return 0; 12301da177e4SLinus Torvalds } 12311da177e4SLinus Torvalds 1232f8113416SDmitry Torokhov static int __init i8042_create_aux_port(int idx) 12331da177e4SLinus Torvalds { 12341da177e4SLinus Torvalds struct serio *serio; 1235de9ce703SDmitry Torokhov int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; 1236de9ce703SDmitry Torokhov struct i8042_port *port = &i8042_ports[port_no]; 12371da177e4SLinus Torvalds 1238d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 12390854e52dSDmitry Torokhov if (!serio) 12400854e52dSDmitry Torokhov return -ENOMEM; 12410854e52dSDmitry Torokhov 12421da177e4SLinus Torvalds serio->id.type = SERIO_8042; 12431da177e4SLinus Torvalds serio->write = i8042_aux_write; 12441da177e4SLinus Torvalds serio->start = i8042_start; 12451da177e4SLinus Torvalds serio->stop = i8042_stop; 12461da177e4SLinus Torvalds serio->port_data = port; 12471da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 1248de9ce703SDmitry Torokhov if (idx < 0) { 1249de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); 12501da177e4SLinus Torvalds strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 1251a7c5868cSHans de Goede strlcpy(serio->firmware_id, i8042_aux_firmware_id, 1252a7c5868cSHans de Goede sizeof(serio->firmware_id)); 12535ddbc77cSDmitry Torokhov serio->close = i8042_port_close; 1254de9ce703SDmitry Torokhov } else { 1255de9ce703SDmitry Torokhov snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); 1256de9ce703SDmitry Torokhov snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); 1257266e43c4SHans de Goede strlcpy(serio->firmware_id, i8042_aux_firmware_id, 1258266e43c4SHans de Goede sizeof(serio->firmware_id)); 12591da177e4SLinus Torvalds } 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds port->serio = serio; 1262de9ce703SDmitry Torokhov port->mux = idx; 1263de9ce703SDmitry Torokhov port->irq = I8042_AUX_IRQ; 12640854e52dSDmitry Torokhov 1265de9ce703SDmitry Torokhov return 0; 1266de9ce703SDmitry Torokhov } 1267de9ce703SDmitry Torokhov 1268f8113416SDmitry Torokhov static void __init i8042_free_kbd_port(void) 1269de9ce703SDmitry Torokhov { 1270de9ce703SDmitry Torokhov kfree(i8042_ports[I8042_KBD_PORT_NO].serio); 1271de9ce703SDmitry Torokhov i8042_ports[I8042_KBD_PORT_NO].serio = NULL; 1272de9ce703SDmitry Torokhov } 1273de9ce703SDmitry Torokhov 1274f8113416SDmitry Torokhov static void __init i8042_free_aux_ports(void) 1275de9ce703SDmitry Torokhov { 1276de9ce703SDmitry Torokhov int i; 1277de9ce703SDmitry Torokhov 1278de9ce703SDmitry Torokhov for (i = I8042_AUX_PORT_NO; i < I8042_NUM_PORTS; i++) { 1279de9ce703SDmitry Torokhov kfree(i8042_ports[i].serio); 1280de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 1281de9ce703SDmitry Torokhov } 1282de9ce703SDmitry Torokhov } 1283de9ce703SDmitry Torokhov 1284f8113416SDmitry Torokhov static void __init i8042_register_ports(void) 1285de9ce703SDmitry Torokhov { 1286de9ce703SDmitry Torokhov int i; 1287de9ce703SDmitry Torokhov 1288de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 1289de9ce703SDmitry Torokhov if (i8042_ports[i].serio) { 1290de9ce703SDmitry Torokhov printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", 1291de9ce703SDmitry Torokhov i8042_ports[i].serio->name, 1292de9ce703SDmitry Torokhov (unsigned long) I8042_DATA_REG, 1293de9ce703SDmitry Torokhov (unsigned long) I8042_COMMAND_REG, 1294de9ce703SDmitry Torokhov i8042_ports[i].irq); 1295de9ce703SDmitry Torokhov serio_register_port(i8042_ports[i].serio); 1296de9ce703SDmitry Torokhov } 1297de9ce703SDmitry Torokhov } 1298de9ce703SDmitry Torokhov } 1299de9ce703SDmitry Torokhov 1300e2619cf7SBill Pemberton static void i8042_unregister_ports(void) 1301de9ce703SDmitry Torokhov { 1302de9ce703SDmitry Torokhov int i; 1303de9ce703SDmitry Torokhov 1304de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 1305de9ce703SDmitry Torokhov if (i8042_ports[i].serio) { 1306de9ce703SDmitry Torokhov serio_unregister_port(i8042_ports[i].serio); 1307de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 1308de9ce703SDmitry Torokhov } 1309de9ce703SDmitry Torokhov } 1310de9ce703SDmitry Torokhov } 1311de9ce703SDmitry Torokhov 1312181d683dSDmitry Torokhov /* 1313181d683dSDmitry Torokhov * Checks whether port belongs to i8042 controller. 1314181d683dSDmitry Torokhov */ 1315181d683dSDmitry Torokhov bool i8042_check_port_owner(const struct serio *port) 1316181d683dSDmitry Torokhov { 1317181d683dSDmitry Torokhov int i; 1318181d683dSDmitry Torokhov 1319181d683dSDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) 1320181d683dSDmitry Torokhov if (i8042_ports[i].serio == port) 1321181d683dSDmitry Torokhov return true; 1322181d683dSDmitry Torokhov 1323181d683dSDmitry Torokhov return false; 1324181d683dSDmitry Torokhov } 1325181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_check_port_owner); 1326181d683dSDmitry Torokhov 1327de9ce703SDmitry Torokhov static void i8042_free_irqs(void) 1328de9ce703SDmitry Torokhov { 1329de9ce703SDmitry Torokhov if (i8042_aux_irq_registered) 1330de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1331de9ce703SDmitry Torokhov if (i8042_kbd_irq_registered) 1332de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1333de9ce703SDmitry Torokhov 1334386b3849SDmitry Torokhov i8042_aux_irq_registered = i8042_kbd_irq_registered = false; 1335de9ce703SDmitry Torokhov } 1336de9ce703SDmitry Torokhov 1337f8113416SDmitry Torokhov static int __init i8042_setup_aux(void) 1338de9ce703SDmitry Torokhov { 1339de9ce703SDmitry Torokhov int (*aux_enable)(void); 1340de9ce703SDmitry Torokhov int error; 1341de9ce703SDmitry Torokhov int i; 1342de9ce703SDmitry Torokhov 1343de9ce703SDmitry Torokhov if (i8042_check_aux()) 1344de9ce703SDmitry Torokhov return -ENODEV; 1345de9ce703SDmitry Torokhov 1346de9ce703SDmitry Torokhov if (i8042_nomux || i8042_check_mux()) { 1347de9ce703SDmitry Torokhov error = i8042_create_aux_port(-1); 1348de9ce703SDmitry Torokhov if (error) 1349de9ce703SDmitry Torokhov goto err_free_ports; 1350de9ce703SDmitry Torokhov aux_enable = i8042_enable_aux_port; 1351de9ce703SDmitry Torokhov } else { 1352de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 1353de9ce703SDmitry Torokhov error = i8042_create_aux_port(i); 1354de9ce703SDmitry Torokhov if (error) 1355de9ce703SDmitry Torokhov goto err_free_ports; 1356de9ce703SDmitry Torokhov } 1357de9ce703SDmitry Torokhov aux_enable = i8042_enable_mux_ports; 1358de9ce703SDmitry Torokhov } 1359de9ce703SDmitry Torokhov 1360de9ce703SDmitry Torokhov error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, 1361de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1362de9ce703SDmitry Torokhov if (error) 1363de9ce703SDmitry Torokhov goto err_free_ports; 1364de9ce703SDmitry Torokhov 1365de9ce703SDmitry Torokhov if (aux_enable()) 1366de9ce703SDmitry Torokhov goto err_free_irq; 1367de9ce703SDmitry Torokhov 1368386b3849SDmitry Torokhov i8042_aux_irq_registered = true; 1369de9ce703SDmitry Torokhov return 0; 1370de9ce703SDmitry Torokhov 1371de9ce703SDmitry Torokhov err_free_irq: 1372de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1373de9ce703SDmitry Torokhov err_free_ports: 1374de9ce703SDmitry Torokhov i8042_free_aux_ports(); 1375de9ce703SDmitry Torokhov return error; 1376de9ce703SDmitry Torokhov } 1377de9ce703SDmitry Torokhov 1378f8113416SDmitry Torokhov static int __init i8042_setup_kbd(void) 1379de9ce703SDmitry Torokhov { 1380de9ce703SDmitry Torokhov int error; 1381de9ce703SDmitry Torokhov 1382de9ce703SDmitry Torokhov error = i8042_create_kbd_port(); 1383de9ce703SDmitry Torokhov if (error) 1384de9ce703SDmitry Torokhov return error; 1385de9ce703SDmitry Torokhov 1386de9ce703SDmitry Torokhov error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, 1387de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1388de9ce703SDmitry Torokhov if (error) 1389de9ce703SDmitry Torokhov goto err_free_port; 1390de9ce703SDmitry Torokhov 1391de9ce703SDmitry Torokhov error = i8042_enable_kbd_port(); 1392de9ce703SDmitry Torokhov if (error) 1393de9ce703SDmitry Torokhov goto err_free_irq; 1394de9ce703SDmitry Torokhov 1395386b3849SDmitry Torokhov i8042_kbd_irq_registered = true; 1396de9ce703SDmitry Torokhov return 0; 1397de9ce703SDmitry Torokhov 1398de9ce703SDmitry Torokhov err_free_irq: 1399de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1400de9ce703SDmitry Torokhov err_free_port: 1401de9ce703SDmitry Torokhov i8042_free_kbd_port(); 1402de9ce703SDmitry Torokhov return error; 14031da177e4SLinus Torvalds } 14041da177e4SLinus Torvalds 1405f8113416SDmitry Torokhov static int __init i8042_probe(struct platform_device *dev) 14061da177e4SLinus Torvalds { 1407de9ce703SDmitry Torokhov int error; 14081da177e4SLinus Torvalds 1409ec62e1c8SDmitry Torokhov i8042_platform_device = dev; 1410ec62e1c8SDmitry Torokhov 14111ca56e51SDmitry Torokhov if (i8042_reset) { 1412de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 1413de9ce703SDmitry Torokhov if (error) 1414de9ce703SDmitry Torokhov return error; 14151ca56e51SDmitry Torokhov } 14161da177e4SLinus Torvalds 1417de9ce703SDmitry Torokhov error = i8042_controller_init(); 1418de9ce703SDmitry Torokhov if (error) 1419de9ce703SDmitry Torokhov return error; 14201da177e4SLinus Torvalds 1421d35895dbSBruno Prémont #ifdef CONFIG_X86 1422d35895dbSBruno Prémont if (i8042_dritek) 1423d35895dbSBruno Prémont i8042_dritek_enable(); 1424d35895dbSBruno Prémont #endif 1425d35895dbSBruno Prémont 1426de9ce703SDmitry Torokhov if (!i8042_noaux) { 1427de9ce703SDmitry Torokhov error = i8042_setup_aux(); 1428de9ce703SDmitry Torokhov if (error && error != -ENODEV && error != -EBUSY) 1429de9ce703SDmitry Torokhov goto out_fail; 14301da177e4SLinus Torvalds } 14311da177e4SLinus Torvalds 1432945ef0d4SDmitry Torokhov if (!i8042_nokbd) { 1433de9ce703SDmitry Torokhov error = i8042_setup_kbd(); 1434de9ce703SDmitry Torokhov if (error) 1435de9ce703SDmitry Torokhov goto out_fail; 1436945ef0d4SDmitry Torokhov } 1437de9ce703SDmitry Torokhov /* 1438de9ce703SDmitry Torokhov * Ok, everything is ready, let's register all serio ports 1439de9ce703SDmitry Torokhov */ 1440de9ce703SDmitry Torokhov i8042_register_ports(); 14411da177e4SLinus Torvalds 14421da177e4SLinus Torvalds return 0; 14430854e52dSDmitry Torokhov 1444de9ce703SDmitry Torokhov out_fail: 1445de9ce703SDmitry Torokhov i8042_free_aux_ports(); /* in case KBD failed but AUX not */ 1446de9ce703SDmitry Torokhov i8042_free_irqs(); 14471729ad1fSDmitry Torokhov i8042_controller_reset(false); 1448ec62e1c8SDmitry Torokhov i8042_platform_device = NULL; 14490854e52dSDmitry Torokhov 1450de9ce703SDmitry Torokhov return error; 14511da177e4SLinus Torvalds } 14521da177e4SLinus Torvalds 1453e2619cf7SBill Pemberton static int i8042_remove(struct platform_device *dev) 14541da177e4SLinus Torvalds { 1455de9ce703SDmitry Torokhov i8042_unregister_ports(); 1456de9ce703SDmitry Torokhov i8042_free_irqs(); 14571729ad1fSDmitry Torokhov i8042_controller_reset(false); 1458ec62e1c8SDmitry Torokhov i8042_platform_device = NULL; 14591da177e4SLinus Torvalds 146087fd6318SDmitry Torokhov return 0; 146187fd6318SDmitry Torokhov } 146287fd6318SDmitry Torokhov 146387fd6318SDmitry Torokhov static struct platform_driver i8042_driver = { 146487fd6318SDmitry Torokhov .driver = { 146587fd6318SDmitry Torokhov .name = "i8042", 146687fd6318SDmitry Torokhov .owner = THIS_MODULE, 1467ebd7768dSDmitry Torokhov #ifdef CONFIG_PM 1468ebd7768dSDmitry Torokhov .pm = &i8042_pm_ops, 1469ebd7768dSDmitry Torokhov #endif 147087fd6318SDmitry Torokhov }, 14711cb0aa88SBill Pemberton .remove = i8042_remove, 147282dd9effSDmitry Torokhov .shutdown = i8042_shutdown, 147387fd6318SDmitry Torokhov }; 147487fd6318SDmitry Torokhov 147587fd6318SDmitry Torokhov static int __init i8042_init(void) 147687fd6318SDmitry Torokhov { 1477ec62e1c8SDmitry Torokhov struct platform_device *pdev; 147887fd6318SDmitry Torokhov int err; 147987fd6318SDmitry Torokhov 148087fd6318SDmitry Torokhov dbg_init(); 148187fd6318SDmitry Torokhov 148287fd6318SDmitry Torokhov err = i8042_platform_init(); 148387fd6318SDmitry Torokhov if (err) 148487fd6318SDmitry Torokhov return err; 148587fd6318SDmitry Torokhov 1486de9ce703SDmitry Torokhov err = i8042_controller_check(); 1487de9ce703SDmitry Torokhov if (err) 1488de9ce703SDmitry Torokhov goto err_platform_exit; 148987fd6318SDmitry Torokhov 1490ec62e1c8SDmitry Torokhov pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); 1491ec62e1c8SDmitry Torokhov if (IS_ERR(pdev)) { 1492ec62e1c8SDmitry Torokhov err = PTR_ERR(pdev); 1493f8113416SDmitry Torokhov goto err_platform_exit; 149487fd6318SDmitry Torokhov } 149587fd6318SDmitry Torokhov 1496de9ce703SDmitry Torokhov panic_blink = i8042_panic_blink; 1497de9ce703SDmitry Torokhov 149887fd6318SDmitry Torokhov return 0; 149987fd6318SDmitry Torokhov 150087fd6318SDmitry Torokhov err_platform_exit: 150187fd6318SDmitry Torokhov i8042_platform_exit(); 150287fd6318SDmitry Torokhov return err; 150387fd6318SDmitry Torokhov } 150487fd6318SDmitry Torokhov 150587fd6318SDmitry Torokhov static void __exit i8042_exit(void) 150687fd6318SDmitry Torokhov { 1507f8113416SDmitry Torokhov platform_device_unregister(i8042_platform_device); 1508af045b86SDmitry Torokhov platform_driver_unregister(&i8042_driver); 15091da177e4SLinus Torvalds i8042_platform_exit(); 15101da177e4SLinus Torvalds 15111da177e4SLinus Torvalds panic_blink = NULL; 15121da177e4SLinus Torvalds } 15131da177e4SLinus Torvalds 15141da177e4SLinus Torvalds module_init(i8042_init); 15151da177e4SLinus Torvalds module_exit(i8042_exit); 1516