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 131da177e4SLinus Torvalds #include <linux/delay.h> 141da177e4SLinus Torvalds #include <linux/module.h> 151da177e4SLinus Torvalds #include <linux/moduleparam.h> 161da177e4SLinus Torvalds #include <linux/interrupt.h> 171da177e4SLinus Torvalds #include <linux/ioport.h> 181da177e4SLinus Torvalds #include <linux/init.h> 191da177e4SLinus Torvalds #include <linux/serio.h> 201da177e4SLinus Torvalds #include <linux/err.h> 211da177e4SLinus Torvalds #include <linux/rcupdate.h> 22d052d1beSRussell King #include <linux/platform_device.h> 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #include <asm/io.h> 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); 271da177e4SLinus Torvalds MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); 281da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 291da177e4SLinus Torvalds 30945ef0d4SDmitry Torokhov static unsigned int i8042_nokbd; 31945ef0d4SDmitry Torokhov module_param_named(nokbd, i8042_nokbd, bool, 0); 32945ef0d4SDmitry Torokhov MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); 33945ef0d4SDmitry Torokhov 341da177e4SLinus Torvalds static unsigned int i8042_noaux; 351da177e4SLinus Torvalds module_param_named(noaux, i8042_noaux, bool, 0); 361da177e4SLinus Torvalds MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds static unsigned int i8042_nomux; 391da177e4SLinus Torvalds module_param_named(nomux, i8042_nomux, bool, 0); 401da177e4SLinus Torvalds MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds static unsigned int i8042_unlock; 431da177e4SLinus Torvalds module_param_named(unlock, i8042_unlock, bool, 0); 441da177e4SLinus Torvalds MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds static unsigned int i8042_reset; 471da177e4SLinus Torvalds module_param_named(reset, i8042_reset, bool, 0); 481da177e4SLinus Torvalds MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds static unsigned int i8042_direct; 511da177e4SLinus Torvalds module_param_named(direct, i8042_direct, bool, 0); 521da177e4SLinus Torvalds MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds static unsigned int i8042_dumbkbd; 551da177e4SLinus Torvalds module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); 561da177e4SLinus Torvalds MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds static unsigned int i8042_noloop; 591da177e4SLinus Torvalds module_param_named(noloop, i8042_noloop, bool, 0); 601da177e4SLinus Torvalds MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds static unsigned int i8042_blink_frequency = 500; 631da177e4SLinus Torvalds module_param_named(panicblink, i8042_blink_frequency, uint, 0600); 641da177e4SLinus Torvalds MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds #ifdef CONFIG_PNP 671da177e4SLinus Torvalds static int i8042_nopnp; 681da177e4SLinus Torvalds module_param_named(nopnp, i8042_nopnp, bool, 0); 691da177e4SLinus Torvalds MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); 701da177e4SLinus Torvalds #endif 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #define DEBUG 731da177e4SLinus Torvalds #ifdef DEBUG 741da177e4SLinus Torvalds static int i8042_debug; 751da177e4SLinus Torvalds module_param_named(debug, i8042_debug, bool, 0600); 761da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); 771da177e4SLinus Torvalds #endif 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds __obsolete_setup("i8042_noaux"); 801da177e4SLinus Torvalds __obsolete_setup("i8042_nomux"); 811da177e4SLinus Torvalds __obsolete_setup("i8042_unlock"); 821da177e4SLinus Torvalds __obsolete_setup("i8042_reset"); 831da177e4SLinus Torvalds __obsolete_setup("i8042_direct"); 841da177e4SLinus Torvalds __obsolete_setup("i8042_dumbkbd"); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds #include "i8042.h" 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds static DEFINE_SPINLOCK(i8042_lock); 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds struct i8042_port { 911da177e4SLinus Torvalds struct serio *serio; 921da177e4SLinus Torvalds int irq; 931da177e4SLinus Torvalds unsigned char exists; 941da177e4SLinus Torvalds signed char mux; 951da177e4SLinus Torvalds }; 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds #define I8042_KBD_PORT_NO 0 981da177e4SLinus Torvalds #define I8042_AUX_PORT_NO 1 991da177e4SLinus Torvalds #define I8042_MUX_PORT_NO 2 1001da177e4SLinus Torvalds #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) 101de9ce703SDmitry Torokhov 102de9ce703SDmitry Torokhov static struct i8042_port i8042_ports[I8042_NUM_PORTS]; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds static unsigned char i8042_initial_ctr; 1051da177e4SLinus Torvalds static unsigned char i8042_ctr; 1061da177e4SLinus Torvalds static unsigned char i8042_mux_present; 107de9ce703SDmitry Torokhov static unsigned char i8042_kbd_irq_registered; 108de9ce703SDmitry Torokhov static unsigned char i8042_aux_irq_registered; 1091da177e4SLinus Torvalds static struct platform_device *i8042_platform_device; 1101da177e4SLinus Torvalds 111*7d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds /* 1141da177e4SLinus Torvalds * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to 1151da177e4SLinus Torvalds * be ready for reading values from it / writing values to it. 1161da177e4SLinus Torvalds * Called always with i8042_lock held. 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds static int i8042_wait_read(void) 1201da177e4SLinus Torvalds { 1211da177e4SLinus Torvalds int i = 0; 122de9ce703SDmitry Torokhov 1231da177e4SLinus Torvalds while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { 1241da177e4SLinus Torvalds udelay(50); 1251da177e4SLinus Torvalds i++; 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds static int i8042_wait_write(void) 1311da177e4SLinus Torvalds { 1321da177e4SLinus Torvalds int i = 0; 133de9ce703SDmitry Torokhov 1341da177e4SLinus Torvalds while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { 1351da177e4SLinus Torvalds udelay(50); 1361da177e4SLinus Torvalds i++; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds return -(i == I8042_CTL_TIMEOUT); 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds /* 1421da177e4SLinus Torvalds * i8042_flush() flushes all data that may be in the keyboard and mouse buffers 1431da177e4SLinus Torvalds * of the i8042 down the toilet. 1441da177e4SLinus Torvalds */ 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds static int i8042_flush(void) 1471da177e4SLinus Torvalds { 1481da177e4SLinus Torvalds unsigned long flags; 1491da177e4SLinus Torvalds unsigned char data, str; 1501da177e4SLinus Torvalds int i = 0; 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) { 1551da177e4SLinus Torvalds udelay(50); 1561da177e4SLinus Torvalds data = i8042_read_data(); 1571da177e4SLinus Torvalds i++; 1581da177e4SLinus Torvalds dbg("%02x <- i8042 (flush, %s)", data, 1591da177e4SLinus Torvalds str & I8042_STR_AUXDATA ? "aux" : "kbd"); 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds return i; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* 1681da177e4SLinus Torvalds * i8042_command() executes a command on the i8042. It also sends the input 1691da177e4SLinus Torvalds * parameter(s) of the commands to it, and receives the output value(s). The 1701da177e4SLinus Torvalds * parameters are to be stored in the param array, and the output is placed 1711da177e4SLinus Torvalds * into the same array. The number of the parameters and output values is 1721da177e4SLinus Torvalds * encoded in bits 8-11 of the command number. 1731da177e4SLinus Torvalds */ 1741da177e4SLinus Torvalds 175de9ce703SDmitry Torokhov static int __i8042_command(unsigned char *param, int command) 1761da177e4SLinus Torvalds { 177de9ce703SDmitry Torokhov int i, error; 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds if (i8042_noloop && command == I8042_CMD_AUX_LOOP) 1801da177e4SLinus Torvalds return -1; 1811da177e4SLinus Torvalds 182de9ce703SDmitry Torokhov error = i8042_wait_write(); 183de9ce703SDmitry Torokhov if (error) 184de9ce703SDmitry Torokhov return error; 185463a4f76SDmitry Torokhov 1861da177e4SLinus Torvalds dbg("%02x -> i8042 (command)", command & 0xff); 1871da177e4SLinus Torvalds i8042_write_command(command & 0xff); 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds for (i = 0; i < ((command >> 12) & 0xf); i++) { 190de9ce703SDmitry Torokhov error = i8042_wait_write(); 191de9ce703SDmitry Torokhov if (error) 192de9ce703SDmitry Torokhov return error; 1931da177e4SLinus Torvalds dbg("%02x -> i8042 (parameter)", param[i]); 1941da177e4SLinus Torvalds i8042_write_data(param[i]); 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds for (i = 0; i < ((command >> 8) & 0xf); i++) { 198de9ce703SDmitry Torokhov error = i8042_wait_read(); 199de9ce703SDmitry Torokhov if (error) { 200de9ce703SDmitry Torokhov dbg(" -- i8042 (timeout)"); 201de9ce703SDmitry Torokhov return error; 202de9ce703SDmitry Torokhov } 203463a4f76SDmitry Torokhov 204463a4f76SDmitry Torokhov if (command == I8042_CMD_AUX_LOOP && 205463a4f76SDmitry Torokhov !(i8042_read_status() & I8042_STR_AUXDATA)) { 206de9ce703SDmitry Torokhov dbg(" -- i8042 (auxerr)"); 207de9ce703SDmitry Torokhov return -1; 208463a4f76SDmitry Torokhov } 209463a4f76SDmitry Torokhov 2101da177e4SLinus Torvalds param[i] = i8042_read_data(); 2111da177e4SLinus Torvalds dbg("%02x <- i8042 (return)", param[i]); 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds 214de9ce703SDmitry Torokhov return 0; 215de9ce703SDmitry Torokhov } 2161da177e4SLinus Torvalds 217de9ce703SDmitry Torokhov static int i8042_command(unsigned char *param, int command) 218de9ce703SDmitry Torokhov { 219de9ce703SDmitry Torokhov unsigned long flags; 220de9ce703SDmitry Torokhov int retval; 221de9ce703SDmitry Torokhov 222de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 223de9ce703SDmitry Torokhov retval = __i8042_command(param, command); 224463a4f76SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 225de9ce703SDmitry Torokhov 2261da177e4SLinus Torvalds return retval; 2271da177e4SLinus Torvalds } 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds /* 2301da177e4SLinus Torvalds * i8042_kbd_write() sends a byte out through the keyboard interface. 2311da177e4SLinus Torvalds */ 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds static int i8042_kbd_write(struct serio *port, unsigned char c) 2341da177e4SLinus Torvalds { 2351da177e4SLinus Torvalds unsigned long flags; 2361da177e4SLinus Torvalds int retval = 0; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds if (!(retval = i8042_wait_write())) { 2411da177e4SLinus Torvalds dbg("%02x -> i8042 (kbd-data)", c); 2421da177e4SLinus Torvalds i8042_write_data(c); 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds return retval; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /* 2511da177e4SLinus Torvalds * i8042_aux_write() sends a byte out through the aux interface. 2521da177e4SLinus Torvalds */ 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds static int i8042_aux_write(struct serio *serio, unsigned char c) 2551da177e4SLinus Torvalds { 2561da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 2571da177e4SLinus Torvalds int retval; 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds /* 2601da177e4SLinus Torvalds * Send the byte out. 2611da177e4SLinus Torvalds */ 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (port->mux == -1) 2641da177e4SLinus Torvalds retval = i8042_command(&c, I8042_CMD_AUX_SEND); 2651da177e4SLinus Torvalds else 2661da177e4SLinus Torvalds retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux); 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds /* 2691da177e4SLinus Torvalds * Make sure the interrupt happens and the character is received even 2701da177e4SLinus Torvalds * in the case the IRQ isn't wired, so that we can receive further 2711da177e4SLinus Torvalds * characters later. 2721da177e4SLinus Torvalds */ 2731da177e4SLinus Torvalds 274*7d12e780SDavid Howells i8042_interrupt(0, NULL); 2751da177e4SLinus Torvalds return retval; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds /* 2791da177e4SLinus Torvalds * i8042_start() is called by serio core when port is about to finish 2801da177e4SLinus Torvalds * registering. It will mark port as existing so i8042_interrupt can 2811da177e4SLinus Torvalds * start sending data through it. 2821da177e4SLinus Torvalds */ 2831da177e4SLinus Torvalds static int i8042_start(struct serio *serio) 2841da177e4SLinus Torvalds { 2851da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds port->exists = 1; 2881da177e4SLinus Torvalds mb(); 2891da177e4SLinus Torvalds return 0; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds /* 2931da177e4SLinus Torvalds * i8042_stop() marks serio port as non-existing so i8042_interrupt 2941da177e4SLinus Torvalds * will not try to send data to the port that is about to go away. 2951da177e4SLinus Torvalds * The function is called by serio core as part of unregister procedure. 2961da177e4SLinus Torvalds */ 2971da177e4SLinus Torvalds static void i8042_stop(struct serio *serio) 2981da177e4SLinus Torvalds { 2991da177e4SLinus Torvalds struct i8042_port *port = serio->port_data; 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds port->exists = 0; 302b2b18660SPaul E. McKenney synchronize_sched(); 3031da177e4SLinus Torvalds port->serio = NULL; 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds /* 3071da177e4SLinus Torvalds * i8042_interrupt() is the most important function in this driver - 3081da177e4SLinus Torvalds * it handles the interrupts from the i8042, and sends incoming bytes 3091da177e4SLinus Torvalds * to the upper layers. 3101da177e4SLinus Torvalds */ 3111da177e4SLinus Torvalds 312*7d12e780SDavid Howells static irqreturn_t i8042_interrupt(int irq, void *dev_id) 3131da177e4SLinus Torvalds { 3141da177e4SLinus Torvalds struct i8042_port *port; 3151da177e4SLinus Torvalds unsigned long flags; 3161da177e4SLinus Torvalds unsigned char str, data; 3171da177e4SLinus Torvalds unsigned int dfl; 3181da177e4SLinus Torvalds unsigned int port_no; 3191da177e4SLinus Torvalds int ret; 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 3221da177e4SLinus Torvalds str = i8042_read_status(); 3231da177e4SLinus Torvalds if (unlikely(~str & I8042_STR_OBF)) { 3241da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 3251da177e4SLinus Torvalds if (irq) dbg("Interrupt %d, without any data", irq); 3261da177e4SLinus Torvalds ret = 0; 3271da177e4SLinus Torvalds goto out; 3281da177e4SLinus Torvalds } 3291da177e4SLinus Torvalds data = i8042_read_data(); 3301da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 3331da177e4SLinus Torvalds static unsigned long last_transmit; 3341da177e4SLinus Torvalds static unsigned char last_str; 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds dfl = 0; 3371da177e4SLinus Torvalds if (str & I8042_STR_MUXERR) { 3381da177e4SLinus Torvalds dbg("MUX error, status is %02x, data is %02x", str, data); 3391da177e4SLinus Torvalds switch (data) { 3401da177e4SLinus Torvalds default: 3411da177e4SLinus Torvalds /* 3421da177e4SLinus Torvalds * When MUXERR condition is signalled the data register can only contain 3431da177e4SLinus Torvalds * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately 3441da177e4SLinus Torvalds * it is not always the case. Some KBC just get confused which port the 3451da177e4SLinus Torvalds * data came from and signal error leaving the data intact. They _do not_ 3461da177e4SLinus Torvalds * revert to legacy mode (actually I've never seen KBC reverting to legacy 3471da177e4SLinus Torvalds * mode yet, when we see one we'll add proper handling). 3481da177e4SLinus Torvalds * Anyway, we will assume that the data came from the same serio last byte 3491da177e4SLinus Torvalds * was transmitted (if transmission happened not too long ago). 3501da177e4SLinus Torvalds */ 3511da177e4SLinus Torvalds if (time_before(jiffies, last_transmit + HZ/10)) { 3521da177e4SLinus Torvalds str = last_str; 3531da177e4SLinus Torvalds break; 3541da177e4SLinus Torvalds } 3551da177e4SLinus Torvalds /* fall through - report timeout */ 3561da177e4SLinus Torvalds case 0xfd: 3571da177e4SLinus Torvalds case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; 3581da177e4SLinus Torvalds case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); 3631da177e4SLinus Torvalds last_str = str; 3641da177e4SLinus Torvalds last_transmit = jiffies; 3651da177e4SLinus Torvalds } else { 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | 3681da177e4SLinus Torvalds ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds port_no = (str & I8042_STR_AUXDATA) ? 3711da177e4SLinus Torvalds I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; 3721da177e4SLinus Torvalds } 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds port = &i8042_ports[port_no]; 3751da177e4SLinus Torvalds 376de9ce703SDmitry Torokhov dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", 377de9ce703SDmitry Torokhov data, port_no, irq, 3781da177e4SLinus Torvalds dfl & SERIO_PARITY ? ", bad parity" : "", 3791da177e4SLinus Torvalds dfl & SERIO_TIMEOUT ? ", timeout" : ""); 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds if (likely(port->exists)) 382*7d12e780SDavid Howells serio_interrupt(port->serio, data, dfl); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds ret = 1; 3851da177e4SLinus Torvalds out: 3861da177e4SLinus Torvalds return IRQ_RETVAL(ret); 3871da177e4SLinus Torvalds } 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds /* 390de9ce703SDmitry Torokhov * i8042_enable_kbd_port enables keybaord port on chip 391de9ce703SDmitry Torokhov */ 392de9ce703SDmitry Torokhov 393de9ce703SDmitry Torokhov static int i8042_enable_kbd_port(void) 394de9ce703SDmitry Torokhov { 395de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_KBDDIS; 396de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_KBDINT; 397de9ce703SDmitry Torokhov 398de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 399de9ce703SDmitry Torokhov printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); 400de9ce703SDmitry Torokhov return -EIO; 401de9ce703SDmitry Torokhov } 402de9ce703SDmitry Torokhov 403de9ce703SDmitry Torokhov return 0; 404de9ce703SDmitry Torokhov } 405de9ce703SDmitry Torokhov 406de9ce703SDmitry Torokhov /* 407de9ce703SDmitry Torokhov * i8042_enable_aux_port enables AUX (mouse) port on chip 408de9ce703SDmitry Torokhov */ 409de9ce703SDmitry Torokhov 410de9ce703SDmitry Torokhov static int i8042_enable_aux_port(void) 411de9ce703SDmitry Torokhov { 412de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXDIS; 413de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXINT; 414de9ce703SDmitry Torokhov 415de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 416de9ce703SDmitry Torokhov printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); 417de9ce703SDmitry Torokhov return -EIO; 418de9ce703SDmitry Torokhov } 419de9ce703SDmitry Torokhov 420de9ce703SDmitry Torokhov return 0; 421de9ce703SDmitry Torokhov } 422de9ce703SDmitry Torokhov 423de9ce703SDmitry Torokhov /* 424de9ce703SDmitry Torokhov * i8042_enable_mux_ports enables 4 individual AUX ports after 425de9ce703SDmitry Torokhov * the controller has been switched into Multiplexed mode 426de9ce703SDmitry Torokhov */ 427de9ce703SDmitry Torokhov 428de9ce703SDmitry Torokhov static int i8042_enable_mux_ports(void) 429de9ce703SDmitry Torokhov { 430de9ce703SDmitry Torokhov unsigned char param; 431de9ce703SDmitry Torokhov int i; 432de9ce703SDmitry Torokhov 433de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 434de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_MUX_PFX + i); 435de9ce703SDmitry Torokhov i8042_command(¶m, I8042_CMD_AUX_ENABLE); 436de9ce703SDmitry Torokhov } 437de9ce703SDmitry Torokhov 438de9ce703SDmitry Torokhov return i8042_enable_aux_port(); 439de9ce703SDmitry Torokhov } 440de9ce703SDmitry Torokhov 441de9ce703SDmitry Torokhov /* 4421da177e4SLinus Torvalds * i8042_set_mux_mode checks whether the controller has an active 4431da177e4SLinus Torvalds * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. 4441da177e4SLinus Torvalds */ 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) 4471da177e4SLinus Torvalds { 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds unsigned char param; 4501da177e4SLinus Torvalds /* 4511da177e4SLinus Torvalds * Get rid of bytes in the queue. 4521da177e4SLinus Torvalds */ 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds i8042_flush(); 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* 4571da177e4SLinus Torvalds * Internal loopback test - send three bytes, they should come back from the 458de9ce703SDmitry Torokhov * mouse interface, the last should be version. 4591da177e4SLinus Torvalds */ 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds param = 0xf0; 462463a4f76SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) 4631da177e4SLinus Torvalds return -1; 4641da177e4SLinus Torvalds param = mode ? 0x56 : 0xf6; 465463a4f76SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) 4661da177e4SLinus Torvalds return -1; 4671da177e4SLinus Torvalds param = mode ? 0xa4 : 0xa5; 468463a4f76SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) 4691da177e4SLinus Torvalds return -1; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds if (mux_version) 472463a4f76SDmitry Torokhov *mux_version = param; 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds return 0; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds /* 4781da177e4SLinus Torvalds * i8042_check_mux() checks whether the controller supports the PS/2 Active 4791da177e4SLinus Torvalds * Multiplexing specification by Synaptics, Phoenix, Insyde and 4801da177e4SLinus Torvalds * LCS/Telegraphics. 4811da177e4SLinus Torvalds */ 4821da177e4SLinus Torvalds 48387fd6318SDmitry Torokhov static int __devinit i8042_check_mux(void) 4841da177e4SLinus Torvalds { 4851da177e4SLinus Torvalds unsigned char mux_version; 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds if (i8042_set_mux_mode(1, &mux_version)) 4881da177e4SLinus Torvalds return -1; 4891da177e4SLinus Torvalds 490de9ce703SDmitry Torokhov /* 491de9ce703SDmitry Torokhov * Workaround for interference with USB Legacy emulation 492de9ce703SDmitry Torokhov * that causes a v10.12 MUX to be found. 493de9ce703SDmitry Torokhov */ 4941da177e4SLinus Torvalds if (mux_version == 0xAC) 4951da177e4SLinus Torvalds return -1; 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", 4981da177e4SLinus Torvalds (mux_version >> 4) & 0xf, mux_version & 0xf); 4991da177e4SLinus Torvalds 500de9ce703SDmitry Torokhov /* 501de9ce703SDmitry Torokhov * Disable all muxed ports by disabling AUX. 502de9ce703SDmitry Torokhov */ 503de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS; 504de9ce703SDmitry Torokhov i8042_ctr &= ~I8042_CTR_AUXINT; 505de9ce703SDmitry Torokhov 506de9ce703SDmitry Torokhov if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 507de9ce703SDmitry Torokhov printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); 508de9ce703SDmitry Torokhov return -EIO; 509de9ce703SDmitry Torokhov } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds i8042_mux_present = 1; 512de9ce703SDmitry Torokhov 5131da177e4SLinus Torvalds return 0; 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 516de9ce703SDmitry Torokhov /* 517de9ce703SDmitry Torokhov * The following is used to test AUX IRQ delivery. 518de9ce703SDmitry Torokhov */ 519de9ce703SDmitry Torokhov static struct completion i8042_aux_irq_delivered __devinitdata; 520de9ce703SDmitry Torokhov static int i8042_irq_being_tested __devinitdata; 521de9ce703SDmitry Torokhov 522*7d12e780SDavid Howells static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) 523de9ce703SDmitry Torokhov { 524de9ce703SDmitry Torokhov unsigned long flags; 525de9ce703SDmitry Torokhov unsigned char str, data; 526de9ce703SDmitry Torokhov 527de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 528de9ce703SDmitry Torokhov str = i8042_read_status(); 529de9ce703SDmitry Torokhov if (str & I8042_STR_OBF) { 530de9ce703SDmitry Torokhov data = i8042_read_data(); 531de9ce703SDmitry Torokhov if (i8042_irq_being_tested && 532de9ce703SDmitry Torokhov data == 0xa5 && (str & I8042_STR_AUXDATA)) 533de9ce703SDmitry Torokhov complete(&i8042_aux_irq_delivered); 534de9ce703SDmitry Torokhov } 535de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 536de9ce703SDmitry Torokhov 537de9ce703SDmitry Torokhov return IRQ_HANDLED; 538de9ce703SDmitry Torokhov } 539de9ce703SDmitry Torokhov 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds /* 5421da177e4SLinus Torvalds * i8042_check_aux() applies as much paranoia as it can at detecting 5431da177e4SLinus Torvalds * the presence of an AUX interface. 5441da177e4SLinus Torvalds */ 5451da177e4SLinus Torvalds 54687fd6318SDmitry Torokhov static int __devinit i8042_check_aux(void) 5471da177e4SLinus Torvalds { 548de9ce703SDmitry Torokhov int retval = -1; 549de9ce703SDmitry Torokhov int irq_registered = 0; 550de9ce703SDmitry Torokhov unsigned long flags; 5511da177e4SLinus Torvalds unsigned char param; 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /* 5541da177e4SLinus Torvalds * Get rid of bytes in the queue. 5551da177e4SLinus Torvalds */ 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds i8042_flush(); 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds /* 5601da177e4SLinus Torvalds * Internal loopback test - filters out AT-type i8042's. Unfortunately 5611da177e4SLinus Torvalds * SiS screwed up and their 5597 doesn't support the LOOP command even 5621da177e4SLinus Torvalds * though it has an AUX port. 5631da177e4SLinus Torvalds */ 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds param = 0x5a; 566463a4f76SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x5a) { 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds /* 5691da177e4SLinus Torvalds * External connection test - filters out AT-soldered PS/2 i8042's 5701da177e4SLinus Torvalds * 0x00 - no error, 0x01-0x03 - clock/data stuck, 0xff - general error 5711da177e4SLinus Torvalds * 0xfa - no error on some notebooks which ignore the spec 5721da177e4SLinus Torvalds * Because it's common for chipsets to return error on perfectly functioning 5731da177e4SLinus Torvalds * AUX ports, we test for this only when the LOOP command failed. 5741da177e4SLinus Torvalds */ 5751da177e4SLinus Torvalds 576de9ce703SDmitry Torokhov if (i8042_command(¶m, I8042_CMD_AUX_TEST) || 577de9ce703SDmitry Torokhov (param && param != 0xfa && param != 0xff)) 5781da177e4SLinus Torvalds return -1; 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds /* 5821da177e4SLinus Torvalds * Bit assignment test - filters out PS/2 i8042's in AT mode 5831da177e4SLinus Torvalds */ 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds if (i8042_command(¶m, I8042_CMD_AUX_DISABLE)) 5861da177e4SLinus Torvalds return -1; 5871da177e4SLinus Torvalds if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) { 5881da177e4SLinus Torvalds printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); 5891da177e4SLinus Torvalds printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); 5901da177e4SLinus Torvalds } 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds if (i8042_command(¶m, I8042_CMD_AUX_ENABLE)) 5931da177e4SLinus Torvalds return -1; 5941da177e4SLinus Torvalds if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS)) 5951da177e4SLinus Torvalds return -1; 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds /* 598de9ce703SDmitry Torokhov * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and 599de9ce703SDmitry Torokhov * used it for a PCI card or somethig else. 600de9ce703SDmitry Torokhov */ 601de9ce703SDmitry Torokhov 602de9ce703SDmitry Torokhov if (i8042_noloop) { 603de9ce703SDmitry Torokhov /* 604de9ce703SDmitry Torokhov * Without LOOP command we can't test AUX IRQ delivery. Assume the port 605de9ce703SDmitry Torokhov * is working and hope we are right. 606de9ce703SDmitry Torokhov */ 607de9ce703SDmitry Torokhov retval = 0; 608de9ce703SDmitry Torokhov goto out; 609de9ce703SDmitry Torokhov } 610de9ce703SDmitry Torokhov 611de9ce703SDmitry Torokhov if (request_irq(I8042_AUX_IRQ, i8042_aux_test_irq, IRQF_SHARED, 612de9ce703SDmitry Torokhov "i8042", i8042_platform_device)) 613de9ce703SDmitry Torokhov goto out; 614de9ce703SDmitry Torokhov 615de9ce703SDmitry Torokhov irq_registered = 1; 616de9ce703SDmitry Torokhov 617de9ce703SDmitry Torokhov if (i8042_enable_aux_port()) 618de9ce703SDmitry Torokhov goto out; 619de9ce703SDmitry Torokhov 620de9ce703SDmitry Torokhov spin_lock_irqsave(&i8042_lock, flags); 621de9ce703SDmitry Torokhov 622de9ce703SDmitry Torokhov init_completion(&i8042_aux_irq_delivered); 623de9ce703SDmitry Torokhov i8042_irq_being_tested = 1; 624de9ce703SDmitry Torokhov 625de9ce703SDmitry Torokhov param = 0xa5; 626de9ce703SDmitry Torokhov retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); 627de9ce703SDmitry Torokhov 628de9ce703SDmitry Torokhov spin_unlock_irqrestore(&i8042_lock, flags); 629de9ce703SDmitry Torokhov 630de9ce703SDmitry Torokhov if (retval) 631de9ce703SDmitry Torokhov goto out; 632de9ce703SDmitry Torokhov 633de9ce703SDmitry Torokhov if (wait_for_completion_timeout(&i8042_aux_irq_delivered, 634de9ce703SDmitry Torokhov msecs_to_jiffies(250)) == 0) { 635de9ce703SDmitry Torokhov /* 636de9ce703SDmitry Torokhov * AUX IRQ was never delivered so we need to flush the controller to 637de9ce703SDmitry Torokhov * get rid of the byte we put there; otherwise keyboard may not work. 638de9ce703SDmitry Torokhov */ 639de9ce703SDmitry Torokhov i8042_flush(); 640de9ce703SDmitry Torokhov retval = -1; 641de9ce703SDmitry Torokhov } 642de9ce703SDmitry Torokhov 643de9ce703SDmitry Torokhov out: 644de9ce703SDmitry Torokhov 645de9ce703SDmitry Torokhov /* 6461da177e4SLinus Torvalds * Disable the interface. 6471da177e4SLinus Torvalds */ 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_AUXDIS; 6501da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_AUXINT; 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 653de9ce703SDmitry Torokhov retval = -1; 654de9ce703SDmitry Torokhov 655de9ce703SDmitry Torokhov if (irq_registered) 656de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 657de9ce703SDmitry Torokhov 658de9ce703SDmitry Torokhov return retval; 659de9ce703SDmitry Torokhov } 660de9ce703SDmitry Torokhov 661de9ce703SDmitry Torokhov static int i8042_controller_check(void) 662de9ce703SDmitry Torokhov { 663de9ce703SDmitry Torokhov if (i8042_flush() == I8042_BUFFER_SIZE) { 664de9ce703SDmitry Torokhov printk(KERN_ERR "i8042.c: No controller found.\n"); 665de9ce703SDmitry Torokhov return -ENODEV; 666de9ce703SDmitry Torokhov } 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds return 0; 6691da177e4SLinus Torvalds } 6701da177e4SLinus Torvalds 671de9ce703SDmitry Torokhov static int i8042_controller_selftest(void) 6722673c836SVojtech Pavlik { 6732673c836SVojtech Pavlik unsigned char param; 6742673c836SVojtech Pavlik 6752673c836SVojtech Pavlik if (!i8042_reset) 6762673c836SVojtech Pavlik return 0; 6772673c836SVojtech Pavlik 6782673c836SVojtech Pavlik if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { 6792673c836SVojtech Pavlik printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); 680de9ce703SDmitry Torokhov return -ENODEV; 6812673c836SVojtech Pavlik } 6822673c836SVojtech Pavlik 6832673c836SVojtech Pavlik if (param != I8042_RET_CTL_TEST) { 6842673c836SVojtech Pavlik printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", 6852673c836SVojtech Pavlik param, I8042_RET_CTL_TEST); 686de9ce703SDmitry Torokhov return -EIO; 6872673c836SVojtech Pavlik } 6882673c836SVojtech Pavlik 6892673c836SVojtech Pavlik return 0; 6902673c836SVojtech Pavlik } 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds /* 6931da177e4SLinus Torvalds * i8042_controller init initializes the i8042 controller, and, 6941da177e4SLinus Torvalds * most importantly, sets it into non-xlated mode if that's 6951da177e4SLinus Torvalds * desired. 6961da177e4SLinus Torvalds */ 6971da177e4SLinus Torvalds 6981da177e4SLinus Torvalds static int i8042_controller_init(void) 6991da177e4SLinus Torvalds { 7001da177e4SLinus Torvalds unsigned long flags; 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds /* 7031da177e4SLinus Torvalds * Save the CTR for restoral on unload / reboot. 7041da177e4SLinus Torvalds */ 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { 7071da177e4SLinus Torvalds printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); 708de9ce703SDmitry Torokhov return -EIO; 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds i8042_initial_ctr = i8042_ctr; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds /* 7141da177e4SLinus Torvalds * Disable the keyboard interface and interrupt. 7151da177e4SLinus Torvalds */ 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_KBDDIS; 7181da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_KBDINT; 7191da177e4SLinus Torvalds 7201da177e4SLinus Torvalds /* 7211da177e4SLinus Torvalds * Handle keylock. 7221da177e4SLinus Torvalds */ 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds spin_lock_irqsave(&i8042_lock, flags); 7251da177e4SLinus Torvalds if (~i8042_read_status() & I8042_STR_KEYLOCK) { 7261da177e4SLinus Torvalds if (i8042_unlock) 7271da177e4SLinus Torvalds i8042_ctr |= I8042_CTR_IGNKEYLOCK; 7281da177e4SLinus Torvalds else 7291da177e4SLinus Torvalds printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n"); 7301da177e4SLinus Torvalds } 7311da177e4SLinus Torvalds spin_unlock_irqrestore(&i8042_lock, flags); 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds /* 7341da177e4SLinus Torvalds * If the chip is configured into nontranslated mode by the BIOS, don't 7351da177e4SLinus Torvalds * bother enabling translating and be happy. 7361da177e4SLinus Torvalds */ 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds if (~i8042_ctr & I8042_CTR_XLATE) 7391da177e4SLinus Torvalds i8042_direct = 1; 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds /* 7421da177e4SLinus Torvalds * Set nontranslated mode for the kbd interface if requested by an option. 7431da177e4SLinus Torvalds * After this the kbd interface becomes a simple serial in/out, like the aux 7441da177e4SLinus Torvalds * interface is. We don't do this by default, since it can confuse notebook 7451da177e4SLinus Torvalds * BIOSes. 7461da177e4SLinus Torvalds */ 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds if (i8042_direct) 7491da177e4SLinus Torvalds i8042_ctr &= ~I8042_CTR_XLATE; 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds /* 7521da177e4SLinus Torvalds * Write CTR back. 7531da177e4SLinus Torvalds */ 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 7561da177e4SLinus Torvalds printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); 757de9ce703SDmitry Torokhov return -EIO; 7581da177e4SLinus Torvalds } 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds return 0; 7611da177e4SLinus Torvalds } 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds /* 765de9ce703SDmitry Torokhov * Reset the controller and reset CRT to the original value set by BIOS. 7661da177e4SLinus Torvalds */ 7671da177e4SLinus Torvalds 768de9ce703SDmitry Torokhov static void i8042_controller_reset(void) 769de9ce703SDmitry Torokhov { 770de9ce703SDmitry Torokhov i8042_flush(); 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds /* 7731da177e4SLinus Torvalds * Disable MUX mode if present. 7741da177e4SLinus Torvalds */ 7751da177e4SLinus Torvalds 7761da177e4SLinus Torvalds if (i8042_mux_present) 7771da177e4SLinus Torvalds i8042_set_mux_mode(0, NULL); 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds /* 780de9ce703SDmitry Torokhov * Reset the controller if requested. 781de9ce703SDmitry Torokhov */ 782de9ce703SDmitry Torokhov 783de9ce703SDmitry Torokhov i8042_controller_selftest(); 784de9ce703SDmitry Torokhov 785de9ce703SDmitry Torokhov /* 7861da177e4SLinus Torvalds * Restore the original control register setting. 7871da177e4SLinus Torvalds */ 7881da177e4SLinus Torvalds 789de9ce703SDmitry Torokhov if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) 7901da177e4SLinus Torvalds printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvalds /* 7951da177e4SLinus Torvalds * Here we try to reset everything back to a state in which the BIOS will be 7961da177e4SLinus Torvalds * able to talk to the hardware when rebooting. 7971da177e4SLinus Torvalds */ 7981da177e4SLinus Torvalds 7991da177e4SLinus Torvalds static void i8042_controller_cleanup(void) 8001da177e4SLinus Torvalds { 8011da177e4SLinus Torvalds int i; 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds /* 8041da177e4SLinus Torvalds * Reset anything that is connected to the ports. 8051da177e4SLinus Torvalds */ 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds for (i = 0; i < I8042_NUM_PORTS; i++) 808de9ce703SDmitry Torokhov if (i8042_ports[i].serio) 8091da177e4SLinus Torvalds serio_cleanup(i8042_ports[i].serio); 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds i8042_controller_reset(); 8121da177e4SLinus Torvalds } 8131da177e4SLinus Torvalds 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds /* 8161da177e4SLinus Torvalds * i8042_panic_blink() will flash the keyboard LEDs and is called when 8171da177e4SLinus Torvalds * kernel panics. Flashing LEDs is useful for users running X who may 8181da177e4SLinus Torvalds * not see the console and will help distingushing panics from "real" 8191da177e4SLinus Torvalds * lockups. 8201da177e4SLinus Torvalds * 8211da177e4SLinus Torvalds * Note that DELAY has a limit of 10ms so we will not get stuck here 8221da177e4SLinus Torvalds * waiting for KBC to free up even if KBD interrupt is off 8231da177e4SLinus Torvalds */ 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds static long i8042_panic_blink(long count) 8281da177e4SLinus Torvalds { 8291da177e4SLinus Torvalds long delay = 0; 8301da177e4SLinus Torvalds static long last_blink; 8311da177e4SLinus Torvalds static char led; 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds /* 8341da177e4SLinus Torvalds * We expect frequency to be about 1/2s. KDB uses about 1s. 8351da177e4SLinus Torvalds * Make sure they are different. 8361da177e4SLinus Torvalds */ 8371da177e4SLinus Torvalds if (!i8042_blink_frequency) 8381da177e4SLinus Torvalds return 0; 8391da177e4SLinus Torvalds if (count - last_blink < i8042_blink_frequency) 8401da177e4SLinus Torvalds return 0; 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds led ^= 0x01 | 0x04; 8431da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 8441da177e4SLinus Torvalds DELAY; 8451da177e4SLinus Torvalds i8042_write_data(0xed); /* set leds */ 8461da177e4SLinus Torvalds DELAY; 8471da177e4SLinus Torvalds while (i8042_read_status() & I8042_STR_IBF) 8481da177e4SLinus Torvalds DELAY; 8491da177e4SLinus Torvalds DELAY; 8501da177e4SLinus Torvalds i8042_write_data(led); 8511da177e4SLinus Torvalds DELAY; 8521da177e4SLinus Torvalds last_blink = count; 8531da177e4SLinus Torvalds return delay; 8541da177e4SLinus Torvalds } 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds #undef DELAY 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvalds /* 8591da177e4SLinus Torvalds * Here we try to restore the original BIOS settings 8601da177e4SLinus Torvalds */ 8611da177e4SLinus Torvalds 8623ae5eaecSRussell King static int i8042_suspend(struct platform_device *dev, pm_message_t state) 8631da177e4SLinus Torvalds { 864de9ce703SDmitry Torokhov i8042_controller_cleanup(); 8651da177e4SLinus Torvalds 8661da177e4SLinus Torvalds return 0; 8671da177e4SLinus Torvalds } 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds /* 8711da177e4SLinus Torvalds * Here we try to reset everything back to a state in which suspended 8721da177e4SLinus Torvalds */ 8731da177e4SLinus Torvalds 8743ae5eaecSRussell King static int i8042_resume(struct platform_device *dev) 8751da177e4SLinus Torvalds { 876de9ce703SDmitry Torokhov int error; 8771da177e4SLinus Torvalds 878de9ce703SDmitry Torokhov error = i8042_controller_check(); 879de9ce703SDmitry Torokhov if (error) 880de9ce703SDmitry Torokhov return error; 8812673c836SVojtech Pavlik 882de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 883de9ce703SDmitry Torokhov if (error) 884de9ce703SDmitry Torokhov return error; 885de9ce703SDmitry Torokhov 886de9ce703SDmitry Torokhov /* 887de9ce703SDmitry Torokhov * Restore pre-resume CTR value and disable all ports 888de9ce703SDmitry Torokhov */ 889de9ce703SDmitry Torokhov 890de9ce703SDmitry Torokhov i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; 891de9ce703SDmitry Torokhov i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); 8922673c836SVojtech Pavlik if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { 893de9ce703SDmitry Torokhov printk(KERN_ERR "i8042: Can't write CTR to resume\n"); 894de9ce703SDmitry Torokhov return -EIO; 8951da177e4SLinus Torvalds } 8961da177e4SLinus Torvalds 897de9ce703SDmitry Torokhov if (i8042_mux_present) { 8981da177e4SLinus Torvalds if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) 899de9ce703SDmitry Torokhov printk(KERN_WARNING 900de9ce703SDmitry Torokhov "i8042: failed to resume active multiplexor, " 901de9ce703SDmitry Torokhov "mouse won't work.\n"); 902de9ce703SDmitry Torokhov } else if (i8042_ports[I8042_AUX_PORT_NO].serio) 903de9ce703SDmitry Torokhov i8042_enable_aux_port(); 9041da177e4SLinus Torvalds 905de9ce703SDmitry Torokhov if (i8042_ports[I8042_KBD_PORT_NO].serio) 906de9ce703SDmitry Torokhov i8042_enable_kbd_port(); 9071da177e4SLinus Torvalds 908*7d12e780SDavid Howells i8042_interrupt(0, NULL); 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds return 0; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds 9131da177e4SLinus Torvalds /* 9141da177e4SLinus Torvalds * We need to reset the 8042 back to original mode on system shutdown, 9151da177e4SLinus Torvalds * because otherwise BIOSes will be confused. 9161da177e4SLinus Torvalds */ 9171da177e4SLinus Torvalds 9183ae5eaecSRussell King static void i8042_shutdown(struct platform_device *dev) 9191da177e4SLinus Torvalds { 9201da177e4SLinus Torvalds i8042_controller_cleanup(); 9211da177e4SLinus Torvalds } 9221da177e4SLinus Torvalds 92387fd6318SDmitry Torokhov static int __devinit i8042_create_kbd_port(void) 9241da177e4SLinus Torvalds { 9251da177e4SLinus Torvalds struct serio *serio; 9261da177e4SLinus Torvalds struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; 9271da177e4SLinus Torvalds 928d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 9290854e52dSDmitry Torokhov if (!serio) 9300854e52dSDmitry Torokhov return -ENOMEM; 9310854e52dSDmitry Torokhov 9321da177e4SLinus Torvalds serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; 9331da177e4SLinus Torvalds serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; 9341da177e4SLinus Torvalds serio->start = i8042_start; 9351da177e4SLinus Torvalds serio->stop = i8042_stop; 9361da177e4SLinus Torvalds serio->port_data = port; 9371da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 938de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); 9391da177e4SLinus Torvalds strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds port->serio = serio; 942de9ce703SDmitry Torokhov port->irq = I8042_KBD_IRQ; 9430854e52dSDmitry Torokhov 944de9ce703SDmitry Torokhov return 0; 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 947de9ce703SDmitry Torokhov static int __devinit i8042_create_aux_port(int idx) 9481da177e4SLinus Torvalds { 9491da177e4SLinus Torvalds struct serio *serio; 950de9ce703SDmitry Torokhov int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; 951de9ce703SDmitry Torokhov struct i8042_port *port = &i8042_ports[port_no]; 9521da177e4SLinus Torvalds 953d39969deSDmitry Torokhov serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 9540854e52dSDmitry Torokhov if (!serio) 9550854e52dSDmitry Torokhov return -ENOMEM; 9560854e52dSDmitry Torokhov 9571da177e4SLinus Torvalds serio->id.type = SERIO_8042; 9581da177e4SLinus Torvalds serio->write = i8042_aux_write; 9591da177e4SLinus Torvalds serio->start = i8042_start; 9601da177e4SLinus Torvalds serio->stop = i8042_stop; 9611da177e4SLinus Torvalds serio->port_data = port; 9621da177e4SLinus Torvalds serio->dev.parent = &i8042_platform_device->dev; 963de9ce703SDmitry Torokhov if (idx < 0) { 964de9ce703SDmitry Torokhov strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); 9651da177e4SLinus Torvalds strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 966de9ce703SDmitry Torokhov } else { 967de9ce703SDmitry Torokhov snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); 968de9ce703SDmitry Torokhov snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds port->serio = serio; 972de9ce703SDmitry Torokhov port->mux = idx; 973de9ce703SDmitry Torokhov port->irq = I8042_AUX_IRQ; 9740854e52dSDmitry Torokhov 975de9ce703SDmitry Torokhov return 0; 976de9ce703SDmitry Torokhov } 977de9ce703SDmitry Torokhov 978de9ce703SDmitry Torokhov static void __devinit i8042_free_kbd_port(void) 979de9ce703SDmitry Torokhov { 980de9ce703SDmitry Torokhov kfree(i8042_ports[I8042_KBD_PORT_NO].serio); 981de9ce703SDmitry Torokhov i8042_ports[I8042_KBD_PORT_NO].serio = NULL; 982de9ce703SDmitry Torokhov } 983de9ce703SDmitry Torokhov 984de9ce703SDmitry Torokhov static void __devinit i8042_free_aux_ports(void) 985de9ce703SDmitry Torokhov { 986de9ce703SDmitry Torokhov int i; 987de9ce703SDmitry Torokhov 988de9ce703SDmitry Torokhov for (i = I8042_AUX_PORT_NO; i < I8042_NUM_PORTS; i++) { 989de9ce703SDmitry Torokhov kfree(i8042_ports[i].serio); 990de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 991de9ce703SDmitry Torokhov } 992de9ce703SDmitry Torokhov } 993de9ce703SDmitry Torokhov 994de9ce703SDmitry Torokhov static void __devinit i8042_register_ports(void) 995de9ce703SDmitry Torokhov { 996de9ce703SDmitry Torokhov int i; 997de9ce703SDmitry Torokhov 998de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 999de9ce703SDmitry Torokhov if (i8042_ports[i].serio) { 1000de9ce703SDmitry Torokhov printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", 1001de9ce703SDmitry Torokhov i8042_ports[i].serio->name, 1002de9ce703SDmitry Torokhov (unsigned long) I8042_DATA_REG, 1003de9ce703SDmitry Torokhov (unsigned long) I8042_COMMAND_REG, 1004de9ce703SDmitry Torokhov i8042_ports[i].irq); 1005de9ce703SDmitry Torokhov serio_register_port(i8042_ports[i].serio); 1006de9ce703SDmitry Torokhov } 1007de9ce703SDmitry Torokhov } 1008de9ce703SDmitry Torokhov } 1009de9ce703SDmitry Torokhov 1010de9ce703SDmitry Torokhov static void __devinit i8042_unregister_ports(void) 1011de9ce703SDmitry Torokhov { 1012de9ce703SDmitry Torokhov int i; 1013de9ce703SDmitry Torokhov 1014de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_PORTS; i++) { 1015de9ce703SDmitry Torokhov if (i8042_ports[i].serio) { 1016de9ce703SDmitry Torokhov serio_unregister_port(i8042_ports[i].serio); 1017de9ce703SDmitry Torokhov i8042_ports[i].serio = NULL; 1018de9ce703SDmitry Torokhov } 1019de9ce703SDmitry Torokhov } 1020de9ce703SDmitry Torokhov } 1021de9ce703SDmitry Torokhov 1022de9ce703SDmitry Torokhov static void i8042_free_irqs(void) 1023de9ce703SDmitry Torokhov { 1024de9ce703SDmitry Torokhov if (i8042_aux_irq_registered) 1025de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1026de9ce703SDmitry Torokhov if (i8042_kbd_irq_registered) 1027de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1028de9ce703SDmitry Torokhov 1029de9ce703SDmitry Torokhov i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; 1030de9ce703SDmitry Torokhov } 1031de9ce703SDmitry Torokhov 1032de9ce703SDmitry Torokhov static int __devinit i8042_setup_aux(void) 1033de9ce703SDmitry Torokhov { 1034de9ce703SDmitry Torokhov int (*aux_enable)(void); 1035de9ce703SDmitry Torokhov int error; 1036de9ce703SDmitry Torokhov int i; 1037de9ce703SDmitry Torokhov 1038de9ce703SDmitry Torokhov if (i8042_check_aux()) 1039de9ce703SDmitry Torokhov return -ENODEV; 1040de9ce703SDmitry Torokhov 1041de9ce703SDmitry Torokhov if (i8042_nomux || i8042_check_mux()) { 1042de9ce703SDmitry Torokhov error = i8042_create_aux_port(-1); 1043de9ce703SDmitry Torokhov if (error) 1044de9ce703SDmitry Torokhov goto err_free_ports; 1045de9ce703SDmitry Torokhov aux_enable = i8042_enable_aux_port; 1046de9ce703SDmitry Torokhov } else { 1047de9ce703SDmitry Torokhov for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { 1048de9ce703SDmitry Torokhov error = i8042_create_aux_port(i); 1049de9ce703SDmitry Torokhov if (error) 1050de9ce703SDmitry Torokhov goto err_free_ports; 1051de9ce703SDmitry Torokhov } 1052de9ce703SDmitry Torokhov aux_enable = i8042_enable_mux_ports; 1053de9ce703SDmitry Torokhov } 1054de9ce703SDmitry Torokhov 1055de9ce703SDmitry Torokhov error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, 1056de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1057de9ce703SDmitry Torokhov if (error) 1058de9ce703SDmitry Torokhov goto err_free_ports; 1059de9ce703SDmitry Torokhov 1060de9ce703SDmitry Torokhov if (aux_enable()) 1061de9ce703SDmitry Torokhov goto err_free_irq; 1062de9ce703SDmitry Torokhov 1063de9ce703SDmitry Torokhov i8042_aux_irq_registered = 1; 1064de9ce703SDmitry Torokhov return 0; 1065de9ce703SDmitry Torokhov 1066de9ce703SDmitry Torokhov err_free_irq: 1067de9ce703SDmitry Torokhov free_irq(I8042_AUX_IRQ, i8042_platform_device); 1068de9ce703SDmitry Torokhov err_free_ports: 1069de9ce703SDmitry Torokhov i8042_free_aux_ports(); 1070de9ce703SDmitry Torokhov return error; 1071de9ce703SDmitry Torokhov } 1072de9ce703SDmitry Torokhov 1073de9ce703SDmitry Torokhov static int __devinit i8042_setup_kbd(void) 1074de9ce703SDmitry Torokhov { 1075de9ce703SDmitry Torokhov int error; 1076de9ce703SDmitry Torokhov 1077de9ce703SDmitry Torokhov error = i8042_create_kbd_port(); 1078de9ce703SDmitry Torokhov if (error) 1079de9ce703SDmitry Torokhov return error; 1080de9ce703SDmitry Torokhov 1081de9ce703SDmitry Torokhov error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, 1082de9ce703SDmitry Torokhov "i8042", i8042_platform_device); 1083de9ce703SDmitry Torokhov if (error) 1084de9ce703SDmitry Torokhov goto err_free_port; 1085de9ce703SDmitry Torokhov 1086de9ce703SDmitry Torokhov error = i8042_enable_kbd_port(); 1087de9ce703SDmitry Torokhov if (error) 1088de9ce703SDmitry Torokhov goto err_free_irq; 1089de9ce703SDmitry Torokhov 1090de9ce703SDmitry Torokhov i8042_kbd_irq_registered = 1; 1091de9ce703SDmitry Torokhov return 0; 1092de9ce703SDmitry Torokhov 1093de9ce703SDmitry Torokhov err_free_irq: 1094de9ce703SDmitry Torokhov free_irq(I8042_KBD_IRQ, i8042_platform_device); 1095de9ce703SDmitry Torokhov err_free_port: 1096de9ce703SDmitry Torokhov i8042_free_kbd_port(); 1097de9ce703SDmitry Torokhov return error; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds 110087fd6318SDmitry Torokhov static int __devinit i8042_probe(struct platform_device *dev) 11011da177e4SLinus Torvalds { 1102de9ce703SDmitry Torokhov int error; 11031da177e4SLinus Torvalds 1104de9ce703SDmitry Torokhov error = i8042_controller_selftest(); 1105de9ce703SDmitry Torokhov if (error) 1106de9ce703SDmitry Torokhov return error; 11071da177e4SLinus Torvalds 1108de9ce703SDmitry Torokhov error = i8042_controller_init(); 1109de9ce703SDmitry Torokhov if (error) 1110de9ce703SDmitry Torokhov return error; 11111da177e4SLinus Torvalds 1112de9ce703SDmitry Torokhov if (!i8042_noaux) { 1113de9ce703SDmitry Torokhov error = i8042_setup_aux(); 1114de9ce703SDmitry Torokhov if (error && error != -ENODEV && error != -EBUSY) 1115de9ce703SDmitry Torokhov goto out_fail; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 1118945ef0d4SDmitry Torokhov if (!i8042_nokbd) { 1119de9ce703SDmitry Torokhov error = i8042_setup_kbd(); 1120de9ce703SDmitry Torokhov if (error) 1121de9ce703SDmitry Torokhov goto out_fail; 1122945ef0d4SDmitry Torokhov } 1123945ef0d4SDmitry Torokhov 1124de9ce703SDmitry Torokhov /* 1125de9ce703SDmitry Torokhov * Ok, everything is ready, let's register all serio ports 1126de9ce703SDmitry Torokhov */ 1127de9ce703SDmitry Torokhov i8042_register_ports(); 11281da177e4SLinus Torvalds 11291da177e4SLinus Torvalds return 0; 11300854e52dSDmitry Torokhov 1131de9ce703SDmitry Torokhov out_fail: 1132de9ce703SDmitry Torokhov i8042_free_aux_ports(); /* in case KBD failed but AUX not */ 1133de9ce703SDmitry Torokhov i8042_free_irqs(); 1134de9ce703SDmitry Torokhov i8042_controller_reset(); 11350854e52dSDmitry Torokhov 1136de9ce703SDmitry Torokhov return error; 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds 113987fd6318SDmitry Torokhov static int __devexit i8042_remove(struct platform_device *dev) 11401da177e4SLinus Torvalds { 1141de9ce703SDmitry Torokhov i8042_unregister_ports(); 1142de9ce703SDmitry Torokhov i8042_free_irqs(); 1143de9ce703SDmitry Torokhov i8042_controller_reset(); 11441da177e4SLinus Torvalds 114587fd6318SDmitry Torokhov return 0; 114687fd6318SDmitry Torokhov } 114787fd6318SDmitry Torokhov 114887fd6318SDmitry Torokhov static struct platform_driver i8042_driver = { 114987fd6318SDmitry Torokhov .driver = { 115087fd6318SDmitry Torokhov .name = "i8042", 115187fd6318SDmitry Torokhov .owner = THIS_MODULE, 115287fd6318SDmitry Torokhov }, 115387fd6318SDmitry Torokhov .probe = i8042_probe, 115487fd6318SDmitry Torokhov .remove = __devexit_p(i8042_remove), 115587fd6318SDmitry Torokhov .suspend = i8042_suspend, 115687fd6318SDmitry Torokhov .resume = i8042_resume, 115787fd6318SDmitry Torokhov .shutdown = i8042_shutdown, 115887fd6318SDmitry Torokhov }; 115987fd6318SDmitry Torokhov 116087fd6318SDmitry Torokhov static int __init i8042_init(void) 116187fd6318SDmitry Torokhov { 116287fd6318SDmitry Torokhov int err; 116387fd6318SDmitry Torokhov 116487fd6318SDmitry Torokhov dbg_init(); 116587fd6318SDmitry Torokhov 116687fd6318SDmitry Torokhov err = i8042_platform_init(); 116787fd6318SDmitry Torokhov if (err) 116887fd6318SDmitry Torokhov return err; 116987fd6318SDmitry Torokhov 1170de9ce703SDmitry Torokhov err = i8042_controller_check(); 1171de9ce703SDmitry Torokhov if (err) 1172de9ce703SDmitry Torokhov goto err_platform_exit; 117387fd6318SDmitry Torokhov 117487fd6318SDmitry Torokhov err = platform_driver_register(&i8042_driver); 117587fd6318SDmitry Torokhov if (err) 117687fd6318SDmitry Torokhov goto err_platform_exit; 117787fd6318SDmitry Torokhov 117887fd6318SDmitry Torokhov i8042_platform_device = platform_device_alloc("i8042", -1); 117987fd6318SDmitry Torokhov if (!i8042_platform_device) { 118087fd6318SDmitry Torokhov err = -ENOMEM; 118187fd6318SDmitry Torokhov goto err_unregister_driver; 118287fd6318SDmitry Torokhov } 118387fd6318SDmitry Torokhov 118487fd6318SDmitry Torokhov err = platform_device_add(i8042_platform_device); 118587fd6318SDmitry Torokhov if (err) 118687fd6318SDmitry Torokhov goto err_free_device; 118787fd6318SDmitry Torokhov 1188de9ce703SDmitry Torokhov panic_blink = i8042_panic_blink; 1189de9ce703SDmitry Torokhov 119087fd6318SDmitry Torokhov return 0; 119187fd6318SDmitry Torokhov 119287fd6318SDmitry Torokhov err_free_device: 119387fd6318SDmitry Torokhov platform_device_put(i8042_platform_device); 119487fd6318SDmitry Torokhov err_unregister_driver: 119587fd6318SDmitry Torokhov platform_driver_unregister(&i8042_driver); 119687fd6318SDmitry Torokhov err_platform_exit: 119787fd6318SDmitry Torokhov i8042_platform_exit(); 119887fd6318SDmitry Torokhov 119987fd6318SDmitry Torokhov return err; 120087fd6318SDmitry Torokhov } 120187fd6318SDmitry Torokhov 120287fd6318SDmitry Torokhov static void __exit i8042_exit(void) 120387fd6318SDmitry Torokhov { 12041da177e4SLinus Torvalds platform_device_unregister(i8042_platform_device); 12053ae5eaecSRussell King platform_driver_unregister(&i8042_driver); 12061da177e4SLinus Torvalds i8042_platform_exit(); 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds panic_blink = NULL; 12091da177e4SLinus Torvalds } 12101da177e4SLinus Torvalds 12111da177e4SLinus Torvalds module_init(i8042_init); 12121da177e4SLinus Torvalds module_exit(i8042_exit); 1213