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 42e55a3366SDmitry 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 70148e9a71SSrihari Vijayaraghavan static bool i8042_kbdreset; 71148e9a71SSrihari Vijayaraghavan module_param_named(kbdreset, i8042_kbdreset, bool, 0); 72148e9a71SSrihari Vijayaraghavan MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port"); 73148e9a71SSrihari Vijayaraghavan 748987fec0SCarlos Corbacho #ifdef CONFIG_X86 75386b3849SDmitry Torokhov static bool i8042_dritek; 768987fec0SCarlos Corbacho module_param_named(dritek, i8042_dritek, bool, 0); 778987fec0SCarlos Corbacho MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); 788987fec0SCarlos Corbacho #endif 798987fec0SCarlos Corbacho 801da177e4SLinus Torvalds #ifdef CONFIG_PNP 81386b3849SDmitry Torokhov static bool i8042_nopnp; 821da177e4SLinus Torvalds module_param_named(nopnp, i8042_nopnp, bool, 0); 831da177e4SLinus Torvalds MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); 841da177e4SLinus Torvalds #endif 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds #define DEBUG 871da177e4SLinus Torvalds #ifdef DEBUG 88386b3849SDmitry Torokhov static bool i8042_debug; 891da177e4SLinus Torvalds module_param_named(debug, i8042_debug, bool, 0600); 901da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); 911da177e4SLinus Torvalds #endif 921da177e4SLinus Torvalds 931c7827aeSDmitry Torokhov static bool i8042_bypass_aux_irq_test; 94a7c5868cSHans de Goede static char i8042_kbd_firmware_id[128]; 95a7c5868cSHans de Goede static char i8042_aux_firmware_id[128]; 961c7827aeSDmitry Torokhov 971da177e4SLinus Torvalds #include "i8042.h" 981da177e4SLinus Torvalds 99181d683dSDmitry Torokhov /* 100181d683dSDmitry Torokhov * i8042_lock protects serialization between i8042_command and 101181d683dSDmitry Torokhov * the interrupt handler. 102181d683dSDmitry Torokhov */ 1031da177e4SLinus Torvalds static DEFINE_SPINLOCK(i8042_lock); 1041da177e4SLinus Torvalds 105181d683dSDmitry Torokhov /* 106181d683dSDmitry Torokhov * Writers to AUX and KBD ports as well as users issuing i8042_command 107181d683dSDmitry Torokhov * directly should acquire i8042_mutex (by means of calling 108181d683dSDmitry Torokhov * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that 109181d683dSDmitry Torokhov * they do not disturb each other (unfortunately in many i8042 110181d683dSDmitry Torokhov * implementations write to one of the ports will immediately abort 111181d683dSDmitry Torokhov * command that is being processed by another port). 112181d683dSDmitry Torokhov */ 113181d683dSDmitry Torokhov static DEFINE_MUTEX(i8042_mutex); 114181d683dSDmitry Torokhov 1151da177e4SLinus Torvalds struct i8042_port { 1161da177e4SLinus Torvalds struct serio *serio; 1171da177e4SLinus Torvalds int irq; 118386b3849SDmitry Torokhov bool exists; 1191da177e4SLinus Torvalds signed char mux; 1201da177e4SLinus Torvalds }; 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds #define I8042_KBD_PORT_NO 0 1231da177e4SLinus Torvalds #define I8042_AUX_PORT_NO 1 1241da177e4SLinus Torvalds #define I8042_MUX_PORT_NO 2 1251da177e4SLinus Torvalds #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) 126de9ce703SDmitry Torokhov 127de9ce703SDmitry Torokhov static struct i8042_port i8042_ports[I8042_NUM_PORTS]; 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds static unsigned char i8042_initial_ctr; 1301da177e4SLinus Torvalds static unsigned char i8042_ctr; 131386b3849SDmitry Torokhov static bool i8042_mux_present; 132386b3849SDmitry Torokhov static bool i8042_kbd_irq_registered; 133386b3849SDmitry Torokhov static bool i8042_aux_irq_registered; 134817e6ba3SDmitry Torokhov static unsigned char i8042_suppress_kbd_ack; 1351da177e4SLinus Torvalds static struct platform_device *i8042_platform_device; 1361da177e4SLinus Torvalds 1377d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id); 138967c9ef9SMatthew Garrett static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, 139967c9ef9SMatthew Garrett struct serio *serio); 1401da177e4SLinus Torvalds 141181d683dSDmitry Torokhov void i8042_lock_chip(void) 142181d683dSDmitry Torokhov { 143181d683dSDmitry Torokhov mutex_lock(&i8042_mutex); 144181d683dSDmitry Torokhov } 145181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_lock_chip); 146181d683dSDmitry Torokhov 147181d683dSDmitry Torokhov void i8042_unlock_chip(void) 148181d683dSDmitry Torokhov { 149181d683dSDmitry Torokhov mutex_unlock(&i8042_mutex); 150181d683dSDmitry Torokhov } 151181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_unlock_chip); 152181d683dSDmitry Torokhov 153967c9ef9SMatthew Garrett int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 154967c9ef9SMatthew Garrett struct serio *serio)) 155967c9ef9SMatthew Garrett { 156967c9ef9SMatthew Garrett unsigned long flags; 157967c9ef9SMatthew Garrett int ret = 0; 158967c9ef9SMatthew Garrett 159967c9ef9SMatthew Garrett spin_lock_irqsave(&i8042_lock, flags); 160967c9ef9SMatthew Garrett 161967c9ef9SMatthew Garrett if (i8042_platform_filter) { 162967c9ef9SMatthew Garrett ret = -EBUSY; 163967c9ef9SMatthew Garrett goto out; 164967c9ef9SMatthew Garrett } 165967c9ef9SMatthew Garrett 166967c9ef9SMatthew Garrett i8042_platform_filter = filter; 167967c9ef9SMatthew Garrett 168967c9ef9SMatthew Garrett out: 169967c9ef9SMatthew Garrett spin_unlock_irqrestore(&i8042_lock, flags); 170967c9ef9SMatthew Garrett return ret; 171967c9ef9SMatthew Garrett } 172967c9ef9SMatthew Garrett EXPORT_SYMBOL(i8042_install_filter); 173967c9ef9SMatthew Garrett 174967c9ef9SMatthew Garrett int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 175967c9ef9SMatthew Garrett struct serio *port)) 176967c9ef9SMatthew Garrett { 177967c9ef9SMatthew Garrett unsigned long flags; 178967c9ef9SMatthew Garrett int ret = 0; 179967c9ef9SMatthew Garrett 180967c9ef9SMatthew Garrett spin_lock_irqsave(&i8042_lock, flags); 181967c9ef9SMatthew Garrett 182967c9ef9SMatthew Garrett if (i8042_platform_filter != filter) { 183967c9ef9SMatthew Garrett ret = -EINVAL; 184967c9ef9SMatthew Garrett goto out; 185967c9ef9SMatthew Garrett } 186967c9ef9SMatthew Garrett 187967c9ef9SMatthew Garrett i8042_platform_filter = NULL; 188967c9ef9SMatthew Garrett 189967c9ef9SMatthew Garrett out: 190967c9ef9SMatthew Garrett spin_unlock_irqrestore(&i8042_lock, flags); 191967c9ef9SMatthew Garrett return ret; 192967c9ef9SMatthew Garrett } 193967c9ef9SMatthew Garrett EXPORT_SYMBOL(i8042_remove_filter); 194967c9ef9SMatthew Garrett 1951da177e4SLinus Torvalds /* 1961da177e4SLinus Torvalds * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to 1971da177e4SLinus Torvalds * be ready for reading values from it / writing values to it. 1981da177e4SLinus Torvalds * Called always with i8042_lock held. 1991da177e4SLinus Torvalds */ 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds static int i8042_wait_read(void) 2021da177e4SLinus Torvalds { 2031da177e4SLinus Torvalds int i = 0; 204de9ce703SDmitry Torokhov 2051da177e4SLinus Torvalds while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { 2061da177e4SLinus Torvalds udelay(50); 2071da177e4SLinus Torvalds i++; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds static int i8042_wait_write(void) 2131da177e4SLinus Torvalds { 2141da177e4SLinus Torvalds int i = 0; 215de9ce703SDmitry Torokhov 2161da177e4SLinus Torvalds while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { 2171da177e4SLinus Torvalds udelay(50); 2181da177e4SLinus Torvalds i++; 2191da177e4SLinus Torvalds } 2201da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds /* 2241da177e4SLinus Torvalds * i8042_flush() flushes all data that may be in the keyboard and mouse buffers 2251da177e4SLinus Torvalds * of the i8042 down the toilet. 2261da177e4SLinus Torvalds */ 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds static int i8042_flush(void) 2291da177e4SLinus Torvalds { 2301da177e4SLinus Torvalds unsigned long flags; 2311da177e4SLinus Torvalds unsigned char data, str; 2322f0d2604SAndrey Moiseev int count = 0; 2332f0d2604SAndrey Moiseev int retval = 0; 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 2361da177e4SLinus Torvalds 2372f0d2604SAndrey Moiseev while ((str = i8042_read_status()) & I8042_STR_OBF) { 2382f0d2604SAndrey Moiseev if (count++ < I8042_BUFFER_SIZE) { 2391da177e4SLinus Torvalds udelay(50); 2401da177e4SLinus Torvalds data = i8042_read_data(); 2414eb3c30bSJoe Perches dbg("%02x <- i8042 (flush, %s)\n", 2424eb3c30bSJoe Perches data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 2432f0d2604SAndrey Moiseev } else { 2442f0d2604SAndrey Moiseev retval = -EIO; 2452f0d2604SAndrey Moiseev break; 2462f0d2604SAndrey Moiseev } 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 2501da177e4SLinus Torvalds 2512f0d2604SAndrey Moiseev return retval; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds /* 2551da177e4SLinus Torvalds * i8042_command() executes a command on the i8042. It also sends the input 2561da177e4SLinus Torvalds * parameter(s) of the commands to it, and receives the output value(s). The 2571da177e4SLinus Torvalds * parameters are to be stored in the param array, and the output is placed 2581da177e4SLinus Torvalds * into the same array. The number of the parameters and output values is 2591da177e4SLinus Torvalds * encoded in bits 8-11 of the command number. 2601da177e4SLinus Torvalds */ 2611da177e4SLinus Torvalds 262de9ce703SDmitry Torokhov static int __i8042_command(unsigned char *param, int command) 2631da177e4SLinus Torvalds { 264de9ce703SDmitry Torokhov int i, error; 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds if (i8042_noloop && command == I8042_CMD_AUX_LOOP) 2671da177e4SLinus Torvalds return -1; 2681da177e4SLinus Torvalds 269de9ce703SDmitry Torokhov error = i8042_wait_write(); 270de9ce703SDmitry Torokhov if (error) 271de9ce703SDmitry Torokhov return error; 272463a4f76SDmitry Torokhov 2734eb3c30bSJoe Perches dbg("%02x -> i8042 (command)\n", command & 0xff); 2741da177e4SLinus Torvalds i8042_write_command(command & 0xff); 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds for (i = 0; i < ((command >> 12) & 0xf); i++) { 277de9ce703SDmitry Torokhov error = i8042_wait_write(); 278de9ce703SDmitry Torokhov if (error) 279de9ce703SDmitry Torokhov return error; 2804eb3c30bSJoe Perches dbg("%02x -> i8042 (parameter)\n", param[i]); 2811da177e4SLinus Torvalds i8042_write_data(param[i]); 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds for (i = 0; i < ((command >> 8) & 0xf); i++) { 285de9ce703SDmitry Torokhov error = i8042_wait_read(); 286de9ce703SDmitry Torokhov if (error) { 2874eb3c30bSJoe Perches dbg(" -- i8042 (timeout)\n"); 288de9ce703SDmitry Torokhov return error; 289de9ce703SDmitry Torokhov } 290463a4f76SDmitry Torokhov 291463a4f76SDmitry Torokhov if (command == I8042_CMD_AUX_LOOP && 292463a4f76SDmitry Torokhov !(i8042_read_status() & I8042_STR_AUXDATA)) { 2934eb3c30bSJoe Perches dbg(" -- i8042 (auxerr)\n"); 294de9ce703SDmitry Torokhov return -1; 295463a4f76SDmitry Torokhov } 296463a4f76SDmitry Torokhov 2971da177e4SLinus Torvalds param[i] = i8042_read_data(); 2984eb3c30bSJoe Perches dbg("%02x <- i8042 (return)\n", param[i]); 2991da177e4SLinus Torvalds } 3001da177e4SLinus Torvalds 301de9ce703SDmitry Torokhov return 0; 302de9ce703SDmitry Torokhov } 3031da177e4SLinus Torvalds 304553a05b8SMárton Németh int i8042_command(unsigned char *param, int command) 305de9ce703SDmitry Torokhov { 306de9ce703SDmitry Torokhov unsigned long flags; 307de9ce703SDmitry Torokhov int retval; 308de9ce703SDmitry Torokhov 309de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 310de9ce703SDmitry Torokhov retval = __i8042_command(param, command); 311463a4f76SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 312de9ce703SDmitry Torokhov 3131da177e4SLinus Torvalds return retval; 3141da177e4SLinus Torvalds } 315553a05b8SMárton Németh EXPORT_SYMBOL(i8042_command); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* 3181da177e4SLinus Torvalds * i8042_kbd_write() sends a byte out through the keyboard interface. 3191da177e4SLinus Torvalds */ 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds static int i8042_kbd_write(struct serio *port, unsigned char c) 3221da177e4SLinus Torvalds { 3231da177e4SLinus Torvalds unsigned long flags; 3241da177e4SLinus Torvalds int retval = 0; 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds if (!(retval = i8042_wait_write())) { 3294eb3c30bSJoe Perches dbg("%02x -> i8042 (kbd-data)\n", c); 3301da177e4SLinus Torvalds i8042_write_data(c); 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds return retval; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds /* 3391da177e4SLinus Torvalds * i8042_aux_write() sends a byte out through the aux interface. 3401da177e4SLinus Torvalds */ 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds static int i8042_aux_write(struct serio *serio, unsigned char c) 3431da177e4SLinus Torvalds { 3441da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 3451da177e4SLinus Torvalds 346f4e3c711SDmitry Torokhov return i8042_command(&c, port->mux == -1 ? 347f4e3c711SDmitry Torokhov I8042_CMD_AUX_SEND : 348f4e3c711SDmitry Torokhov I8042_CMD_MUX_SEND + port->mux); 3491da177e4SLinus Torvalds } 3501da177e4SLinus Torvalds 3515ddbc77cSDmitry Torokhov 3525ddbc77cSDmitry Torokhov /* 3535ddbc77cSDmitry Torokhov * i8042_aux_close attempts to clear AUX or KBD port state by disabling 3545ddbc77cSDmitry Torokhov * and then re-enabling it. 3555ddbc77cSDmitry Torokhov */ 3565ddbc77cSDmitry Torokhov 3575ddbc77cSDmitry Torokhov static void i8042_port_close(struct serio *serio) 3585ddbc77cSDmitry Torokhov { 3595ddbc77cSDmitry Torokhov int irq_bit; 3605ddbc77cSDmitry Torokhov int disable_bit; 3615ddbc77cSDmitry Torokhov const char *port_name; 3625ddbc77cSDmitry Torokhov 3635ddbc77cSDmitry Torokhov if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { 3645ddbc77cSDmitry Torokhov irq_bit = I8042_CTR_AUXINT; 3655ddbc77cSDmitry Torokhov disable_bit = I8042_CTR_AUXDIS; 3665ddbc77cSDmitry Torokhov port_name = "AUX"; 3675ddbc77cSDmitry Torokhov } else { 3685ddbc77cSDmitry Torokhov irq_bit = I8042_CTR_KBDINT; 3695ddbc77cSDmitry Torokhov disable_bit = I8042_CTR_KBDDIS; 3705ddbc77cSDmitry Torokhov port_name = "KBD"; 3715ddbc77cSDmitry Torokhov } 3725ddbc77cSDmitry Torokhov 3735ddbc77cSDmitry Torokhov i8042_ctr &= ~irq_bit; 3745ddbc77cSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 3754eb3c30bSJoe Perches pr_warn("Can't write CTR while closing %s port\n", port_name); 3765ddbc77cSDmitry Torokhov 3775ddbc77cSDmitry Torokhov udelay(50); 3785ddbc77cSDmitry Torokhov 3795ddbc77cSDmitry Torokhov i8042_ctr &= ~disable_bit; 3805ddbc77cSDmitry Torokhov i8042_ctr |= irq_bit; 3815ddbc77cSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 3824eb3c30bSJoe Perches pr_err("Can't reactivate %s port\n", port_name); 3835ddbc77cSDmitry Torokhov 3845ddbc77cSDmitry Torokhov /* 3855ddbc77cSDmitry Torokhov * See if there is any data appeared while we were messing with 3865ddbc77cSDmitry Torokhov * port state. 3875ddbc77cSDmitry Torokhov */ 3885ddbc77cSDmitry Torokhov i8042_interrupt(0, NULL); 3895ddbc77cSDmitry Torokhov } 3905ddbc77cSDmitry Torokhov 3911da177e4SLinus Torvalds /* 3921da177e4SLinus Torvalds * i8042_start() is called by serio core when port is about to finish 3931da177e4SLinus Torvalds * registering. It will mark port as existing so i8042_interrupt can 3941da177e4SLinus Torvalds * start sending data through it. 3951da177e4SLinus Torvalds */ 3961da177e4SLinus Torvalds static int i8042_start(struct serio *serio) 3971da177e4SLinus Torvalds { 3981da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 3991da177e4SLinus Torvalds 400386b3849SDmitry Torokhov port->exists = true; 4011da177e4SLinus Torvalds mb(); 4021da177e4SLinus Torvalds return 0; 4031da177e4SLinus Torvalds } 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds /* 4061da177e4SLinus Torvalds * i8042_stop() marks serio port as non-existing so i8042_interrupt 4071da177e4SLinus Torvalds * will not try to send data to the port that is about to go away. 4081da177e4SLinus Torvalds * The function is called by serio core as part of unregister procedure. 4091da177e4SLinus Torvalds */ 4101da177e4SLinus Torvalds static void i8042_stop(struct serio *serio) 4111da177e4SLinus Torvalds { 4121da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 4131da177e4SLinus Torvalds 414386b3849SDmitry Torokhov port->exists = false; 415a8399c51SDmitry Torokhov 416a8399c51SDmitry Torokhov /* 417a8399c51SDmitry Torokhov * We synchronize with both AUX and KBD IRQs because there is 418a8399c51SDmitry Torokhov * a (very unlikely) chance that AUX IRQ is raised for KBD port 419a8399c51SDmitry Torokhov * and vice versa. 420a8399c51SDmitry Torokhov */ 421a8399c51SDmitry Torokhov synchronize_irq(I8042_AUX_IRQ); 422a8399c51SDmitry Torokhov synchronize_irq(I8042_KBD_IRQ); 4231da177e4SLinus Torvalds port->serio = NULL; 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds /* 4274e8d340dSDmitry Torokhov * i8042_filter() filters out unwanted bytes from the input data stream. 4284e8d340dSDmitry Torokhov * It is called from i8042_interrupt and thus is running with interrupts 4294e8d340dSDmitry Torokhov * off and i8042_lock held. 4304e8d340dSDmitry Torokhov */ 431967c9ef9SMatthew Garrett static bool i8042_filter(unsigned char data, unsigned char str, 432967c9ef9SMatthew Garrett struct serio *serio) 4334e8d340dSDmitry Torokhov { 4344e8d340dSDmitry Torokhov if (unlikely(i8042_suppress_kbd_ack)) { 4354e8d340dSDmitry Torokhov if ((~str & I8042_STR_AUXDATA) && 4364e8d340dSDmitry Torokhov (data == 0xfa || data == 0xfe)) { 4374e8d340dSDmitry Torokhov i8042_suppress_kbd_ack--; 4384e8d340dSDmitry Torokhov dbg("Extra keyboard ACK - filtered out\n"); 4394e8d340dSDmitry Torokhov return true; 4404e8d340dSDmitry Torokhov } 4414e8d340dSDmitry Torokhov } 4424e8d340dSDmitry Torokhov 443967c9ef9SMatthew Garrett if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { 4440747e3bcSStefan Weil dbg("Filtered out by platform filter\n"); 445967c9ef9SMatthew Garrett return true; 446967c9ef9SMatthew Garrett } 447967c9ef9SMatthew Garrett 4484e8d340dSDmitry Torokhov return false; 4494e8d340dSDmitry Torokhov } 4504e8d340dSDmitry Torokhov 4514e8d340dSDmitry Torokhov /* 4521da177e4SLinus Torvalds * i8042_interrupt() is the most important function in this driver - 4531da177e4SLinus Torvalds * it handles the interrupts from the i8042, and sends incoming bytes 4541da177e4SLinus Torvalds * to the upper layers. 4551da177e4SLinus Torvalds */ 4561da177e4SLinus Torvalds 4577d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id) 4581da177e4SLinus Torvalds { 4591da177e4SLinus Torvalds struct i8042_port *port; 460967c9ef9SMatthew Garrett struct serio *serio; 4611da177e4SLinus Torvalds unsigned long flags; 4621da177e4SLinus Torvalds unsigned char str, data; 4631da177e4SLinus Torvalds unsigned int dfl; 4641da177e4SLinus Torvalds unsigned int port_no; 4654e8d340dSDmitry Torokhov bool filtered; 466817e6ba3SDmitry Torokhov int ret = 1; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 4694e8d340dSDmitry Torokhov 4701da177e4SLinus Torvalds str = i8042_read_status(); 4711da177e4SLinus Torvalds if (unlikely(~str & I8042_STR_OBF)) { 4721da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 4734eb3c30bSJoe Perches if (irq) 4744eb3c30bSJoe Perches dbg("Interrupt %d, without any data\n", irq); 4751da177e4SLinus Torvalds ret = 0; 4761da177e4SLinus Torvalds goto out; 4771da177e4SLinus Torvalds } 4784e8d340dSDmitry Torokhov 4791da177e4SLinus Torvalds data = i8042_read_data(); 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 4821da177e4SLinus Torvalds static unsigned long last_transmit; 4831da177e4SLinus Torvalds static unsigned char last_str; 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds dfl = 0; 4861da177e4SLinus Torvalds if (str & I8042_STR_MUXERR) { 4874eb3c30bSJoe Perches dbg("MUX error, status is %02x, data is %02x\n", 4884eb3c30bSJoe Perches str, data); 4891da177e4SLinus Torvalds /* 4901da177e4SLinus Torvalds * When MUXERR condition is signalled the data register can only contain 4911da177e4SLinus Torvalds * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately 492a216a4b6SDmitry Torokhov * it is not always the case. Some KBCs also report 0xfc when there is 493a216a4b6SDmitry Torokhov * nothing connected to the port while others sometimes get confused which 494a216a4b6SDmitry Torokhov * port the data came from and signal error leaving the data intact. They 495a216a4b6SDmitry Torokhov * _do not_ revert to legacy mode (actually I've never seen KBC reverting 496a216a4b6SDmitry Torokhov * to legacy mode yet, when we see one we'll add proper handling). 497a216a4b6SDmitry Torokhov * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the 498a216a4b6SDmitry Torokhov * rest assume that the data came from the same serio last byte 4991da177e4SLinus Torvalds * was transmitted (if transmission happened not too long ago). 5001da177e4SLinus Torvalds */ 501a216a4b6SDmitry Torokhov 502a216a4b6SDmitry Torokhov switch (data) { 503a216a4b6SDmitry Torokhov default: 5041da177e4SLinus Torvalds if (time_before(jiffies, last_transmit + HZ/10)) { 5051da177e4SLinus Torvalds str = last_str; 5061da177e4SLinus Torvalds break; 5071da177e4SLinus Torvalds } 5081da177e4SLinus Torvalds /* fall through - report timeout */ 509a216a4b6SDmitry Torokhov case 0xfc: 5101da177e4SLinus Torvalds case 0xfd: 5111da177e4SLinus Torvalds case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; 5121da177e4SLinus Torvalds case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); 5171da177e4SLinus Torvalds last_str = str; 5181da177e4SLinus Torvalds last_transmit = jiffies; 5191da177e4SLinus Torvalds } else { 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | 522f8313ef1SJiri Kosina ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds port_no = (str & I8042_STR_AUXDATA) ? 5251da177e4SLinus Torvalds I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds port = &i8042_ports[port_no]; 529967c9ef9SMatthew Garrett serio = port->exists ? port->serio : NULL; 5301da177e4SLinus Torvalds 5314eb3c30bSJoe Perches dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n", 532de9ce703SDmitry Torokhov data, port_no, irq, 5331da177e4SLinus Torvalds dfl & SERIO_PARITY ? ", bad parity" : "", 5341da177e4SLinus Torvalds dfl & SERIO_TIMEOUT ? ", timeout" : ""); 5351da177e4SLinus Torvalds 536967c9ef9SMatthew Garrett filtered = i8042_filter(data, str, serio); 537817e6ba3SDmitry Torokhov 5384e8d340dSDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 5394e8d340dSDmitry Torokhov 5404e8d340dSDmitry Torokhov if (likely(port->exists && !filtered)) 541967c9ef9SMatthew Garrett serio_interrupt(serio, data, dfl); 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds out: 5441da177e4SLinus Torvalds return IRQ_RETVAL(ret); 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds /* 5485ddbc77cSDmitry Torokhov * i8042_enable_kbd_port enables keyboard port on chip 549de9ce703SDmitry Torokhov */ 550de9ce703SDmitry Torokhov 551de9ce703SDmitry Torokhov static int i8042_enable_kbd_port(void) 552de9ce703SDmitry Torokhov { 553de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_KBDDIS; 554de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_KBDINT; 555de9ce703SDmitry Torokhov 556de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 557018db6bbSMarkus Armbruster i8042_ctr &= ~I8042_CTR_KBDINT; 558018db6bbSMarkus Armbruster i8042_ctr |= I8042_CTR_KBDDIS; 5594eb3c30bSJoe Perches pr_err("Failed to enable KBD port\n"); 560de9ce703SDmitry Torokhov return -EIO; 561de9ce703SDmitry Torokhov } 562de9ce703SDmitry Torokhov 563de9ce703SDmitry Torokhov return 0; 564de9ce703SDmitry Torokhov } 565de9ce703SDmitry Torokhov 566de9ce703SDmitry Torokhov /* 567de9ce703SDmitry Torokhov * i8042_enable_aux_port enables AUX (mouse) port on chip 568de9ce703SDmitry Torokhov */ 569de9ce703SDmitry Torokhov 570de9ce703SDmitry Torokhov static int i8042_enable_aux_port(void) 571de9ce703SDmitry Torokhov { 572de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXDIS; 573de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXINT; 574de9ce703SDmitry Torokhov 575de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 576018db6bbSMarkus Armbruster i8042_ctr &= ~I8042_CTR_AUXINT; 577018db6bbSMarkus Armbruster i8042_ctr |= I8042_CTR_AUXDIS; 5784eb3c30bSJoe Perches pr_err("Failed to enable AUX port\n"); 579de9ce703SDmitry Torokhov return -EIO; 580de9ce703SDmitry Torokhov } 581de9ce703SDmitry Torokhov 582de9ce703SDmitry Torokhov return 0; 583de9ce703SDmitry Torokhov } 584de9ce703SDmitry Torokhov 585de9ce703SDmitry Torokhov /* 586de9ce703SDmitry Torokhov * i8042_enable_mux_ports enables 4 individual AUX ports after 587de9ce703SDmitry Torokhov * the controller has been switched into Multiplexed mode 588de9ce703SDmitry Torokhov */ 589de9ce703SDmitry Torokhov 590de9ce703SDmitry Torokhov static int i8042_enable_mux_ports(void) 591de9ce703SDmitry Torokhov { 592de9ce703SDmitry Torokhov unsigned char param; 593de9ce703SDmitry Torokhov int i; 594de9ce703SDmitry Torokhov 595de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 596de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_MUX_PFX + i); 597de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_AUX_ENABLE); 598de9ce703SDmitry Torokhov } 599de9ce703SDmitry Torokhov 600de9ce703SDmitry Torokhov return i8042_enable_aux_port(); 601de9ce703SDmitry Torokhov } 602de9ce703SDmitry Torokhov 603de9ce703SDmitry Torokhov /* 604386b3849SDmitry Torokhov * i8042_set_mux_mode checks whether the controller has an 605386b3849SDmitry Torokhov * active multiplexor and puts the chip into Multiplexed (true) 606386b3849SDmitry Torokhov * or Legacy (false) mode. 6071da177e4SLinus Torvalds */ 6081da177e4SLinus Torvalds 609386b3849SDmitry Torokhov static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) 6101da177e4SLinus Torvalds { 6111da177e4SLinus Torvalds 612386b3849SDmitry Torokhov unsigned char param, val; 6131da177e4SLinus Torvalds /* 6141da177e4SLinus Torvalds * Get rid of bytes in the queue. 6151da177e4SLinus Torvalds */ 6161da177e4SLinus Torvalds 6171da177e4SLinus Torvalds i8042_flush(); 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds /* 6201da177e4SLinus Torvalds * Internal loopback test - send three bytes, they should come back from the 621de9ce703SDmitry Torokhov * mouse interface, the last should be version. 6221da177e4SLinus Torvalds */ 6231da177e4SLinus Torvalds 624386b3849SDmitry Torokhov param = val = 0xf0; 625386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) 6261da177e4SLinus Torvalds return -1; 627386b3849SDmitry Torokhov param = val = multiplex ? 0x56 : 0xf6; 628386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) 6291da177e4SLinus Torvalds return -1; 630386b3849SDmitry Torokhov param = val = multiplex ? 0xa4 : 0xa5; 631386b3849SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) 632386b3849SDmitry Torokhov return -1; 633386b3849SDmitry Torokhov 634386b3849SDmitry Torokhov /* 635386b3849SDmitry Torokhov * Workaround for interference with USB Legacy emulation 636386b3849SDmitry Torokhov * that causes a v10.12 MUX to be found. 637386b3849SDmitry Torokhov */ 638386b3849SDmitry Torokhov if (param == 0xac) 6391da177e4SLinus Torvalds return -1; 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds if (mux_version) 642463a4f76SDmitry Torokhov *mux_version = param; 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds return 0; 6451da177e4SLinus Torvalds } 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds /* 6481da177e4SLinus Torvalds * i8042_check_mux() checks whether the controller supports the PS/2 Active 6491da177e4SLinus Torvalds * Multiplexing specification by Synaptics, Phoenix, Insyde and 6501da177e4SLinus Torvalds * LCS/Telegraphics. 6511da177e4SLinus Torvalds */ 6521da177e4SLinus Torvalds 653f8113416SDmitry Torokhov static int __init i8042_check_mux(void) 6541da177e4SLinus Torvalds { 6551da177e4SLinus Torvalds unsigned char mux_version; 6561da177e4SLinus Torvalds 657386b3849SDmitry Torokhov if (i8042_set_mux_mode(true, &mux_version)) 6581da177e4SLinus Torvalds return -1; 6591da177e4SLinus Torvalds 6604eb3c30bSJoe Perches pr_info("Detected active multiplexing controller, rev %d.%d\n", 6611da177e4SLinus Torvalds (mux_version >> 4) & 0xf, mux_version & 0xf); 6621da177e4SLinus Torvalds 663de9ce703SDmitry Torokhov /* 664de9ce703SDmitry Torokhov * Disable all muxed ports by disabling AUX. 665de9ce703SDmitry Torokhov */ 666de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS; 667de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXINT; 668de9ce703SDmitry Torokhov 669de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 6704eb3c30bSJoe Perches pr_err("Failed to disable AUX port, can't use MUX\n"); 671de9ce703SDmitry Torokhov return -EIO; 672de9ce703SDmitry Torokhov } 6731da177e4SLinus Torvalds 674386b3849SDmitry Torokhov i8042_mux_present = true; 675de9ce703SDmitry Torokhov 6761da177e4SLinus Torvalds return 0; 6771da177e4SLinus Torvalds } 6781da177e4SLinus Torvalds 679de9ce703SDmitry Torokhov /* 680de9ce703SDmitry Torokhov * The following is used to test AUX IRQ delivery. 681de9ce703SDmitry Torokhov */ 682f8113416SDmitry Torokhov static struct completion i8042_aux_irq_delivered __initdata; 683f8113416SDmitry Torokhov static bool i8042_irq_being_tested __initdata; 684de9ce703SDmitry Torokhov 685f8113416SDmitry Torokhov static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) 686de9ce703SDmitry Torokhov { 687de9ce703SDmitry Torokhov unsigned long flags; 688de9ce703SDmitry Torokhov unsigned char str, data; 689e3758b2aSFernando Luis Vázquez Cao int ret = 0; 690de9ce703SDmitry Torokhov 691de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 692de9ce703SDmitry Torokhov str = i8042_read_status(); 693de9ce703SDmitry Torokhov if (str & I8042_STR_OBF) { 694de9ce703SDmitry Torokhov data = i8042_read_data(); 6954eb3c30bSJoe Perches dbg("%02x <- i8042 (aux_test_irq, %s)\n", 696d3d2dfe2SDmitry Torokhov data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 697de9ce703SDmitry Torokhov if (i8042_irq_being_tested && 698de9ce703SDmitry Torokhov data == 0xa5 && (str & I8042_STR_AUXDATA)) 699de9ce703SDmitry Torokhov complete(&i8042_aux_irq_delivered); 700e3758b2aSFernando Luis Vázquez Cao ret = 1; 701de9ce703SDmitry Torokhov } 702de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 703de9ce703SDmitry Torokhov 704e3758b2aSFernando Luis Vázquez Cao return IRQ_RETVAL(ret); 705de9ce703SDmitry Torokhov } 706de9ce703SDmitry Torokhov 707d2ada559SRoland Scheidegger /* 708d2ada559SRoland Scheidegger * i8042_toggle_aux - enables or disables AUX port on i8042 via command and 709d2ada559SRoland Scheidegger * verifies success by readinng CTR. Used when testing for presence of AUX 710d2ada559SRoland Scheidegger * port. 711d2ada559SRoland Scheidegger */ 712f8113416SDmitry Torokhov static int __init i8042_toggle_aux(bool on) 713d2ada559SRoland Scheidegger { 714d2ada559SRoland Scheidegger unsigned char param; 715d2ada559SRoland Scheidegger int i; 716d2ada559SRoland Scheidegger 717d2ada559SRoland Scheidegger if (i8042_command(¶m, 718d2ada559SRoland Scheidegger on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE)) 719d2ada559SRoland Scheidegger return -1; 720d2ada559SRoland Scheidegger 721d2ada559SRoland Scheidegger /* some chips need some time to set the I8042_CTR_AUXDIS bit */ 722d2ada559SRoland Scheidegger for (i = 0; i < 100; i++) { 723d2ada559SRoland Scheidegger udelay(50); 724d2ada559SRoland Scheidegger 725d2ada559SRoland Scheidegger if (i8042_command(¶m, I8042_CMD_CTL_RCTR)) 726d2ada559SRoland Scheidegger return -1; 727d2ada559SRoland Scheidegger 728d2ada559SRoland Scheidegger if (!(param & I8042_CTR_AUXDIS) == on) 729d2ada559SRoland Scheidegger return 0; 730d2ada559SRoland Scheidegger } 731d2ada559SRoland Scheidegger 732d2ada559SRoland Scheidegger return -1; 733d2ada559SRoland Scheidegger } 7341da177e4SLinus Torvalds 7351da177e4SLinus Torvalds /* 7361da177e4SLinus Torvalds * i8042_check_aux() applies as much paranoia as it can at detecting 7371da177e4SLinus Torvalds * the presence of an AUX interface. 7381da177e4SLinus Torvalds */ 7391da177e4SLinus Torvalds 740f8113416SDmitry Torokhov static int __init i8042_check_aux(void) 7411da177e4SLinus Torvalds { 742de9ce703SDmitry Torokhov int retval = -1; 743386b3849SDmitry Torokhov bool irq_registered = false; 744386b3849SDmitry Torokhov bool aux_loop_broken = false; 745de9ce703SDmitry Torokhov unsigned long flags; 7461da177e4SLinus Torvalds unsigned char param; 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds /* 7491da177e4SLinus Torvalds * Get rid of bytes in the queue. 7501da177e4SLinus Torvalds */ 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds i8042_flush(); 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds /* 7551da177e4SLinus Torvalds * Internal loopback test - filters out AT-type i8042's. Unfortunately 7561da177e4SLinus Torvalds * SiS screwed up and their 5597 doesn't support the LOOP command even 7571da177e4SLinus Torvalds * though it has an AUX port. 7581da177e4SLinus Torvalds */ 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds param = 0x5a; 7613ca5de6dSDmitry Torokhov retval = i8042_command(¶m, I8042_CMD_AUX_LOOP); 7623ca5de6dSDmitry Torokhov if (retval || param != 0x5a) { 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds /* 7651da177e4SLinus Torvalds * External connection test - filters out AT-soldered PS/2 i8042's 7661da177e4SLinus Torvalds * 0x00 - no error, 0x01-0x03 - clock/data stuck, 0xff - general error 7671da177e4SLinus Torvalds * 0xfa - no error on some notebooks which ignore the spec 7681da177e4SLinus Torvalds * Because it's common for chipsets to return error on perfectly functioning 7691da177e4SLinus Torvalds * AUX ports, we test for this only when the LOOP command failed. 7701da177e4SLinus Torvalds */ 7711da177e4SLinus Torvalds 772de9ce703SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_TEST) || 773de9ce703SDmitry Torokhov (param && param != 0xfa && param != 0xff)) 7741da177e4SLinus Torvalds return -1; 7751e4865f8SDmitry Torokhov 7763ca5de6dSDmitry Torokhov /* 7773ca5de6dSDmitry Torokhov * If AUX_LOOP completed without error but returned unexpected data 7783ca5de6dSDmitry Torokhov * mark it as broken 7793ca5de6dSDmitry Torokhov */ 7803ca5de6dSDmitry Torokhov if (!retval) 781386b3849SDmitry Torokhov aux_loop_broken = true; 7821da177e4SLinus Torvalds } 7831da177e4SLinus Torvalds 7841da177e4SLinus Torvalds /* 7851da177e4SLinus Torvalds * Bit assignment test - filters out PS/2 i8042's in AT mode 7861da177e4SLinus Torvalds */ 7871da177e4SLinus Torvalds 788386b3849SDmitry Torokhov if (i8042_toggle_aux(false)) { 7894eb3c30bSJoe Perches pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); 7904eb3c30bSJoe Perches pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n"); 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds 793386b3849SDmitry Torokhov if (i8042_toggle_aux(true)) 7941da177e4SLinus Torvalds return -1; 7951da177e4SLinus Torvalds 7961da177e4SLinus Torvalds /* 797148e9a71SSrihari Vijayaraghavan * Reset keyboard (needed on some laptops to successfully detect 798148e9a71SSrihari Vijayaraghavan * touchpad, e.g., some Gigabyte laptop models with Elantech 799148e9a71SSrihari Vijayaraghavan * touchpads). 800148e9a71SSrihari Vijayaraghavan */ 801148e9a71SSrihari Vijayaraghavan if (i8042_kbdreset) { 802148e9a71SSrihari Vijayaraghavan pr_warn("Attempting to reset device connected to KBD port\n"); 803148e9a71SSrihari Vijayaraghavan i8042_kbd_write(NULL, (unsigned char) 0xff); 804148e9a71SSrihari Vijayaraghavan } 805148e9a71SSrihari Vijayaraghavan 806148e9a71SSrihari Vijayaraghavan /* 807de9ce703SDmitry Torokhov * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and 808de9ce703SDmitry Torokhov * used it for a PCI card or somethig else. 809de9ce703SDmitry Torokhov */ 810de9ce703SDmitry Torokhov 8111c7827aeSDmitry Torokhov if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { 812de9ce703SDmitry Torokhov /* 813de9ce703SDmitry Torokhov * Without LOOP command we can't test AUX IRQ delivery. Assume the port 814de9ce703SDmitry Torokhov * is working and hope we are right. 815de9ce703SDmitry Torokhov */ 816de9ce703SDmitry Torokhov retval = 0; 817de9ce703SDmitry Torokhov goto out; 818de9ce703SDmitry Torokhov } 819de9ce703SDmitry Torokhov 820de9ce703SDmitry Torokhov if (request_irq(I8042_AUX_IRQ, i8042_aux_test_irq, IRQF_SHARED, 821de9ce703SDmitry Torokhov "i8042", i8042_platform_device)) 822de9ce703SDmitry Torokhov goto out; 823de9ce703SDmitry Torokhov 824386b3849SDmitry Torokhov irq_registered = true; 825de9ce703SDmitry Torokhov 826de9ce703SDmitry Torokhov if (i8042_enable_aux_port()) 827de9ce703SDmitry Torokhov goto out; 828de9ce703SDmitry Torokhov 829de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 830de9ce703SDmitry Torokhov 831de9ce703SDmitry Torokhov init_completion(&i8042_aux_irq_delivered); 832386b3849SDmitry Torokhov i8042_irq_being_tested = true; 833de9ce703SDmitry Torokhov 834de9ce703SDmitry Torokhov param = 0xa5; 835de9ce703SDmitry Torokhov retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); 836de9ce703SDmitry Torokhov 837de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 838de9ce703SDmitry Torokhov 839de9ce703SDmitry Torokhov if (retval) 840de9ce703SDmitry Torokhov goto out; 841de9ce703SDmitry Torokhov 842de9ce703SDmitry Torokhov if (wait_for_completion_timeout(&i8042_aux_irq_delivered, 843de9ce703SDmitry Torokhov msecs_to_jiffies(250)) == 0) { 844de9ce703SDmitry Torokhov /* 845de9ce703SDmitry Torokhov * AUX IRQ was never delivered so we need to flush the controller to 846de9ce703SDmitry Torokhov * get rid of the byte we put there; otherwise keyboard may not work. 847de9ce703SDmitry Torokhov */ 8484eb3c30bSJoe Perches dbg(" -- i8042 (aux irq test timeout)\n"); 849de9ce703SDmitry Torokhov i8042_flush(); 850de9ce703SDmitry Torokhov retval = -1; 851de9ce703SDmitry Torokhov } 852de9ce703SDmitry Torokhov 853de9ce703SDmitry Torokhov out: 854de9ce703SDmitry Torokhov 855de9ce703SDmitry Torokhov /* 8561da177e4SLinus Torvalds * Disable the interface. 8571da177e4SLinus Torvalds */ 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_AUXDIS; 8601da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_AUXINT; 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 863de9ce703SDmitry Torokhov retval = -1; 864de9ce703SDmitry Torokhov 865de9ce703SDmitry Torokhov if (irq_registered) 866de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 867de9ce703SDmitry Torokhov 868de9ce703SDmitry Torokhov return retval; 869de9ce703SDmitry Torokhov } 870de9ce703SDmitry Torokhov 871de9ce703SDmitry Torokhov static int i8042_controller_check(void) 872de9ce703SDmitry Torokhov { 8732f0d2604SAndrey Moiseev if (i8042_flush()) { 8744eb3c30bSJoe Perches pr_err("No controller found\n"); 875de9ce703SDmitry Torokhov return -ENODEV; 876de9ce703SDmitry Torokhov } 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds return 0; 8791da177e4SLinus Torvalds } 8801da177e4SLinus Torvalds 881de9ce703SDmitry Torokhov static int i8042_controller_selftest(void) 8822673c836SVojtech Pavlik { 8832673c836SVojtech Pavlik unsigned char param; 8845ea2fc64SArjan van de Ven int i = 0; 8852673c836SVojtech Pavlik 8865ea2fc64SArjan van de Ven /* 8875ea2fc64SArjan van de Ven * We try this 5 times; on some really fragile systems this does not 8885ea2fc64SArjan van de Ven * take the first time... 8895ea2fc64SArjan van de Ven */ 8905ea2fc64SArjan van de Ven do { 8915ea2fc64SArjan van de Ven 8922673c836SVojtech Pavlik if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { 8934eb3c30bSJoe Perches pr_err("i8042 controller selftest timeout\n"); 894de9ce703SDmitry Torokhov return -ENODEV; 8952673c836SVojtech Pavlik } 8962673c836SVojtech Pavlik 8975ea2fc64SArjan van de Ven if (param == I8042_RET_CTL_TEST) 8985ea2fc64SArjan van de Ven return 0; 8995ea2fc64SArjan van de Ven 900a2a94e73SPaul Bolle dbg("i8042 controller selftest: %#x != %#x\n", 9012673c836SVojtech Pavlik param, I8042_RET_CTL_TEST); 9025ea2fc64SArjan van de Ven msleep(50); 9035ea2fc64SArjan van de Ven } while (i++ < 5); 9042673c836SVojtech Pavlik 9055ea2fc64SArjan van de Ven #ifdef CONFIG_X86 9065ea2fc64SArjan van de Ven /* 9075ea2fc64SArjan van de Ven * On x86, we don't fail entire i8042 initialization if controller 9085ea2fc64SArjan van de Ven * reset fails in hopes that keyboard port will still be functional 9095ea2fc64SArjan van de Ven * and user will still get a working keyboard. This is especially 9105ea2fc64SArjan van de Ven * important on netbooks. On other arches we trust hardware more. 9115ea2fc64SArjan van de Ven */ 9124eb3c30bSJoe Perches pr_info("giving up on controller selftest, continuing anyway...\n"); 9132673c836SVojtech Pavlik return 0; 9145ea2fc64SArjan van de Ven #else 915a2a94e73SPaul Bolle pr_err("i8042 controller selftest failed\n"); 9165ea2fc64SArjan van de Ven return -EIO; 9175ea2fc64SArjan van de Ven #endif 9182673c836SVojtech Pavlik } 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds /* 9211da177e4SLinus Torvalds * i8042_controller init initializes the i8042 controller, and, 9221da177e4SLinus Torvalds * most importantly, sets it into non-xlated mode if that's 9231da177e4SLinus Torvalds * desired. 9241da177e4SLinus Torvalds */ 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds static int i8042_controller_init(void) 9271da177e4SLinus Torvalds { 9281da177e4SLinus Torvalds unsigned long flags; 929ee1e82ceSDmitry Torokhov int n = 0; 930ee1e82ceSDmitry Torokhov unsigned char ctr[2]; 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds /* 933ee1e82ceSDmitry Torokhov * Save the CTR for restore on unload / reboot. 9341da177e4SLinus Torvalds */ 9351da177e4SLinus Torvalds 936ee1e82ceSDmitry Torokhov do { 937ee1e82ceSDmitry Torokhov if (n >= 10) { 9384eb3c30bSJoe Perches pr_err("Unable to get stable CTR read\n"); 939de9ce703SDmitry Torokhov return -EIO; 9401da177e4SLinus Torvalds } 9411da177e4SLinus Torvalds 942ee1e82ceSDmitry Torokhov if (n != 0) 943ee1e82ceSDmitry Torokhov udelay(50); 944ee1e82ceSDmitry Torokhov 945ee1e82ceSDmitry Torokhov if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { 9464eb3c30bSJoe Perches pr_err("Can't read CTR while initializing i8042\n"); 947ee1e82ceSDmitry Torokhov return -EIO; 948ee1e82ceSDmitry Torokhov } 949ee1e82ceSDmitry Torokhov 950ee1e82ceSDmitry Torokhov } while (n < 2 || ctr[0] != ctr[1]); 951ee1e82ceSDmitry Torokhov 952ee1e82ceSDmitry Torokhov i8042_initial_ctr = i8042_ctr = ctr[0]; 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds /* 9551da177e4SLinus Torvalds * Disable the keyboard interface and interrupt. 9561da177e4SLinus Torvalds */ 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_KBDDIS; 9591da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_KBDINT; 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds /* 9621da177e4SLinus Torvalds * Handle keylock. 9631da177e4SLinus Torvalds */ 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 9661da177e4SLinus Torvalds if (~i8042_read_status() & I8042_STR_KEYLOCK) { 9671da177e4SLinus Torvalds if (i8042_unlock) 9681da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_IGNKEYLOCK; 9691da177e4SLinus Torvalds else 9704eb3c30bSJoe Perches pr_warn("Warning: Keylock active\n"); 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds /* 9751da177e4SLinus Torvalds * If the chip is configured into nontranslated mode by the BIOS, don't 9761da177e4SLinus Torvalds * bother enabling translating and be happy. 9771da177e4SLinus Torvalds */ 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds if (~i8042_ctr & I8042_CTR_XLATE) 980386b3849SDmitry Torokhov i8042_direct = true; 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds /* 9831da177e4SLinus Torvalds * Set nontranslated mode for the kbd interface if requested by an option. 9841da177e4SLinus Torvalds * After this the kbd interface becomes a simple serial in/out, like the aux 9851da177e4SLinus Torvalds * interface is. We don't do this by default, since it can confuse notebook 9861da177e4SLinus Torvalds * BIOSes. 9871da177e4SLinus Torvalds */ 9881da177e4SLinus Torvalds 9891da177e4SLinus Torvalds if (i8042_direct) 9901da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_XLATE; 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds /* 9931da177e4SLinus Torvalds * Write CTR back. 9941da177e4SLinus Torvalds */ 9951da177e4SLinus Torvalds 9961da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 9974eb3c30bSJoe Perches pr_err("Can't write CTR while initializing i8042\n"); 998de9ce703SDmitry Torokhov return -EIO; 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds 1001ee1e82ceSDmitry Torokhov /* 1002ee1e82ceSDmitry Torokhov * Flush whatever accumulated while we were disabling keyboard port. 1003ee1e82ceSDmitry Torokhov */ 1004ee1e82ceSDmitry Torokhov 1005ee1e82ceSDmitry Torokhov i8042_flush(); 1006ee1e82ceSDmitry Torokhov 10071da177e4SLinus Torvalds return 0; 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds /* 1012de9ce703SDmitry Torokhov * Reset the controller and reset CRT to the original value set by BIOS. 10131da177e4SLinus Torvalds */ 10141da177e4SLinus Torvalds 10151729ad1fSDmitry Torokhov static void i8042_controller_reset(bool force_reset) 1016de9ce703SDmitry Torokhov { 1017de9ce703SDmitry Torokhov i8042_flush(); 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds /* 10208d04ddb6SDmitry Torokhov * Disable both KBD and AUX interfaces so they don't get in the way 10218d04ddb6SDmitry Torokhov */ 10228d04ddb6SDmitry Torokhov 10238d04ddb6SDmitry Torokhov i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; 10248d04ddb6SDmitry Torokhov i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); 10258d04ddb6SDmitry Torokhov 1026ee1e82ceSDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 10274eb3c30bSJoe Perches pr_warn("Can't write CTR while resetting\n"); 10285ddbc77cSDmitry Torokhov 10298d04ddb6SDmitry Torokhov /* 10301da177e4SLinus Torvalds * Disable MUX mode if present. 10311da177e4SLinus Torvalds */ 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds if (i8042_mux_present) 1034386b3849SDmitry Torokhov i8042_set_mux_mode(false, NULL); 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds /* 1037de9ce703SDmitry Torokhov * Reset the controller if requested. 1038de9ce703SDmitry Torokhov */ 1039de9ce703SDmitry Torokhov 10401729ad1fSDmitry Torokhov if (i8042_reset || force_reset) 1041de9ce703SDmitry Torokhov i8042_controller_selftest(); 1042de9ce703SDmitry Torokhov 1043de9ce703SDmitry Torokhov /* 10441da177e4SLinus Torvalds * Restore the original control register setting. 10451da177e4SLinus Torvalds */ 10461da177e4SLinus Torvalds 1047de9ce703SDmitry Torokhov if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) 10484eb3c30bSJoe Perches pr_warn("Can't restore CTR\n"); 10491da177e4SLinus Torvalds } 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds 10521da177e4SLinus Torvalds /* 1053c7ff0d9cSTAMUKI Shoichi * i8042_panic_blink() will turn the keyboard LEDs on or off and is called 1054c7ff0d9cSTAMUKI Shoichi * when kernel panics. Flashing LEDs is useful for users running X who may 1055aa5e5dc2SMichael Opdenacker * not see the console and will help distinguishing panics from "real" 10561da177e4SLinus Torvalds * lockups. 10571da177e4SLinus Torvalds * 10581da177e4SLinus Torvalds * Note that DELAY has a limit of 10ms so we will not get stuck here 10591da177e4SLinus Torvalds * waiting for KBC to free up even if KBD interrupt is off 10601da177e4SLinus Torvalds */ 10611da177e4SLinus Torvalds 10621da177e4SLinus Torvalds #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) 10631da177e4SLinus Torvalds 1064c7ff0d9cSTAMUKI Shoichi static long i8042_panic_blink(int state) 10651da177e4SLinus Torvalds { 10661da177e4SLinus Torvalds long delay = 0; 1067c7ff0d9cSTAMUKI Shoichi char led; 10681da177e4SLinus Torvalds 1069c7ff0d9cSTAMUKI Shoichi led = (state) ? 0x01 | 0x04 : 0; 10701da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 10711da177e4SLinus Torvalds DELAY; 10724eb3c30bSJoe Perches dbg("%02x -> i8042 (panic blink)\n", 0xed); 107319f3c3e3SDmitry Torokhov i8042_suppress_kbd_ack = 2; 10741da177e4SLinus Torvalds i8042_write_data(0xed); /* set leds */ 10751da177e4SLinus Torvalds DELAY; 10761da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 10771da177e4SLinus Torvalds DELAY; 10781da177e4SLinus Torvalds DELAY; 10794eb3c30bSJoe Perches dbg("%02x -> i8042 (panic blink)\n", led); 10801da177e4SLinus Torvalds i8042_write_data(led); 10811da177e4SLinus Torvalds DELAY; 10821da177e4SLinus Torvalds return delay; 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 10851da177e4SLinus Torvalds #undef DELAY 10861da177e4SLinus Torvalds 1087d35895dbSBruno Prémont #ifdef CONFIG_X86 1088d35895dbSBruno Prémont static void i8042_dritek_enable(void) 1089d35895dbSBruno Prémont { 1090594d6363SChristoph Fritz unsigned char param = 0x90; 1091d35895dbSBruno Prémont int error; 1092d35895dbSBruno Prémont 1093d35895dbSBruno Prémont error = i8042_command(¶m, 0x1059); 1094d35895dbSBruno Prémont if (error) 10954eb3c30bSJoe Perches pr_warn("Failed to enable DRITEK extension: %d\n", error); 1096d35895dbSBruno Prémont } 1097d35895dbSBruno Prémont #endif 1098d35895dbSBruno Prémont 109982dd9effSDmitry Torokhov #ifdef CONFIG_PM 11007e044e05SDmitry Torokhov 11011da177e4SLinus Torvalds /* 1102ebd7768dSDmitry Torokhov * Here we try to reset everything back to a state we had 1103ebd7768dSDmitry Torokhov * before suspending. 11041da177e4SLinus Torvalds */ 11051da177e4SLinus Torvalds 11061ca56e51SDmitry Torokhov static int i8042_controller_resume(bool force_reset) 11071da177e4SLinus Torvalds { 1108de9ce703SDmitry Torokhov int error; 11091da177e4SLinus Torvalds 1110de9ce703SDmitry Torokhov error = i8042_controller_check(); 1111de9ce703SDmitry Torokhov if (error) 1112de9ce703SDmitry Torokhov return error; 11132673c836SVojtech Pavlik 11141ca56e51SDmitry Torokhov if (i8042_reset || force_reset) { 1115de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 1116de9ce703SDmitry Torokhov if (error) 1117de9ce703SDmitry Torokhov return error; 11181ca56e51SDmitry Torokhov } 1119de9ce703SDmitry Torokhov 1120de9ce703SDmitry Torokhov /* 112182dd9effSDmitry Torokhov * Restore original CTR value and disable all ports 1122de9ce703SDmitry Torokhov */ 1123de9ce703SDmitry Torokhov 112482dd9effSDmitry Torokhov i8042_ctr = i8042_initial_ctr; 112582dd9effSDmitry Torokhov if (i8042_direct) 112682dd9effSDmitry Torokhov i8042_ctr &= ~I8042_CTR_XLATE; 1127de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; 1128de9ce703SDmitry Torokhov i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); 11292673c836SVojtech Pavlik if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 11304eb3c30bSJoe Perches pr_warn("Can't write CTR to resume, retrying...\n"); 11312f6a77d5SJiri Kosina msleep(50); 11322f6a77d5SJiri Kosina if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 11334eb3c30bSJoe Perches pr_err("CTR write retry failed\n"); 1134de9ce703SDmitry Torokhov return -EIO; 11351da177e4SLinus Torvalds } 11362f6a77d5SJiri Kosina } 11371da177e4SLinus Torvalds 1138d35895dbSBruno Prémont 1139d35895dbSBruno Prémont #ifdef CONFIG_X86 1140d35895dbSBruno Prémont if (i8042_dritek) 1141d35895dbSBruno Prémont i8042_dritek_enable(); 1142d35895dbSBruno Prémont #endif 1143d35895dbSBruno Prémont 1144de9ce703SDmitry Torokhov if (i8042_mux_present) { 1145386b3849SDmitry Torokhov if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) 11464eb3c30bSJoe Perches pr_warn("failed to resume active multiplexor, mouse won't work\n"); 1147de9ce703SDmitry Torokhov } else if (i8042_ports[I8042_AUX_PORT_NO].serio) 1148de9ce703SDmitry Torokhov i8042_enable_aux_port(); 11491da177e4SLinus Torvalds 1150de9ce703SDmitry Torokhov if (i8042_ports[I8042_KBD_PORT_NO].serio) 1151de9ce703SDmitry Torokhov i8042_enable_kbd_port(); 11521da177e4SLinus Torvalds 11537d12e780SDavid Howells i8042_interrupt(0, NULL); 11541da177e4SLinus Torvalds 11551da177e4SLinus Torvalds return 0; 11561da177e4SLinus Torvalds } 1157ebd7768dSDmitry Torokhov 11581ca56e51SDmitry Torokhov /* 11591ca56e51SDmitry Torokhov * Here we try to restore the original BIOS settings to avoid 11601ca56e51SDmitry Torokhov * upsetting it. 11611ca56e51SDmitry Torokhov */ 11621ca56e51SDmitry Torokhov 11631729ad1fSDmitry Torokhov static int i8042_pm_suspend(struct device *dev) 11641ca56e51SDmitry Torokhov { 1165*f13b2065SRafael J. Wysocki int i; 1166*f13b2065SRafael J. Wysocki 11671729ad1fSDmitry Torokhov i8042_controller_reset(true); 11681ca56e51SDmitry Torokhov 1169*f13b2065SRafael J. Wysocki /* Set up serio interrupts for system wakeup. */ 1170*f13b2065SRafael J. Wysocki for (i = 0; i < I8042_NUM_PORTS; i++) { 1171*f13b2065SRafael J. Wysocki struct serio *serio = i8042_ports[i].serio; 1172*f13b2065SRafael J. Wysocki 1173*f13b2065SRafael J. Wysocki if (serio && device_may_wakeup(&serio->dev)) 1174*f13b2065SRafael J. Wysocki enable_irq_wake(i8042_ports[i].irq); 1175*f13b2065SRafael J. Wysocki } 1176*f13b2065SRafael J. Wysocki 11771ca56e51SDmitry Torokhov return 0; 11781ca56e51SDmitry Torokhov } 11791ca56e51SDmitry Torokhov 11801ca56e51SDmitry Torokhov static int i8042_pm_resume(struct device *dev) 11811ca56e51SDmitry Torokhov { 1182*f13b2065SRafael J. Wysocki int i; 1183*f13b2065SRafael J. Wysocki 1184*f13b2065SRafael J. Wysocki for (i = 0; i < I8042_NUM_PORTS; i++) { 1185*f13b2065SRafael J. Wysocki struct serio *serio = i8042_ports[i].serio; 1186*f13b2065SRafael J. Wysocki 1187*f13b2065SRafael J. Wysocki if (serio && device_may_wakeup(&serio->dev)) 1188*f13b2065SRafael J. Wysocki disable_irq_wake(i8042_ports[i].irq); 1189*f13b2065SRafael J. Wysocki } 1190*f13b2065SRafael J. Wysocki 11911ca56e51SDmitry Torokhov /* 11921ca56e51SDmitry Torokhov * On resume from S2R we always try to reset the controller 11931ca56e51SDmitry Torokhov * to bring it in a sane state. (In case of S2D we expect 11941ca56e51SDmitry Torokhov * BIOS to reset the controller for us.) 11951ca56e51SDmitry Torokhov */ 11961ca56e51SDmitry Torokhov return i8042_controller_resume(true); 11971ca56e51SDmitry Torokhov } 11981ca56e51SDmitry Torokhov 1199c2d1a2a1SAlan Jenkins static int i8042_pm_thaw(struct device *dev) 1200c2d1a2a1SAlan Jenkins { 1201c2d1a2a1SAlan Jenkins i8042_interrupt(0, NULL); 1202c2d1a2a1SAlan Jenkins 1203c2d1a2a1SAlan Jenkins return 0; 1204c2d1a2a1SAlan Jenkins } 1205c2d1a2a1SAlan Jenkins 12061729ad1fSDmitry Torokhov static int i8042_pm_reset(struct device *dev) 12071729ad1fSDmitry Torokhov { 12081729ad1fSDmitry Torokhov i8042_controller_reset(false); 12091729ad1fSDmitry Torokhov 12101729ad1fSDmitry Torokhov return 0; 12111729ad1fSDmitry Torokhov } 12121729ad1fSDmitry Torokhov 12131ca56e51SDmitry Torokhov static int i8042_pm_restore(struct device *dev) 12141ca56e51SDmitry Torokhov { 12151ca56e51SDmitry Torokhov return i8042_controller_resume(false); 12161ca56e51SDmitry Torokhov } 12171ca56e51SDmitry Torokhov 1218ebd7768dSDmitry Torokhov static const struct dev_pm_ops i8042_pm_ops = { 12191729ad1fSDmitry Torokhov .suspend = i8042_pm_suspend, 12201ca56e51SDmitry Torokhov .resume = i8042_pm_resume, 1221c2d1a2a1SAlan Jenkins .thaw = i8042_pm_thaw, 1222ebd7768dSDmitry Torokhov .poweroff = i8042_pm_reset, 1223ebd7768dSDmitry Torokhov .restore = i8042_pm_restore, 1224ebd7768dSDmitry Torokhov }; 1225ebd7768dSDmitry Torokhov 122682dd9effSDmitry Torokhov #endif /* CONFIG_PM */ 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds /* 12291da177e4SLinus Torvalds * We need to reset the 8042 back to original mode on system shutdown, 12301da177e4SLinus Torvalds * because otherwise BIOSes will be confused. 12311da177e4SLinus Torvalds */ 12321da177e4SLinus Torvalds 12333ae5eaecSRussell King static void i8042_shutdown(struct platform_device *dev) 12341da177e4SLinus Torvalds { 12351729ad1fSDmitry Torokhov i8042_controller_reset(false); 12361da177e4SLinus Torvalds } 12371da177e4SLinus Torvalds 1238f8113416SDmitry Torokhov static int __init i8042_create_kbd_port(void) 12391da177e4SLinus Torvalds { 12401da177e4SLinus Torvalds struct serio *serio; 12411da177e4SLinus Torvalds struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; 12421da177e4SLinus Torvalds 1243d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 12440854e52dSDmitry Torokhov if (!serio) 12450854e52dSDmitry Torokhov return -ENOMEM; 12460854e52dSDmitry Torokhov 12471da177e4SLinus Torvalds serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; 12481da177e4SLinus Torvalds serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; 12491da177e4SLinus Torvalds serio->start = i8042_start; 12501da177e4SLinus Torvalds serio->stop = i8042_stop; 12515ddbc77cSDmitry Torokhov serio->close = i8042_port_close; 12521da177e4SLinus Torvalds serio->port_data = port; 12531da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 1254de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); 12551da177e4SLinus Torvalds strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 1256a7c5868cSHans de Goede strlcpy(serio->firmware_id, i8042_kbd_firmware_id, 1257a7c5868cSHans de Goede sizeof(serio->firmware_id)); 12581da177e4SLinus Torvalds 12591da177e4SLinus Torvalds port->serio = serio; 1260de9ce703SDmitry Torokhov port->irq = I8042_KBD_IRQ; 12610854e52dSDmitry Torokhov 1262de9ce703SDmitry Torokhov return 0; 12631da177e4SLinus Torvalds } 12641da177e4SLinus Torvalds 1265f8113416SDmitry Torokhov static int __init i8042_create_aux_port(int idx) 12661da177e4SLinus Torvalds { 12671da177e4SLinus Torvalds struct serio *serio; 1268de9ce703SDmitry Torokhov int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; 1269de9ce703SDmitry Torokhov struct i8042_port *port = &i8042_ports[port_no]; 12701da177e4SLinus Torvalds 1271d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 12720854e52dSDmitry Torokhov if (!serio) 12730854e52dSDmitry Torokhov return -ENOMEM; 12740854e52dSDmitry Torokhov 12751da177e4SLinus Torvalds serio->id.type = SERIO_8042; 12761da177e4SLinus Torvalds serio->write = i8042_aux_write; 12771da177e4SLinus Torvalds serio->start = i8042_start; 12781da177e4SLinus Torvalds serio->stop = i8042_stop; 12791da177e4SLinus Torvalds serio->port_data = port; 12801da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 1281de9ce703SDmitry Torokhov if (idx < 0) { 1282de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); 12831da177e4SLinus Torvalds strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 1284a7c5868cSHans de Goede strlcpy(serio->firmware_id, i8042_aux_firmware_id, 1285a7c5868cSHans de Goede sizeof(serio->firmware_id)); 12865ddbc77cSDmitry Torokhov serio->close = i8042_port_close; 1287de9ce703SDmitry Torokhov } else { 1288de9ce703SDmitry Torokhov snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); 1289de9ce703SDmitry Torokhov snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); 1290266e43c4SHans de Goede strlcpy(serio->firmware_id, i8042_aux_firmware_id, 1291266e43c4SHans de Goede sizeof(serio->firmware_id)); 12921da177e4SLinus Torvalds } 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds port->serio = serio; 1295de9ce703SDmitry Torokhov port->mux = idx; 1296de9ce703SDmitry Torokhov port->irq = I8042_AUX_IRQ; 12970854e52dSDmitry Torokhov 1298de9ce703SDmitry Torokhov return 0; 1299de9ce703SDmitry Torokhov } 1300de9ce703SDmitry Torokhov 1301f8113416SDmitry Torokhov static void __init i8042_free_kbd_port(void) 1302de9ce703SDmitry Torokhov { 1303de9ce703SDmitry Torokhov kfree(i8042_ports[I8042_KBD_PORT_NO].serio); 1304de9ce703SDmitry Torokhov i8042_ports[I8042_KBD_PORT_NO].serio = NULL; 1305de9ce703SDmitry Torokhov } 1306de9ce703SDmitry Torokhov 1307f8113416SDmitry Torokhov static void __init i8042_free_aux_ports(void) 1308de9ce703SDmitry Torokhov { 1309de9ce703SDmitry Torokhov int i; 1310de9ce703SDmitry Torokhov 1311de9ce703SDmitry Torokhov for (i = I8042_AUX_PORT_NO; i < I8042_NUM_PORTS; i++) { 1312de9ce703SDmitry Torokhov kfree(i8042_ports[i].serio); 1313de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 1314de9ce703SDmitry Torokhov } 1315de9ce703SDmitry Torokhov } 1316de9ce703SDmitry Torokhov 1317f8113416SDmitry Torokhov static void __init i8042_register_ports(void) 1318de9ce703SDmitry Torokhov { 1319de9ce703SDmitry Torokhov int i; 1320de9ce703SDmitry Torokhov 1321de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 1322*f13b2065SRafael J. Wysocki struct serio *serio = i8042_ports[i].serio; 1323*f13b2065SRafael J. Wysocki 1324*f13b2065SRafael J. Wysocki if (serio) { 1325de9ce703SDmitry Torokhov printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", 1326*f13b2065SRafael J. Wysocki serio->name, 1327de9ce703SDmitry Torokhov (unsigned long) I8042_DATA_REG, 1328de9ce703SDmitry Torokhov (unsigned long) I8042_COMMAND_REG, 1329de9ce703SDmitry Torokhov i8042_ports[i].irq); 1330*f13b2065SRafael J. Wysocki serio_register_port(serio); 1331*f13b2065SRafael J. Wysocki device_set_wakeup_capable(&serio->dev, true); 1332de9ce703SDmitry Torokhov } 1333de9ce703SDmitry Torokhov } 1334de9ce703SDmitry Torokhov } 1335de9ce703SDmitry Torokhov 1336e2619cf7SBill Pemberton static void i8042_unregister_ports(void) 1337de9ce703SDmitry Torokhov { 1338de9ce703SDmitry Torokhov int i; 1339de9ce703SDmitry Torokhov 1340de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 1341de9ce703SDmitry Torokhov if (i8042_ports[i].serio) { 1342de9ce703SDmitry Torokhov serio_unregister_port(i8042_ports[i].serio); 1343de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 1344de9ce703SDmitry Torokhov } 1345de9ce703SDmitry Torokhov } 1346de9ce703SDmitry Torokhov } 1347de9ce703SDmitry Torokhov 1348181d683dSDmitry Torokhov /* 1349181d683dSDmitry Torokhov * Checks whether port belongs to i8042 controller. 1350181d683dSDmitry Torokhov */ 1351181d683dSDmitry Torokhov bool i8042_check_port_owner(const struct serio *port) 1352181d683dSDmitry Torokhov { 1353181d683dSDmitry Torokhov int i; 1354181d683dSDmitry Torokhov 1355181d683dSDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) 1356181d683dSDmitry Torokhov if (i8042_ports[i].serio == port) 1357181d683dSDmitry Torokhov return true; 1358181d683dSDmitry Torokhov 1359181d683dSDmitry Torokhov return false; 1360181d683dSDmitry Torokhov } 1361181d683dSDmitry Torokhov EXPORT_SYMBOL(i8042_check_port_owner); 1362181d683dSDmitry Torokhov 1363de9ce703SDmitry Torokhov static void i8042_free_irqs(void) 1364de9ce703SDmitry Torokhov { 1365de9ce703SDmitry Torokhov if (i8042_aux_irq_registered) 1366de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1367de9ce703SDmitry Torokhov if (i8042_kbd_irq_registered) 1368de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1369de9ce703SDmitry Torokhov 1370386b3849SDmitry Torokhov i8042_aux_irq_registered = i8042_kbd_irq_registered = false; 1371de9ce703SDmitry Torokhov } 1372de9ce703SDmitry Torokhov 1373f8113416SDmitry Torokhov static int __init i8042_setup_aux(void) 1374de9ce703SDmitry Torokhov { 1375de9ce703SDmitry Torokhov int (*aux_enable)(void); 1376de9ce703SDmitry Torokhov int error; 1377de9ce703SDmitry Torokhov int i; 1378de9ce703SDmitry Torokhov 1379de9ce703SDmitry Torokhov if (i8042_check_aux()) 1380de9ce703SDmitry Torokhov return -ENODEV; 1381de9ce703SDmitry Torokhov 1382de9ce703SDmitry Torokhov if (i8042_nomux || i8042_check_mux()) { 1383de9ce703SDmitry Torokhov error = i8042_create_aux_port(-1); 1384de9ce703SDmitry Torokhov if (error) 1385de9ce703SDmitry Torokhov goto err_free_ports; 1386de9ce703SDmitry Torokhov aux_enable = i8042_enable_aux_port; 1387de9ce703SDmitry Torokhov } else { 1388de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 1389de9ce703SDmitry Torokhov error = i8042_create_aux_port(i); 1390de9ce703SDmitry Torokhov if (error) 1391de9ce703SDmitry Torokhov goto err_free_ports; 1392de9ce703SDmitry Torokhov } 1393de9ce703SDmitry Torokhov aux_enable = i8042_enable_mux_ports; 1394de9ce703SDmitry Torokhov } 1395de9ce703SDmitry Torokhov 1396de9ce703SDmitry Torokhov error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, 1397de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1398de9ce703SDmitry Torokhov if (error) 1399de9ce703SDmitry Torokhov goto err_free_ports; 1400de9ce703SDmitry Torokhov 1401de9ce703SDmitry Torokhov if (aux_enable()) 1402de9ce703SDmitry Torokhov goto err_free_irq; 1403de9ce703SDmitry Torokhov 1404386b3849SDmitry Torokhov i8042_aux_irq_registered = true; 1405de9ce703SDmitry Torokhov return 0; 1406de9ce703SDmitry Torokhov 1407de9ce703SDmitry Torokhov err_free_irq: 1408de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1409de9ce703SDmitry Torokhov err_free_ports: 1410de9ce703SDmitry Torokhov i8042_free_aux_ports(); 1411de9ce703SDmitry Torokhov return error; 1412de9ce703SDmitry Torokhov } 1413de9ce703SDmitry Torokhov 1414f8113416SDmitry Torokhov static int __init i8042_setup_kbd(void) 1415de9ce703SDmitry Torokhov { 1416de9ce703SDmitry Torokhov int error; 1417de9ce703SDmitry Torokhov 1418de9ce703SDmitry Torokhov error = i8042_create_kbd_port(); 1419de9ce703SDmitry Torokhov if (error) 1420de9ce703SDmitry Torokhov return error; 1421de9ce703SDmitry Torokhov 1422de9ce703SDmitry Torokhov error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, 1423de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1424de9ce703SDmitry Torokhov if (error) 1425de9ce703SDmitry Torokhov goto err_free_port; 1426de9ce703SDmitry Torokhov 1427de9ce703SDmitry Torokhov error = i8042_enable_kbd_port(); 1428de9ce703SDmitry Torokhov if (error) 1429de9ce703SDmitry Torokhov goto err_free_irq; 1430de9ce703SDmitry Torokhov 1431386b3849SDmitry Torokhov i8042_kbd_irq_registered = true; 1432de9ce703SDmitry Torokhov return 0; 1433de9ce703SDmitry Torokhov 1434de9ce703SDmitry Torokhov err_free_irq: 1435de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1436de9ce703SDmitry Torokhov err_free_port: 1437de9ce703SDmitry Torokhov i8042_free_kbd_port(); 1438de9ce703SDmitry Torokhov return error; 14391da177e4SLinus Torvalds } 14401da177e4SLinus Torvalds 1441f8113416SDmitry Torokhov static int __init i8042_probe(struct platform_device *dev) 14421da177e4SLinus Torvalds { 1443de9ce703SDmitry Torokhov int error; 14441da177e4SLinus Torvalds 1445ec62e1c8SDmitry Torokhov i8042_platform_device = dev; 1446ec62e1c8SDmitry Torokhov 14471ca56e51SDmitry Torokhov if (i8042_reset) { 1448de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 1449de9ce703SDmitry Torokhov if (error) 1450de9ce703SDmitry Torokhov return error; 14511ca56e51SDmitry Torokhov } 14521da177e4SLinus Torvalds 1453de9ce703SDmitry Torokhov error = i8042_controller_init(); 1454de9ce703SDmitry Torokhov if (error) 1455de9ce703SDmitry Torokhov return error; 14561da177e4SLinus Torvalds 1457d35895dbSBruno Prémont #ifdef CONFIG_X86 1458d35895dbSBruno Prémont if (i8042_dritek) 1459d35895dbSBruno Prémont i8042_dritek_enable(); 1460d35895dbSBruno Prémont #endif 1461d35895dbSBruno Prémont 1462de9ce703SDmitry Torokhov if (!i8042_noaux) { 1463de9ce703SDmitry Torokhov error = i8042_setup_aux(); 1464de9ce703SDmitry Torokhov if (error && error != -ENODEV && error != -EBUSY) 1465de9ce703SDmitry Torokhov goto out_fail; 14661da177e4SLinus Torvalds } 14671da177e4SLinus Torvalds 1468945ef0d4SDmitry Torokhov if (!i8042_nokbd) { 1469de9ce703SDmitry Torokhov error = i8042_setup_kbd(); 1470de9ce703SDmitry Torokhov if (error) 1471de9ce703SDmitry Torokhov goto out_fail; 1472945ef0d4SDmitry Torokhov } 1473de9ce703SDmitry Torokhov /* 1474de9ce703SDmitry Torokhov * Ok, everything is ready, let's register all serio ports 1475de9ce703SDmitry Torokhov */ 1476de9ce703SDmitry Torokhov i8042_register_ports(); 14771da177e4SLinus Torvalds 14781da177e4SLinus Torvalds return 0; 14790854e52dSDmitry Torokhov 1480de9ce703SDmitry Torokhov out_fail: 1481de9ce703SDmitry Torokhov i8042_free_aux_ports(); /* in case KBD failed but AUX not */ 1482de9ce703SDmitry Torokhov i8042_free_irqs(); 14831729ad1fSDmitry Torokhov i8042_controller_reset(false); 1484ec62e1c8SDmitry Torokhov i8042_platform_device = NULL; 14850854e52dSDmitry Torokhov 1486de9ce703SDmitry Torokhov return error; 14871da177e4SLinus Torvalds } 14881da177e4SLinus Torvalds 1489e2619cf7SBill Pemberton static int i8042_remove(struct platform_device *dev) 14901da177e4SLinus Torvalds { 1491de9ce703SDmitry Torokhov i8042_unregister_ports(); 1492de9ce703SDmitry Torokhov i8042_free_irqs(); 14931729ad1fSDmitry Torokhov i8042_controller_reset(false); 1494ec62e1c8SDmitry Torokhov i8042_platform_device = NULL; 14951da177e4SLinus Torvalds 149687fd6318SDmitry Torokhov return 0; 149787fd6318SDmitry Torokhov } 149887fd6318SDmitry Torokhov 149987fd6318SDmitry Torokhov static struct platform_driver i8042_driver = { 150087fd6318SDmitry Torokhov .driver = { 150187fd6318SDmitry Torokhov .name = "i8042", 1502ebd7768dSDmitry Torokhov #ifdef CONFIG_PM 1503ebd7768dSDmitry Torokhov .pm = &i8042_pm_ops, 1504ebd7768dSDmitry Torokhov #endif 150587fd6318SDmitry Torokhov }, 15061cb0aa88SBill Pemberton .remove = i8042_remove, 150782dd9effSDmitry Torokhov .shutdown = i8042_shutdown, 150887fd6318SDmitry Torokhov }; 150987fd6318SDmitry Torokhov 151087fd6318SDmitry Torokhov static int __init i8042_init(void) 151187fd6318SDmitry Torokhov { 1512ec62e1c8SDmitry Torokhov struct platform_device *pdev; 151387fd6318SDmitry Torokhov int err; 151487fd6318SDmitry Torokhov 151587fd6318SDmitry Torokhov dbg_init(); 151687fd6318SDmitry Torokhov 151787fd6318SDmitry Torokhov err = i8042_platform_init(); 151887fd6318SDmitry Torokhov if (err) 151987fd6318SDmitry Torokhov return err; 152087fd6318SDmitry Torokhov 1521de9ce703SDmitry Torokhov err = i8042_controller_check(); 1522de9ce703SDmitry Torokhov if (err) 1523de9ce703SDmitry Torokhov goto err_platform_exit; 152487fd6318SDmitry Torokhov 1525ec62e1c8SDmitry Torokhov pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); 1526ec62e1c8SDmitry Torokhov if (IS_ERR(pdev)) { 1527ec62e1c8SDmitry Torokhov err = PTR_ERR(pdev); 1528f8113416SDmitry Torokhov goto err_platform_exit; 152987fd6318SDmitry Torokhov } 153087fd6318SDmitry Torokhov 1531de9ce703SDmitry Torokhov panic_blink = i8042_panic_blink; 1532de9ce703SDmitry Torokhov 153387fd6318SDmitry Torokhov return 0; 153487fd6318SDmitry Torokhov 153587fd6318SDmitry Torokhov err_platform_exit: 153687fd6318SDmitry Torokhov i8042_platform_exit(); 153787fd6318SDmitry Torokhov return err; 153887fd6318SDmitry Torokhov } 153987fd6318SDmitry Torokhov 154087fd6318SDmitry Torokhov static void __exit i8042_exit(void) 154187fd6318SDmitry Torokhov { 1542f8113416SDmitry Torokhov platform_device_unregister(i8042_platform_device); 1543af045b86SDmitry Torokhov platform_driver_unregister(&i8042_driver); 15441da177e4SLinus Torvalds i8042_platform_exit(); 15451da177e4SLinus Torvalds 15461da177e4SLinus Torvalds panic_blink = NULL; 15471da177e4SLinus Torvalds } 15481da177e4SLinus Torvalds 15491da177e4SLinus Torvalds module_init(i8042_init); 15501da177e4SLinus Torvalds module_exit(i8042_exit); 1551