diff options
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 914ce9370e70..4ccb97c0678f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | |||
56 | if (!ehci->owned_ports) | 56 | if (!ehci->owned_ports) |
57 | return; | 57 | return; |
58 | 58 | ||
59 | /* Make sure the ports are powered */ | ||
60 | port = HCS_N_PORTS(ehci->hcs_params); | ||
61 | while (port--) { | ||
62 | if (test_bit(port, &ehci->owned_ports)) { | ||
63 | reg = &ehci->regs->port_status[port]; | ||
64 | status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; | ||
65 | if (!(status & PORT_POWER)) { | ||
66 | status |= PORT_POWER; | ||
67 | ehci_writel(ehci, status, reg); | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
59 | /* Give the connections some time to appear */ | 72 | /* Give the connections some time to appear */ |
60 | msleep(20); | 73 | msleep(20); |
61 | 74 | ||
@@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
384 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | 397 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
385 | ehci->rh_state = EHCI_RH_RUNNING; | 398 | ehci->rh_state = EHCI_RH_RUNNING; |
386 | 399 | ||
387 | /* Some controller/firmware combinations need a delay during which | 400 | /* |
388 | * they set up the port statuses. See Bugzilla #8190. */ | 401 | * According to Bugzilla #8190, the port status for some controllers |
389 | spin_unlock_irq(&ehci->lock); | 402 | * will be wrong without a delay. At their wrong status, the port |
390 | msleep(8); | 403 | * is enabled, but not suspended neither resumed. |
391 | spin_lock_irq(&ehci->lock); | 404 | */ |
405 | i = HCS_N_PORTS(ehci->hcs_params); | ||
406 | while (i--) { | ||
407 | temp = ehci_readl(ehci, &ehci->regs->port_status[i]); | ||
408 | if ((temp & PORT_PE) && | ||
409 | !(temp & (PORT_SUSPEND | PORT_RESUME))) { | ||
410 | ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); | ||
411 | spin_unlock_irq(&ehci->lock); | ||
412 | msleep(8); | ||
413 | spin_lock_irq(&ehci->lock); | ||
414 | break; | ||
415 | } | ||
416 | } | ||
417 | |||
392 | if (ehci->shutdown) | 418 | if (ehci->shutdown) |
393 | goto shutdown; | 419 | goto shutdown; |
394 | 420 | ||
@@ -764,11 +790,6 @@ static int ehci_hub_control ( | |||
764 | status_reg); | 790 | status_reg); |
765 | break; | 791 | break; |
766 | case USB_PORT_FEAT_C_CONNECTION: | 792 | case USB_PORT_FEAT_C_CONNECTION: |
767 | if (ehci->has_lpm) { | ||
768 | /* clear PORTSC bits on disconnect */ | ||
769 | temp &= ~PORT_LPM; | ||
770 | temp &= ~PORT_DEV_ADDR; | ||
771 | } | ||
772 | ehci_writel(ehci, temp | PORT_CSC, status_reg); | 793 | ehci_writel(ehci, temp | PORT_CSC, status_reg); |
773 | break; | 794 | break; |
774 | case USB_PORT_FEAT_C_OVER_CURRENT: | 795 | case USB_PORT_FEAT_C_OVER_CURRENT: |
@@ -1088,8 +1109,7 @@ error_exit: | |||
1088 | return retval; | 1109 | return retval; |
1089 | } | 1110 | } |
1090 | 1111 | ||
1091 | static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, | 1112 | static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) |
1092 | int portnum) | ||
1093 | { | 1113 | { |
1094 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1114 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1095 | 1115 | ||
@@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, | |||
1098 | set_owner(ehci, --portnum, PORT_OWNER); | 1118 | set_owner(ehci, --portnum, PORT_OWNER); |
1099 | } | 1119 | } |
1100 | 1120 | ||
1101 | static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, | 1121 | static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) |
1102 | int portnum) | ||
1103 | { | 1122 | { |
1104 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1123 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1105 | u32 __iomem *reg; | 1124 | u32 __iomem *reg; |