diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 185721dba42b..a74056488234 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -42,6 +42,9 @@ | |||
42 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | #include <asm/unaligned.h> | 44 | #include <asm/unaligned.h> |
45 | #ifdef CONFIG_PPC_PS3 | ||
46 | #include <asm/firmware.h> | ||
47 | #endif | ||
45 | 48 | ||
46 | 49 | ||
47 | /*-------------------------------------------------------------------------*/ | 50 | /*-------------------------------------------------------------------------*/ |
@@ -299,6 +302,19 @@ static void ehci_watchdog (unsigned long param) | |||
299 | spin_unlock_irqrestore (&ehci->lock, flags); | 302 | spin_unlock_irqrestore (&ehci->lock, flags); |
300 | } | 303 | } |
301 | 304 | ||
305 | /* On some systems, leaving remote wakeup enabled prevents system shutdown. | ||
306 | * The firmware seems to think that powering off is a wakeup event! | ||
307 | * This routine turns off remote wakeup and everything else, on all ports. | ||
308 | */ | ||
309 | static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) | ||
310 | { | ||
311 | int port = HCS_N_PORTS(ehci->hcs_params); | ||
312 | |||
313 | while (port--) | ||
314 | ehci_writel(ehci, PORT_RWC_BITS, | ||
315 | &ehci->regs->port_status[port]); | ||
316 | } | ||
317 | |||
302 | /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). | 318 | /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). |
303 | * This forcibly disables dma and IRQs, helping kexec and other cases | 319 | * This forcibly disables dma and IRQs, helping kexec and other cases |
304 | * where the next system software may expect clean state. | 320 | * where the next system software may expect clean state. |
@@ -310,9 +326,13 @@ ehci_shutdown (struct usb_hcd *hcd) | |||
310 | 326 | ||
311 | ehci = hcd_to_ehci (hcd); | 327 | ehci = hcd_to_ehci (hcd); |
312 | (void) ehci_halt (ehci); | 328 | (void) ehci_halt (ehci); |
329 | ehci_turn_off_all_ports(ehci); | ||
313 | 330 | ||
314 | /* make BIOS/etc use companion controller during reboot */ | 331 | /* make BIOS/etc use companion controller during reboot */ |
315 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); | 332 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
333 | |||
334 | /* unblock posted writes */ | ||
335 | ehci_readl(ehci, &ehci->regs->configured_flag); | ||
316 | } | 336 | } |
317 | 337 | ||
318 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | 338 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) |
@@ -951,15 +971,18 @@ static int __init ehci_hcd_init(void) | |||
951 | #endif | 971 | #endif |
952 | 972 | ||
953 | #ifdef PS3_SYSTEM_BUS_DRIVER | 973 | #ifdef PS3_SYSTEM_BUS_DRIVER |
954 | retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 974 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { |
955 | if (retval < 0) { | 975 | retval = ps3_system_bus_driver_register( |
976 | &PS3_SYSTEM_BUS_DRIVER); | ||
977 | if (retval < 0) { | ||
956 | #ifdef PLATFORM_DRIVER | 978 | #ifdef PLATFORM_DRIVER |
957 | platform_driver_unregister(&PLATFORM_DRIVER); | 979 | platform_driver_unregister(&PLATFORM_DRIVER); |
958 | #endif | 980 | #endif |
959 | #ifdef PCI_DRIVER | 981 | #ifdef PCI_DRIVER |
960 | pci_unregister_driver(&PCI_DRIVER); | 982 | pci_unregister_driver(&PCI_DRIVER); |
961 | #endif | 983 | #endif |
962 | return retval; | 984 | return retval; |
985 | } | ||
963 | } | 986 | } |
964 | #endif | 987 | #endif |
965 | 988 | ||
@@ -976,7 +999,8 @@ static void __exit ehci_hcd_cleanup(void) | |||
976 | pci_unregister_driver(&PCI_DRIVER); | 999 | pci_unregister_driver(&PCI_DRIVER); |
977 | #endif | 1000 | #endif |
978 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1001 | #ifdef PS3_SYSTEM_BUS_DRIVER |
979 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1002 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) |
1003 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
980 | #endif | 1004 | #endif |
981 | } | 1005 | } |
982 | module_exit(ehci_hcd_cleanup); | 1006 | module_exit(ehci_hcd_cleanup); |