diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2006-09-10 21:57:21 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2006-09-10 21:57:21 -0400 |
commit | de9ce703c6b807b1dfef5942df4f2fadd0fdb67a (patch) | |
tree | eb3e97c34d0d72fbd52cd688ef3f4ad3c559ad36 /drivers/input/serio/i8042.c | |
parent | 6d2750c167d47a97936cf4415165205f945c08f8 (diff) |
Input: i8042 - get rid of polling timer
Remove polling timer that was used to detect keybord/mice hotplug and
register both IRQs right away instead of waiting for a driver to
attach to a port.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r-- | drivers/input/serio/i8042.c | 741 |
1 files changed, 388 insertions, 353 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 06a3f25657dd..1bb0c76a9259 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -90,46 +90,24 @@ static DEFINE_SPINLOCK(i8042_lock); | |||
90 | struct i8042_port { | 90 | struct i8042_port { |
91 | struct serio *serio; | 91 | struct serio *serio; |
92 | int irq; | 92 | int irq; |
93 | unsigned char disable; | ||
94 | unsigned char irqen; | ||
95 | unsigned char exists; | 93 | unsigned char exists; |
96 | signed char mux; | 94 | signed char mux; |
97 | char name[8]; | ||
98 | }; | 95 | }; |
99 | 96 | ||
100 | #define I8042_KBD_PORT_NO 0 | 97 | #define I8042_KBD_PORT_NO 0 |
101 | #define I8042_AUX_PORT_NO 1 | 98 | #define I8042_AUX_PORT_NO 1 |
102 | #define I8042_MUX_PORT_NO 2 | 99 | #define I8042_MUX_PORT_NO 2 |
103 | #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) | 100 | #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) |
104 | static struct i8042_port i8042_ports[I8042_NUM_PORTS] = { | 101 | |
105 | { | 102 | static struct i8042_port i8042_ports[I8042_NUM_PORTS]; |
106 | .disable = I8042_CTR_KBDDIS, | ||
107 | .irqen = I8042_CTR_KBDINT, | ||
108 | .mux = -1, | ||
109 | .name = "KBD", | ||
110 | }, | ||
111 | { | ||
112 | .disable = I8042_CTR_AUXDIS, | ||
113 | .irqen = I8042_CTR_AUXINT, | ||
114 | .mux = -1, | ||
115 | .name = "AUX", | ||
116 | } | ||
117 | }; | ||
118 | 103 | ||
119 | static unsigned char i8042_initial_ctr; | 104 | static unsigned char i8042_initial_ctr; |
120 | static unsigned char i8042_ctr; | 105 | static unsigned char i8042_ctr; |
121 | static unsigned char i8042_mux_open; | ||
122 | static unsigned char i8042_mux_present; | 106 | static unsigned char i8042_mux_present; |
123 | static struct timer_list i8042_timer; | 107 | static unsigned char i8042_kbd_irq_registered; |
108 | static unsigned char i8042_aux_irq_registered; | ||
124 | static struct platform_device *i8042_platform_device; | 109 | static struct platform_device *i8042_platform_device; |
125 | 110 | ||
126 | |||
127 | /* | ||
128 | * Shared IRQ's require a device pointer, but this driver doesn't support | ||
129 | * multiple devices | ||
130 | */ | ||
131 | #define i8042_request_irq_cookie (&i8042_timer) | ||
132 | |||
133 | static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 111 | static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
134 | 112 | ||
135 | /* | 113 | /* |
@@ -141,6 +119,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |||
141 | static int i8042_wait_read(void) | 119 | static int i8042_wait_read(void) |
142 | { | 120 | { |
143 | int i = 0; | 121 | int i = 0; |
122 | |||
144 | while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { | 123 | while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { |
145 | udelay(50); | 124 | udelay(50); |
146 | i++; | 125 | i++; |
@@ -151,6 +130,7 @@ static int i8042_wait_read(void) | |||
151 | static int i8042_wait_write(void) | 130 | static int i8042_wait_write(void) |
152 | { | 131 | { |
153 | int i = 0; | 132 | int i = 0; |
133 | |||
154 | while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { | 134 | while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { |
155 | udelay(50); | 135 | udelay(50); |
156 | i++; | 136 | i++; |
@@ -192,48 +172,57 @@ static int i8042_flush(void) | |||
192 | * encoded in bits 8-11 of the command number. | 172 | * encoded in bits 8-11 of the command number. |
193 | */ | 173 | */ |
194 | 174 | ||
195 | static int i8042_command(unsigned char *param, int command) | 175 | static int __i8042_command(unsigned char *param, int command) |
196 | { | 176 | { |
197 | unsigned long flags; | 177 | int i, error; |
198 | int i, retval, auxerr = 0; | ||
199 | 178 | ||
200 | if (i8042_noloop && command == I8042_CMD_AUX_LOOP) | 179 | if (i8042_noloop && command == I8042_CMD_AUX_LOOP) |
201 | return -1; | 180 | return -1; |
202 | 181 | ||
203 | spin_lock_irqsave(&i8042_lock, flags); | 182 | error = i8042_wait_write(); |
204 | 183 | if (error) | |
205 | if ((retval = i8042_wait_write())) | 184 | return error; |
206 | goto out; | ||
207 | 185 | ||
208 | dbg("%02x -> i8042 (command)", command & 0xff); | 186 | dbg("%02x -> i8042 (command)", command & 0xff); |
209 | i8042_write_command(command & 0xff); | 187 | i8042_write_command(command & 0xff); |
210 | 188 | ||
211 | for (i = 0; i < ((command >> 12) & 0xf); i++) { | 189 | for (i = 0; i < ((command >> 12) & 0xf); i++) { |
212 | if ((retval = i8042_wait_write())) | 190 | error = i8042_wait_write(); |
213 | goto out; | 191 | if (error) |
192 | return error; | ||
214 | dbg("%02x -> i8042 (parameter)", param[i]); | 193 | dbg("%02x -> i8042 (parameter)", param[i]); |
215 | i8042_write_data(param[i]); | 194 | i8042_write_data(param[i]); |
216 | } | 195 | } |
217 | 196 | ||
218 | for (i = 0; i < ((command >> 8) & 0xf); i++) { | 197 | for (i = 0; i < ((command >> 8) & 0xf); i++) { |
219 | if ((retval = i8042_wait_read())) | 198 | error = i8042_wait_read(); |
220 | goto out; | 199 | if (error) { |
200 | dbg(" -- i8042 (timeout)"); | ||
201 | return error; | ||
202 | } | ||
221 | 203 | ||
222 | if (command == I8042_CMD_AUX_LOOP && | 204 | if (command == I8042_CMD_AUX_LOOP && |
223 | !(i8042_read_status() & I8042_STR_AUXDATA)) { | 205 | !(i8042_read_status() & I8042_STR_AUXDATA)) { |
224 | retval = auxerr = -1; | 206 | dbg(" -- i8042 (auxerr)"); |
225 | goto out; | 207 | return -1; |
226 | } | 208 | } |
227 | 209 | ||
228 | param[i] = i8042_read_data(); | 210 | param[i] = i8042_read_data(); |
229 | dbg("%02x <- i8042 (return)", param[i]); | 211 | dbg("%02x <- i8042 (return)", param[i]); |
230 | } | 212 | } |
231 | 213 | ||
232 | if (retval) | 214 | return 0; |
233 | dbg(" -- i8042 (%s)", auxerr ? "auxerr" : "timeout"); | 215 | } |
234 | 216 | ||
235 | out: | 217 | static int i8042_command(unsigned char *param, int command) |
218 | { | ||
219 | unsigned long flags; | ||
220 | int retval; | ||
221 | |||
222 | spin_lock_irqsave(&i8042_lock, flags); | ||
223 | retval = __i8042_command(param, command); | ||
236 | spin_unlock_irqrestore(&i8042_lock, flags); | 224 | spin_unlock_irqrestore(&i8042_lock, flags); |
225 | |||
237 | return retval; | 226 | return retval; |
238 | } | 227 | } |
239 | 228 | ||
@@ -248,7 +237,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) | |||
248 | 237 | ||
249 | spin_lock_irqsave(&i8042_lock, flags); | 238 | spin_lock_irqsave(&i8042_lock, flags); |
250 | 239 | ||
251 | if(!(retval = i8042_wait_write())) { | 240 | if (!(retval = i8042_wait_write())) { |
252 | dbg("%02x -> i8042 (kbd-data)", c); | 241 | dbg("%02x -> i8042 (kbd-data)", c); |
253 | i8042_write_data(c); | 242 | i8042_write_data(c); |
254 | } | 243 | } |
@@ -287,100 +276,6 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
287 | } | 276 | } |
288 | 277 | ||
289 | /* | 278 | /* |
290 | * i8042_activate_port() enables port on a chip. | ||
291 | */ | ||
292 | |||
293 | static int i8042_activate_port(struct i8042_port *port) | ||
294 | { | ||
295 | if (!port->serio) | ||
296 | return -1; | ||
297 | |||
298 | i8042_flush(); | ||
299 | |||
300 | /* | ||
301 | * Enable port again here because it is disabled if we are | ||
302 | * resuming (normally it is enabled already). | ||
303 | */ | ||
304 | i8042_ctr &= ~port->disable; | ||
305 | |||
306 | i8042_ctr |= port->irqen; | ||
307 | |||
308 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
309 | i8042_ctr &= ~port->irqen; | ||
310 | return -1; | ||
311 | } | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * i8042_open() is called when a port is open by the higher layer. | ||
319 | * It allocates the interrupt and calls i8042_enable_port. | ||
320 | */ | ||
321 | |||
322 | static int i8042_open(struct serio *serio) | ||
323 | { | ||
324 | struct i8042_port *port = serio->port_data; | ||
325 | |||
326 | if (port->mux != -1) | ||
327 | if (i8042_mux_open++) | ||
328 | return 0; | ||
329 | |||
330 | if (request_irq(port->irq, i8042_interrupt, | ||
331 | IRQF_SHARED, "i8042", i8042_request_irq_cookie)) { | ||
332 | printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name); | ||
333 | goto irq_fail; | ||
334 | } | ||
335 | |||
336 | if (i8042_activate_port(port)) { | ||
337 | printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name); | ||
338 | goto activate_fail; | ||
339 | } | ||
340 | |||
341 | i8042_interrupt(0, NULL, NULL); | ||
342 | |||
343 | return 0; | ||
344 | |||
345 | activate_fail: | ||
346 | free_irq(port->irq, i8042_request_irq_cookie); | ||
347 | |||
348 | irq_fail: | ||
349 | serio_unregister_port_delayed(serio); | ||
350 | |||
351 | return -1; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * i8042_close() frees the interrupt, so that it can possibly be used | ||
356 | * by another driver. We never know - if the user doesn't have a mouse, | ||
357 | * the BIOS could have used the AUX interrupt for PCI. | ||
358 | */ | ||
359 | |||
360 | static void i8042_close(struct serio *serio) | ||
361 | { | ||
362 | struct i8042_port *port = serio->port_data; | ||
363 | |||
364 | if (port->mux != -1) | ||
365 | if (--i8042_mux_open) | ||
366 | return; | ||
367 | |||
368 | i8042_ctr &= ~port->irqen; | ||
369 | |||
370 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
371 | printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name); | ||
372 | /* | ||
373 | * We still want to continue and free IRQ so if more data keeps coming in | ||
374 | * kernel will just ignore the irq. | ||
375 | */ | ||
376 | } | ||
377 | |||
378 | free_irq(port->irq, i8042_request_irq_cookie); | ||
379 | |||
380 | i8042_flush(); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * i8042_start() is called by serio core when port is about to finish | 279 | * i8042_start() is called by serio core when port is about to finish |
385 | * registering. It will mark port as existing so i8042_interrupt can | 280 | * registering. It will mark port as existing so i8042_interrupt can |
386 | * start sending data through it. | 281 | * start sending data through it. |
@@ -423,8 +318,6 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
423 | unsigned int port_no; | 318 | unsigned int port_no; |
424 | int ret; | 319 | int ret; |
425 | 320 | ||
426 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | ||
427 | |||
428 | spin_lock_irqsave(&i8042_lock, flags); | 321 | spin_lock_irqsave(&i8042_lock, flags); |
429 | str = i8042_read_status(); | 322 | str = i8042_read_status(); |
430 | if (unlikely(~str & I8042_STR_OBF)) { | 323 | if (unlikely(~str & I8042_STR_OBF)) { |
@@ -480,8 +373,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
480 | 373 | ||
481 | port = &i8042_ports[port_no]; | 374 | port = &i8042_ports[port_no]; |
482 | 375 | ||
483 | dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", | 376 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", |
484 | data, port->name, irq, | 377 | data, port_no, irq, |
485 | dfl & SERIO_PARITY ? ", bad parity" : "", | 378 | dfl & SERIO_PARITY ? ", bad parity" : "", |
486 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 379 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
487 | 380 | ||
@@ -494,6 +387,58 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
494 | } | 387 | } |
495 | 388 | ||
496 | /* | 389 | /* |
390 | * i8042_enable_kbd_port enables keybaord port on chip | ||
391 | */ | ||
392 | |||
393 | static int i8042_enable_kbd_port(void) | ||
394 | { | ||
395 | i8042_ctr &= ~I8042_CTR_KBDDIS; | ||
396 | i8042_ctr |= I8042_CTR_KBDINT; | ||
397 | |||
398 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
399 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | ||
400 | return -EIO; | ||
401 | } | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * i8042_enable_aux_port enables AUX (mouse) port on chip | ||
408 | */ | ||
409 | |||
410 | static int i8042_enable_aux_port(void) | ||
411 | { | ||
412 | i8042_ctr &= ~I8042_CTR_AUXDIS; | ||
413 | i8042_ctr |= I8042_CTR_AUXINT; | ||
414 | |||
415 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
416 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | ||
417 | return -EIO; | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * i8042_enable_mux_ports enables 4 individual AUX ports after | ||
425 | * the controller has been switched into Multiplexed mode | ||
426 | */ | ||
427 | |||
428 | static int i8042_enable_mux_ports(void) | ||
429 | { | ||
430 | unsigned char param; | ||
431 | int i; | ||
432 | |||
433 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | ||
434 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | ||
435 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | ||
436 | } | ||
437 | |||
438 | return i8042_enable_aux_port(); | ||
439 | } | ||
440 | |||
441 | /* | ||
497 | * i8042_set_mux_mode checks whether the controller has an active | 442 | * i8042_set_mux_mode checks whether the controller has an active |
498 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. | 443 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. |
499 | */ | 444 | */ |
@@ -510,8 +455,7 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
510 | 455 | ||
511 | /* | 456 | /* |
512 | * Internal loopback test - send three bytes, they should come back from the | 457 | * Internal loopback test - send three bytes, they should come back from the |
513 | * mouse interface, the last should be version. Note that we negate mouseport | 458 | * mouse interface, the last should be version. |
514 | * command responses for the i8042_check_aux() routine. | ||
515 | */ | 459 | */ |
516 | 460 | ||
517 | param = 0xf0; | 461 | param = 0xf0; |
@@ -530,67 +474,67 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
530 | return 0; | 474 | return 0; |
531 | } | 475 | } |
532 | 476 | ||
533 | |||
534 | /* | 477 | /* |
535 | * i8042_enable_mux_ports enables 4 individual AUX ports after | 478 | * i8042_check_mux() checks whether the controller supports the PS/2 Active |
536 | * the controller has been switched into Multiplexed mode | 479 | * Multiplexing specification by Synaptics, Phoenix, Insyde and |
480 | * LCS/Telegraphics. | ||
537 | */ | 481 | */ |
538 | 482 | ||
539 | static int i8042_enable_mux_ports(void) | 483 | static int __devinit i8042_check_mux(void) |
540 | { | 484 | { |
541 | unsigned char param; | 485 | unsigned char mux_version; |
542 | int i; | 486 | |
487 | if (i8042_set_mux_mode(1, &mux_version)) | ||
488 | return -1; | ||
489 | |||
543 | /* | 490 | /* |
544 | * Disable all muxed ports by disabling AUX. | 491 | * Workaround for interference with USB Legacy emulation |
492 | * that causes a v10.12 MUX to be found. | ||
545 | */ | 493 | */ |
494 | if (mux_version == 0xAC) | ||
495 | return -1; | ||
496 | |||
497 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | ||
498 | (mux_version >> 4) & 0xf, mux_version & 0xf); | ||
546 | 499 | ||
500 | /* | ||
501 | * Disable all muxed ports by disabling AUX. | ||
502 | */ | ||
547 | i8042_ctr |= I8042_CTR_AUXDIS; | 503 | i8042_ctr |= I8042_CTR_AUXDIS; |
548 | i8042_ctr &= ~I8042_CTR_AUXINT; | 504 | i8042_ctr &= ~I8042_CTR_AUXINT; |
549 | 505 | ||
550 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 506 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
551 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); | 507 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); |
552 | return -1; | 508 | return -EIO; |
553 | } | 509 | } |
554 | 510 | ||
555 | /* | 511 | i8042_mux_present = 1; |
556 | * Enable all muxed ports. | ||
557 | */ | ||
558 | |||
559 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | ||
560 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | ||
561 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | ||
562 | } | ||
563 | 512 | ||
564 | return 0; | 513 | return 0; |
565 | } | 514 | } |
566 | 515 | ||
567 | |||
568 | /* | 516 | /* |
569 | * i8042_check_mux() checks whether the controller supports the PS/2 Active | 517 | * The following is used to test AUX IRQ delivery. |
570 | * Multiplexing specification by Synaptics, Phoenix, Insyde and | ||
571 | * LCS/Telegraphics. | ||
572 | */ | 518 | */ |
519 | static struct completion i8042_aux_irq_delivered __devinitdata; | ||
520 | static int i8042_irq_being_tested __devinitdata; | ||
573 | 521 | ||
574 | static int __devinit i8042_check_mux(void) | 522 | static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id, struct pt_regs *regs) |
575 | { | 523 | { |
576 | unsigned char mux_version; | 524 | unsigned long flags; |
577 | 525 | unsigned char str, data; | |
578 | if (i8042_set_mux_mode(1, &mux_version)) | ||
579 | return -1; | ||
580 | |||
581 | /* Workaround for interference with USB Legacy emulation */ | ||
582 | /* that causes a v10.12 MUX to be found. */ | ||
583 | if (mux_version == 0xAC) | ||
584 | return -1; | ||
585 | |||
586 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | ||
587 | (mux_version >> 4) & 0xf, mux_version & 0xf); | ||
588 | 526 | ||
589 | if (i8042_enable_mux_ports()) | 527 | spin_lock_irqsave(&i8042_lock, flags); |
590 | return -1; | 528 | str = i8042_read_status(); |
529 | if (str & I8042_STR_OBF) { | ||
530 | data = i8042_read_data(); | ||
531 | if (i8042_irq_being_tested && | ||
532 | data == 0xa5 && (str & I8042_STR_AUXDATA)) | ||
533 | complete(&i8042_aux_irq_delivered); | ||
534 | } | ||
535 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
591 | 536 | ||
592 | i8042_mux_present = 1; | 537 | return IRQ_HANDLED; |
593 | return 0; | ||
594 | } | 538 | } |
595 | 539 | ||
596 | 540 | ||
@@ -601,18 +545,10 @@ static int __devinit i8042_check_mux(void) | |||
601 | 545 | ||
602 | static int __devinit i8042_check_aux(void) | 546 | static int __devinit i8042_check_aux(void) |
603 | { | 547 | { |
548 | int retval = -1; | ||
549 | int irq_registered = 0; | ||
550 | unsigned long flags; | ||
604 | unsigned char param; | 551 | unsigned char param; |
605 | static int i8042_check_aux_cookie; | ||
606 | |||
607 | /* | ||
608 | * Check if AUX irq is available. If it isn't, then there is no point | ||
609 | * in trying to detect AUX presence. | ||
610 | */ | ||
611 | |||
612 | if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt, | ||
613 | IRQF_SHARED, "i8042", &i8042_check_aux_cookie)) | ||
614 | return -1; | ||
615 | free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie); | ||
616 | 552 | ||
617 | /* | 553 | /* |
618 | * Get rid of bytes in the queue. | 554 | * Get rid of bytes in the queue. |
@@ -637,9 +573,9 @@ static int __devinit i8042_check_aux(void) | |||
637 | * AUX ports, we test for this only when the LOOP command failed. | 573 | * AUX ports, we test for this only when the LOOP command failed. |
638 | */ | 574 | */ |
639 | 575 | ||
640 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) | 576 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) || |
641 | || (param && param != 0xfa && param != 0xff)) | 577 | (param && param != 0xfa && param != 0xff)) |
642 | return -1; | 578 | return -1; |
643 | } | 579 | } |
644 | 580 | ||
645 | /* | 581 | /* |
@@ -659,54 +595,80 @@ static int __devinit i8042_check_aux(void) | |||
659 | return -1; | 595 | return -1; |
660 | 596 | ||
661 | /* | 597 | /* |
662 | * Disable the interface. | 598 | * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and |
599 | * used it for a PCI card or somethig else. | ||
663 | */ | 600 | */ |
664 | 601 | ||
665 | i8042_ctr |= I8042_CTR_AUXDIS; | 602 | if (i8042_noloop) { |
666 | i8042_ctr &= ~I8042_CTR_AUXINT; | 603 | /* |
604 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | ||
605 | * is working and hope we are right. | ||
606 | */ | ||
607 | retval = 0; | ||
608 | goto out; | ||
609 | } | ||
667 | 610 | ||
668 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 611 | if (request_irq(I8042_AUX_IRQ, i8042_aux_test_irq, IRQF_SHARED, |
669 | return -1; | 612 | "i8042", i8042_platform_device)) |
613 | goto out; | ||
670 | 614 | ||
671 | return 0; | 615 | irq_registered = 1; |
672 | } | 616 | |
617 | if (i8042_enable_aux_port()) | ||
618 | goto out; | ||
619 | |||
620 | spin_lock_irqsave(&i8042_lock, flags); | ||
673 | 621 | ||
622 | init_completion(&i8042_aux_irq_delivered); | ||
623 | i8042_irq_being_tested = 1; | ||
624 | |||
625 | param = 0xa5; | ||
626 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); | ||
627 | |||
628 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
629 | |||
630 | if (retval) | ||
631 | goto out; | ||
674 | 632 | ||
633 | if (wait_for_completion_timeout(&i8042_aux_irq_delivered, | ||
634 | msecs_to_jiffies(250)) == 0) { | ||
675 | /* | 635 | /* |
676 | * i8042_port_register() marks the device as existing, | 636 | * AUX IRQ was never delivered so we need to flush the controller to |
677 | * registers it, and reports to the user. | 637 | * get rid of the byte we put there; otherwise keyboard may not work. |
678 | */ | 638 | */ |
639 | i8042_flush(); | ||
640 | retval = -1; | ||
641 | } | ||
679 | 642 | ||
680 | static int __devinit i8042_port_register(struct i8042_port *port) | 643 | out: |
681 | { | ||
682 | i8042_ctr &= ~port->disable; | ||
683 | 644 | ||
684 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 645 | /* |
685 | printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n"); | 646 | * Disable the interface. |
686 | kfree(port->serio); | 647 | */ |
687 | port->serio = NULL; | ||
688 | i8042_ctr |= port->disable; | ||
689 | return -EIO; | ||
690 | } | ||
691 | 648 | ||
692 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", | 649 | i8042_ctr |= I8042_CTR_AUXDIS; |
693 | port->name, | 650 | i8042_ctr &= ~I8042_CTR_AUXINT; |
694 | (unsigned long) I8042_DATA_REG, | ||
695 | (unsigned long) I8042_COMMAND_REG, | ||
696 | port->irq); | ||
697 | 651 | ||
698 | serio_register_port(port->serio); | 652 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
653 | retval = -1; | ||
699 | 654 | ||
700 | return 0; | 655 | if (irq_registered) |
701 | } | 656 | free_irq(I8042_AUX_IRQ, i8042_platform_device); |
702 | 657 | ||
658 | return retval; | ||
659 | } | ||
703 | 660 | ||
704 | static void i8042_timer_func(unsigned long data) | 661 | static int i8042_controller_check(void) |
705 | { | 662 | { |
706 | i8042_interrupt(0, NULL, NULL); | 663 | if (i8042_flush() == I8042_BUFFER_SIZE) { |
664 | printk(KERN_ERR "i8042.c: No controller found.\n"); | ||
665 | return -ENODEV; | ||
666 | } | ||
667 | |||
668 | return 0; | ||
707 | } | 669 | } |
708 | 670 | ||
709 | static int i8042_ctl_test(void) | 671 | static int i8042_controller_selftest(void) |
710 | { | 672 | { |
711 | unsigned char param; | 673 | unsigned char param; |
712 | 674 | ||
@@ -715,13 +677,13 @@ static int i8042_ctl_test(void) | |||
715 | 677 | ||
716 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 678 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { |
717 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 679 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); |
718 | return -1; | 680 | return -ENODEV; |
719 | } | 681 | } |
720 | 682 | ||
721 | if (param != I8042_RET_CTL_TEST) { | 683 | if (param != I8042_RET_CTL_TEST) { |
722 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 684 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", |
723 | param, I8042_RET_CTL_TEST); | 685 | param, I8042_RET_CTL_TEST); |
724 | return -1; | 686 | return -EIO; |
725 | } | 687 | } |
726 | 688 | ||
727 | return 0; | 689 | return 0; |
@@ -738,25 +700,12 @@ static int i8042_controller_init(void) | |||
738 | unsigned long flags; | 700 | unsigned long flags; |
739 | 701 | ||
740 | /* | 702 | /* |
741 | * Test the i8042. We need to know if it thinks it's working correctly | ||
742 | * before doing anything else. | ||
743 | */ | ||
744 | |||
745 | if (i8042_flush() == I8042_BUFFER_SIZE) { | ||
746 | printk(KERN_ERR "i8042.c: No controller found.\n"); | ||
747 | return -1; | ||
748 | } | ||
749 | |||
750 | if (i8042_ctl_test()) | ||
751 | return -1; | ||
752 | |||
753 | /* | ||
754 | * Save the CTR for restoral on unload / reboot. | 703 | * Save the CTR for restoral on unload / reboot. |
755 | */ | 704 | */ |
756 | 705 | ||
757 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { | 706 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { |
758 | printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); | 707 | printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); |
759 | return -1; | 708 | return -EIO; |
760 | } | 709 | } |
761 | 710 | ||
762 | i8042_initial_ctr = i8042_ctr; | 711 | i8042_initial_ctr = i8042_ctr; |
@@ -805,7 +754,7 @@ static int i8042_controller_init(void) | |||
805 | 754 | ||
806 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 755 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
807 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); | 756 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); |
808 | return -1; | 757 | return -EIO; |
809 | } | 758 | } |
810 | 759 | ||
811 | return 0; | 760 | return 0; |
@@ -813,15 +762,12 @@ static int i8042_controller_init(void) | |||
813 | 762 | ||
814 | 763 | ||
815 | /* | 764 | /* |
816 | * Reset the controller. | 765 | * Reset the controller and reset CRT to the original value set by BIOS. |
817 | */ | 766 | */ |
767 | |||
818 | static void i8042_controller_reset(void) | 768 | static void i8042_controller_reset(void) |
819 | { | 769 | { |
820 | /* | 770 | i8042_flush(); |
821 | * Reset the controller if requested. | ||
822 | */ | ||
823 | |||
824 | i8042_ctl_test(); | ||
825 | 771 | ||
826 | /* | 772 | /* |
827 | * Disable MUX mode if present. | 773 | * Disable MUX mode if present. |
@@ -831,12 +777,16 @@ static void i8042_controller_reset(void) | |||
831 | i8042_set_mux_mode(0, NULL); | 777 | i8042_set_mux_mode(0, NULL); |
832 | 778 | ||
833 | /* | 779 | /* |
834 | * Restore the original control register setting. | 780 | * Reset the controller if requested. |
835 | */ | 781 | */ |
836 | 782 | ||
837 | i8042_ctr = i8042_initial_ctr; | 783 | i8042_controller_selftest(); |
838 | 784 | ||
839 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 785 | /* |
786 | * Restore the original control register setting. | ||
787 | */ | ||
788 | |||
789 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
840 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); | 790 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); |
841 | } | 791 | } |
842 | 792 | ||
@@ -850,14 +800,12 @@ static void i8042_controller_cleanup(void) | |||
850 | { | 800 | { |
851 | int i; | 801 | int i; |
852 | 802 | ||
853 | i8042_flush(); | ||
854 | |||
855 | /* | 803 | /* |
856 | * Reset anything that is connected to the ports. | 804 | * Reset anything that is connected to the ports. |
857 | */ | 805 | */ |
858 | 806 | ||
859 | for (i = 0; i < I8042_NUM_PORTS; i++) | 807 | for (i = 0; i < I8042_NUM_PORTS; i++) |
860 | if (i8042_ports[i].exists) | 808 | if (i8042_ports[i].serio) |
861 | serio_cleanup(i8042_ports[i].serio); | 809 | serio_cleanup(i8042_ports[i].serio); |
862 | 810 | ||
863 | i8042_controller_reset(); | 811 | i8042_controller_reset(); |
@@ -913,8 +861,7 @@ static long i8042_panic_blink(long count) | |||
913 | 861 | ||
914 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 862 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) |
915 | { | 863 | { |
916 | del_timer_sync(&i8042_timer); | 864 | i8042_controller_cleanup(); |
917 | i8042_controller_reset(); | ||
918 | 865 | ||
919 | return 0; | 866 | return 0; |
920 | } | 867 | } |
@@ -926,33 +873,39 @@ static int i8042_suspend(struct platform_device *dev, pm_message_t state) | |||
926 | 873 | ||
927 | static int i8042_resume(struct platform_device *dev) | 874 | static int i8042_resume(struct platform_device *dev) |
928 | { | 875 | { |
929 | int i; | 876 | int error; |
930 | 877 | ||
931 | if (i8042_ctl_test()) | 878 | error = i8042_controller_check(); |
932 | return -1; | 879 | if (error) |
880 | return error; | ||
933 | 881 | ||
934 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 882 | error = i8042_controller_selftest(); |
935 | printk(KERN_ERR "i8042: Can't write CTR\n"); | 883 | if (error) |
936 | return -1; | 884 | return error; |
937 | } | ||
938 | |||
939 | if (i8042_mux_present) | ||
940 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) | ||
941 | printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n"); | ||
942 | 885 | ||
943 | /* | 886 | /* |
944 | * Activate all ports. | 887 | * Restore pre-resume CTR value and disable all ports |
945 | */ | 888 | */ |
946 | 889 | ||
947 | for (i = 0; i < I8042_NUM_PORTS; i++) | 890 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; |
948 | i8042_activate_port(&i8042_ports[i]); | 891 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); |
892 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
893 | printk(KERN_ERR "i8042: Can't write CTR to resume\n"); | ||
894 | return -EIO; | ||
895 | } | ||
949 | 896 | ||
950 | /* | 897 | if (i8042_mux_present) { |
951 | * Restart timer (for polling "stuck" data) | 898 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) |
952 | */ | 899 | printk(KERN_WARNING |
953 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 900 | "i8042: failed to resume active multiplexor, " |
901 | "mouse won't work.\n"); | ||
902 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) | ||
903 | i8042_enable_aux_port(); | ||
954 | 904 | ||
955 | panic_blink = i8042_panic_blink; | 905 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
906 | i8042_enable_kbd_port(); | ||
907 | |||
908 | i8042_interrupt(0, NULL, NULL); | ||
956 | 909 | ||
957 | return 0; | 910 | return 0; |
958 | } | 911 | } |
@@ -978,24 +931,24 @@ static int __devinit i8042_create_kbd_port(void) | |||
978 | 931 | ||
979 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; | 932 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; |
980 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 933 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
981 | serio->open = i8042_open; | ||
982 | serio->close = i8042_close; | ||
983 | serio->start = i8042_start; | 934 | serio->start = i8042_start; |
984 | serio->stop = i8042_stop; | 935 | serio->stop = i8042_stop; |
985 | serio->port_data = port; | 936 | serio->port_data = port; |
986 | serio->dev.parent = &i8042_platform_device->dev; | 937 | serio->dev.parent = &i8042_platform_device->dev; |
987 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); | 938 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
988 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | 939 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); |
989 | 940 | ||
990 | port->serio = serio; | 941 | port->serio = serio; |
942 | port->irq = I8042_KBD_IRQ; | ||
991 | 943 | ||
992 | return i8042_port_register(port); | 944 | return 0; |
993 | } | 945 | } |
994 | 946 | ||
995 | static int __devinit i8042_create_aux_port(void) | 947 | static int __devinit i8042_create_aux_port(int idx) |
996 | { | 948 | { |
997 | struct serio *serio; | 949 | struct serio *serio; |
998 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; | 950 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
951 | struct i8042_port *port = &i8042_ports[port_no]; | ||
999 | 952 | ||
1000 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 953 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
1001 | if (!serio) | 954 | if (!serio) |
@@ -1003,111 +956,191 @@ static int __devinit i8042_create_aux_port(void) | |||
1003 | 956 | ||
1004 | serio->id.type = SERIO_8042; | 957 | serio->id.type = SERIO_8042; |
1005 | serio->write = i8042_aux_write; | 958 | serio->write = i8042_aux_write; |
1006 | serio->open = i8042_open; | ||
1007 | serio->close = i8042_close; | ||
1008 | serio->start = i8042_start; | 959 | serio->start = i8042_start; |
1009 | serio->stop = i8042_stop; | 960 | serio->stop = i8042_stop; |
1010 | serio->port_data = port; | 961 | serio->port_data = port; |
1011 | serio->dev.parent = &i8042_platform_device->dev; | 962 | serio->dev.parent = &i8042_platform_device->dev; |
1012 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); | 963 | if (idx < 0) { |
1013 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 964 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
965 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | ||
966 | } else { | ||
967 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | ||
968 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | ||
969 | } | ||
1014 | 970 | ||
1015 | port->serio = serio; | 971 | port->serio = serio; |
972 | port->mux = idx; | ||
973 | port->irq = I8042_AUX_IRQ; | ||
1016 | 974 | ||
1017 | return i8042_port_register(port); | 975 | return 0; |
1018 | } | 976 | } |
1019 | 977 | ||
1020 | static int __devinit i8042_create_mux_port(int index) | 978 | static void __devinit i8042_free_kbd_port(void) |
1021 | { | 979 | { |
1022 | struct serio *serio; | 980 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
1023 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; | 981 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
982 | } | ||
1024 | 983 | ||
1025 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 984 | static void __devinit i8042_free_aux_ports(void) |
1026 | if (!serio) | 985 | { |
1027 | return -ENOMEM; | 986 | int i; |
1028 | 987 | ||
1029 | serio->id.type = SERIO_8042; | 988 | for (i = I8042_AUX_PORT_NO; i < I8042_NUM_PORTS; i++) { |
1030 | serio->write = i8042_aux_write; | 989 | kfree(i8042_ports[i].serio); |
1031 | serio->open = i8042_open; | 990 | i8042_ports[i].serio = NULL; |
1032 | serio->close = i8042_close; | 991 | } |
1033 | serio->start = i8042_start; | 992 | } |
1034 | serio->stop = i8042_stop; | ||
1035 | serio->port_data = port; | ||
1036 | serio->dev.parent = &i8042_platform_device->dev; | ||
1037 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); | ||
1038 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | ||
1039 | 993 | ||
1040 | *port = i8042_ports[I8042_AUX_PORT_NO]; | 994 | static void __devinit i8042_register_ports(void) |
1041 | port->exists = 0; | 995 | { |
1042 | snprintf(port->name, sizeof(port->name), "AUX%d", index); | 996 | int i; |
1043 | port->mux = index; | ||
1044 | port->serio = serio; | ||
1045 | 997 | ||
1046 | return i8042_port_register(port); | 998 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
999 | if (i8042_ports[i].serio) { | ||
1000 | printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", | ||
1001 | i8042_ports[i].serio->name, | ||
1002 | (unsigned long) I8042_DATA_REG, | ||
1003 | (unsigned long) I8042_COMMAND_REG, | ||
1004 | i8042_ports[i].irq); | ||
1005 | serio_register_port(i8042_ports[i].serio); | ||
1006 | } | ||
1007 | } | ||
1047 | } | 1008 | } |
1048 | 1009 | ||
1049 | static int __devinit i8042_probe(struct platform_device *dev) | 1010 | static void __devinit i8042_unregister_ports(void) |
1050 | { | 1011 | { |
1051 | int i, have_ports = 0; | 1012 | int i; |
1052 | int err; | ||
1053 | 1013 | ||
1054 | init_timer(&i8042_timer); | 1014 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
1055 | i8042_timer.function = i8042_timer_func; | 1015 | if (i8042_ports[i].serio) { |
1016 | serio_unregister_port(i8042_ports[i].serio); | ||
1017 | i8042_ports[i].serio = NULL; | ||
1018 | } | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | static void i8042_free_irqs(void) | ||
1023 | { | ||
1024 | if (i8042_aux_irq_registered) | ||
1025 | free_irq(I8042_AUX_IRQ, i8042_platform_device); | ||
1026 | if (i8042_kbd_irq_registered) | ||
1027 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | ||
1028 | |||
1029 | i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; | ||
1030 | } | ||
1031 | |||
1032 | static int __devinit i8042_setup_aux(void) | ||
1033 | { | ||
1034 | int (*aux_enable)(void); | ||
1035 | int error; | ||
1036 | int i; | ||
1056 | 1037 | ||
1057 | if (i8042_controller_init()) | 1038 | if (i8042_check_aux()) |
1058 | return -ENODEV; | 1039 | return -ENODEV; |
1059 | 1040 | ||
1060 | if (!i8042_noaux && !i8042_check_aux()) { | 1041 | if (i8042_nomux || i8042_check_mux()) { |
1061 | if (!i8042_nomux && !i8042_check_mux()) { | 1042 | error = i8042_create_aux_port(-1); |
1062 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | 1043 | if (error) |
1063 | err = i8042_create_mux_port(i); | 1044 | goto err_free_ports; |
1064 | if (err) | 1045 | aux_enable = i8042_enable_aux_port; |
1065 | goto err_unregister_ports; | 1046 | } else { |
1066 | } | 1047 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
1067 | } else { | 1048 | error = i8042_create_aux_port(i); |
1068 | err = i8042_create_aux_port(); | 1049 | if (error) |
1069 | if (err) | 1050 | goto err_free_ports; |
1070 | goto err_unregister_ports; | ||
1071 | } | 1051 | } |
1072 | have_ports = 1; | 1052 | aux_enable = i8042_enable_mux_ports; |
1073 | } | 1053 | } |
1074 | 1054 | ||
1075 | if (!i8042_nokbd) { | 1055 | error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, |
1076 | err = i8042_create_kbd_port(); | 1056 | "i8042", i8042_platform_device); |
1077 | if (err) | 1057 | if (error) |
1078 | goto err_unregister_ports; | 1058 | goto err_free_ports; |
1079 | have_ports = 1; | ||
1080 | } | ||
1081 | 1059 | ||
1082 | if (!have_ports) { | 1060 | if (aux_enable()) |
1083 | err = -ENODEV; | 1061 | goto err_free_irq; |
1084 | goto err_controller_cleanup; | ||
1085 | } | ||
1086 | 1062 | ||
1087 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 1063 | i8042_aux_irq_registered = 1; |
1088 | return 0; | 1064 | return 0; |
1089 | 1065 | ||
1090 | err_unregister_ports: | 1066 | err_free_irq: |
1091 | for (i = 0; i < I8042_NUM_PORTS; i++) | 1067 | free_irq(I8042_AUX_IRQ, i8042_platform_device); |
1092 | if (i8042_ports[i].serio) | 1068 | err_free_ports: |
1093 | serio_unregister_port(i8042_ports[i].serio); | 1069 | i8042_free_aux_ports(); |
1094 | err_controller_cleanup: | 1070 | return error; |
1095 | i8042_controller_cleanup(); | 1071 | } |
1096 | 1072 | ||
1097 | return err; | 1073 | static int __devinit i8042_setup_kbd(void) |
1074 | { | ||
1075 | int error; | ||
1076 | |||
1077 | error = i8042_create_kbd_port(); | ||
1078 | if (error) | ||
1079 | return error; | ||
1080 | |||
1081 | error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, | ||
1082 | "i8042", i8042_platform_device); | ||
1083 | if (error) | ||
1084 | goto err_free_port; | ||
1085 | |||
1086 | error = i8042_enable_kbd_port(); | ||
1087 | if (error) | ||
1088 | goto err_free_irq; | ||
1089 | |||
1090 | i8042_kbd_irq_registered = 1; | ||
1091 | return 0; | ||
1092 | |||
1093 | err_free_irq: | ||
1094 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | ||
1095 | err_free_port: | ||
1096 | i8042_free_kbd_port(); | ||
1097 | return error; | ||
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | static int __devexit i8042_remove(struct platform_device *dev) | 1100 | static int __devinit i8042_probe(struct platform_device *dev) |
1101 | { | 1101 | { |
1102 | int i; | 1102 | int error; |
1103 | 1103 | ||
1104 | i8042_controller_cleanup(); | 1104 | error = i8042_controller_selftest(); |
1105 | if (error) | ||
1106 | return error; | ||
1105 | 1107 | ||
1106 | for (i = 0; i < I8042_NUM_PORTS; i++) | 1108 | error = i8042_controller_init(); |
1107 | if (i8042_ports[i].exists) | 1109 | if (error) |
1108 | serio_unregister_port(i8042_ports[i].serio); | 1110 | return error; |
1111 | |||
1112 | if (!i8042_noaux) { | ||
1113 | error = i8042_setup_aux(); | ||
1114 | if (error && error != -ENODEV && error != -EBUSY) | ||
1115 | goto out_fail; | ||
1116 | } | ||
1117 | |||
1118 | if (!i8042_nokbd) { | ||
1119 | error = i8042_setup_kbd(); | ||
1120 | if (error) | ||
1121 | goto out_fail; | ||
1122 | } | ||
1109 | 1123 | ||
1110 | del_timer_sync(&i8042_timer); | 1124 | /* |
1125 | * Ok, everything is ready, let's register all serio ports | ||
1126 | */ | ||
1127 | i8042_register_ports(); | ||
1128 | |||
1129 | return 0; | ||
1130 | |||
1131 | out_fail: | ||
1132 | i8042_free_aux_ports(); /* in case KBD failed but AUX not */ | ||
1133 | i8042_free_irqs(); | ||
1134 | i8042_controller_reset(); | ||
1135 | |||
1136 | return error; | ||
1137 | } | ||
1138 | |||
1139 | static int __devexit i8042_remove(struct platform_device *dev) | ||
1140 | { | ||
1141 | i8042_unregister_ports(); | ||
1142 | i8042_free_irqs(); | ||
1143 | i8042_controller_reset(); | ||
1111 | 1144 | ||
1112 | return 0; | 1145 | return 0; |
1113 | } | 1146 | } |
@@ -1134,8 +1167,9 @@ static int __init i8042_init(void) | |||
1134 | if (err) | 1167 | if (err) |
1135 | return err; | 1168 | return err; |
1136 | 1169 | ||
1137 | i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; | 1170 | err = i8042_controller_check(); |
1138 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; | 1171 | if (err) |
1172 | goto err_platform_exit; | ||
1139 | 1173 | ||
1140 | err = platform_driver_register(&i8042_driver); | 1174 | err = platform_driver_register(&i8042_driver); |
1141 | if (err) | 1175 | if (err) |
@@ -1151,6 +1185,8 @@ static int __init i8042_init(void) | |||
1151 | if (err) | 1185 | if (err) |
1152 | goto err_free_device; | 1186 | goto err_free_device; |
1153 | 1187 | ||
1188 | panic_blink = i8042_panic_blink; | ||
1189 | |||
1154 | return 0; | 1190 | return 0; |
1155 | 1191 | ||
1156 | err_free_device: | 1192 | err_free_device: |
@@ -1167,7 +1203,6 @@ static void __exit i8042_exit(void) | |||
1167 | { | 1203 | { |
1168 | platform_device_unregister(i8042_platform_device); | 1204 | platform_device_unregister(i8042_platform_device); |
1169 | platform_driver_unregister(&i8042_driver); | 1205 | platform_driver_unregister(&i8042_driver); |
1170 | |||
1171 | i8042_platform_exit(); | 1206 | i8042_platform_exit(); |
1172 | 1207 | ||
1173 | panic_blink = NULL; | 1208 | panic_blink = NULL; |