diff options
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r-- | drivers/input/serio/i8042.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index c60593c8d2be..082afbf088d6 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -48,6 +48,10 @@ static bool i8042_unlock; | |||
48 | module_param_named(unlock, i8042_unlock, bool, 0); | 48 | module_param_named(unlock, i8042_unlock, bool, 0); |
49 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); | 49 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); |
50 | 50 | ||
51 | static bool i8042_probe_defer; | ||
52 | module_param_named(probe_defer, i8042_probe_defer, bool, 0); | ||
53 | MODULE_PARM_DESC(probe_defer, "Allow deferred probing."); | ||
54 | |||
51 | enum i8042_controller_reset_mode { | 55 | enum i8042_controller_reset_mode { |
52 | I8042_RESET_NEVER, | 56 | I8042_RESET_NEVER, |
53 | I8042_RESET_ALWAYS, | 57 | I8042_RESET_ALWAYS, |
@@ -702,7 +706,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) | |||
702 | * LCS/Telegraphics. | 706 | * LCS/Telegraphics. |
703 | */ | 707 | */ |
704 | 708 | ||
705 | static int __init i8042_check_mux(void) | 709 | static int i8042_check_mux(void) |
706 | { | 710 | { |
707 | unsigned char mux_version; | 711 | unsigned char mux_version; |
708 | 712 | ||
@@ -731,10 +735,10 @@ static int __init i8042_check_mux(void) | |||
731 | /* | 735 | /* |
732 | * The following is used to test AUX IRQ delivery. | 736 | * The following is used to test AUX IRQ delivery. |
733 | */ | 737 | */ |
734 | static struct completion i8042_aux_irq_delivered __initdata; | 738 | static struct completion i8042_aux_irq_delivered; |
735 | static bool i8042_irq_being_tested __initdata; | 739 | static bool i8042_irq_being_tested; |
736 | 740 | ||
737 | static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) | 741 | static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id) |
738 | { | 742 | { |
739 | unsigned long flags; | 743 | unsigned long flags; |
740 | unsigned char str, data; | 744 | unsigned char str, data; |
@@ -761,7 +765,7 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) | |||
761 | * verifies success by readinng CTR. Used when testing for presence of AUX | 765 | * verifies success by readinng CTR. Used when testing for presence of AUX |
762 | * port. | 766 | * port. |
763 | */ | 767 | */ |
764 | static int __init i8042_toggle_aux(bool on) | 768 | static int i8042_toggle_aux(bool on) |
765 | { | 769 | { |
766 | unsigned char param; | 770 | unsigned char param; |
767 | int i; | 771 | int i; |
@@ -789,7 +793,7 @@ static int __init i8042_toggle_aux(bool on) | |||
789 | * the presence of an AUX interface. | 793 | * the presence of an AUX interface. |
790 | */ | 794 | */ |
791 | 795 | ||
792 | static int __init i8042_check_aux(void) | 796 | static int i8042_check_aux(void) |
793 | { | 797 | { |
794 | int retval = -1; | 798 | int retval = -1; |
795 | bool irq_registered = false; | 799 | bool irq_registered = false; |
@@ -996,7 +1000,7 @@ static int i8042_controller_init(void) | |||
996 | 1000 | ||
997 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { | 1001 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { |
998 | pr_err("Can't read CTR while initializing i8042\n"); | 1002 | pr_err("Can't read CTR while initializing i8042\n"); |
999 | return -EIO; | 1003 | return i8042_probe_defer ? -EPROBE_DEFER : -EIO; |
1000 | } | 1004 | } |
1001 | 1005 | ||
1002 | } while (n < 2 || ctr[0] != ctr[1]); | 1006 | } while (n < 2 || ctr[0] != ctr[1]); |
@@ -1311,7 +1315,7 @@ static void i8042_shutdown(struct platform_device *dev) | |||
1311 | i8042_controller_reset(false); | 1315 | i8042_controller_reset(false); |
1312 | } | 1316 | } |
1313 | 1317 | ||
1314 | static int __init i8042_create_kbd_port(void) | 1318 | static int i8042_create_kbd_port(void) |
1315 | { | 1319 | { |
1316 | struct serio *serio; | 1320 | struct serio *serio; |
1317 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 1321 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
@@ -1339,7 +1343,7 @@ static int __init i8042_create_kbd_port(void) | |||
1339 | return 0; | 1343 | return 0; |
1340 | } | 1344 | } |
1341 | 1345 | ||
1342 | static int __init i8042_create_aux_port(int idx) | 1346 | static int i8042_create_aux_port(int idx) |
1343 | { | 1347 | { |
1344 | struct serio *serio; | 1348 | struct serio *serio; |
1345 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; | 1349 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
@@ -1376,13 +1380,13 @@ static int __init i8042_create_aux_port(int idx) | |||
1376 | return 0; | 1380 | return 0; |
1377 | } | 1381 | } |
1378 | 1382 | ||
1379 | static void __init i8042_free_kbd_port(void) | 1383 | static void i8042_free_kbd_port(void) |
1380 | { | 1384 | { |
1381 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); | 1385 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
1382 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; | 1386 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
1383 | } | 1387 | } |
1384 | 1388 | ||
1385 | static void __init i8042_free_aux_ports(void) | 1389 | static void i8042_free_aux_ports(void) |
1386 | { | 1390 | { |
1387 | int i; | 1391 | int i; |
1388 | 1392 | ||
@@ -1392,7 +1396,7 @@ static void __init i8042_free_aux_ports(void) | |||
1392 | } | 1396 | } |
1393 | } | 1397 | } |
1394 | 1398 | ||
1395 | static void __init i8042_register_ports(void) | 1399 | static void i8042_register_ports(void) |
1396 | { | 1400 | { |
1397 | int i; | 1401 | int i; |
1398 | 1402 | ||
@@ -1444,7 +1448,7 @@ static void i8042_free_irqs(void) | |||
1444 | i8042_aux_irq_registered = i8042_kbd_irq_registered = false; | 1448 | i8042_aux_irq_registered = i8042_kbd_irq_registered = false; |
1445 | } | 1449 | } |
1446 | 1450 | ||
1447 | static int __init i8042_setup_aux(void) | 1451 | static int i8042_setup_aux(void) |
1448 | { | 1452 | { |
1449 | int (*aux_enable)(void); | 1453 | int (*aux_enable)(void); |
1450 | int error; | 1454 | int error; |
@@ -1486,7 +1490,7 @@ static int __init i8042_setup_aux(void) | |||
1486 | return error; | 1490 | return error; |
1487 | } | 1491 | } |
1488 | 1492 | ||
1489 | static int __init i8042_setup_kbd(void) | 1493 | static int i8042_setup_kbd(void) |
1490 | { | 1494 | { |
1491 | int error; | 1495 | int error; |
1492 | 1496 | ||
@@ -1536,7 +1540,7 @@ static int i8042_kbd_bind_notifier(struct notifier_block *nb, | |||
1536 | return 0; | 1540 | return 0; |
1537 | } | 1541 | } |
1538 | 1542 | ||
1539 | static int __init i8042_probe(struct platform_device *dev) | 1543 | static int i8042_probe(struct platform_device *dev) |
1540 | { | 1544 | { |
1541 | int error; | 1545 | int error; |
1542 | 1546 | ||
@@ -1601,6 +1605,7 @@ static struct platform_driver i8042_driver = { | |||
1601 | .pm = &i8042_pm_ops, | 1605 | .pm = &i8042_pm_ops, |
1602 | #endif | 1606 | #endif |
1603 | }, | 1607 | }, |
1608 | .probe = i8042_probe, | ||
1604 | .remove = i8042_remove, | 1609 | .remove = i8042_remove, |
1605 | .shutdown = i8042_shutdown, | 1610 | .shutdown = i8042_shutdown, |
1606 | }; | 1611 | }; |
@@ -1611,7 +1616,6 @@ static struct notifier_block i8042_kbd_bind_notifier_block = { | |||
1611 | 1616 | ||
1612 | static int __init i8042_init(void) | 1617 | static int __init i8042_init(void) |
1613 | { | 1618 | { |
1614 | struct platform_device *pdev; | ||
1615 | int err; | 1619 | int err; |
1616 | 1620 | ||
1617 | dbg_init(); | 1621 | dbg_init(); |
@@ -1627,17 +1631,29 @@ static int __init i8042_init(void) | |||
1627 | /* Set this before creating the dev to allow i8042_command to work right away */ | 1631 | /* Set this before creating the dev to allow i8042_command to work right away */ |
1628 | i8042_present = true; | 1632 | i8042_present = true; |
1629 | 1633 | ||
1630 | pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); | 1634 | err = platform_driver_register(&i8042_driver); |
1631 | if (IS_ERR(pdev)) { | 1635 | if (err) |
1632 | err = PTR_ERR(pdev); | ||
1633 | goto err_platform_exit; | 1636 | goto err_platform_exit; |
1637 | |||
1638 | i8042_platform_device = platform_device_alloc("i8042", -1); | ||
1639 | if (!i8042_platform_device) { | ||
1640 | err = -ENOMEM; | ||
1641 | goto err_unregister_driver; | ||
1634 | } | 1642 | } |
1635 | 1643 | ||
1644 | err = platform_device_add(i8042_platform_device); | ||
1645 | if (err) | ||
1646 | goto err_free_device; | ||
1647 | |||
1636 | bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block); | 1648 | bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block); |
1637 | panic_blink = i8042_panic_blink; | 1649 | panic_blink = i8042_panic_blink; |
1638 | 1650 | ||
1639 | return 0; | 1651 | return 0; |
1640 | 1652 | ||
1653 | err_free_device: | ||
1654 | platform_device_put(i8042_platform_device); | ||
1655 | err_unregister_driver: | ||
1656 | platform_driver_unregister(&i8042_driver); | ||
1641 | err_platform_exit: | 1657 | err_platform_exit: |
1642 | i8042_platform_exit(); | 1658 | i8042_platform_exit(); |
1643 | return err; | 1659 | return err; |