aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 218f9660d7ee..97a53a48a3d8 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -194,6 +194,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
194 u32 temp; 194 u32 temp;
195 u32 power_okay; 195 u32 power_okay;
196 int i; 196 int i;
197 u8 resume_needed = 0;
197 198
198 if (time_before (jiffies, ehci->next_statechange)) 199 if (time_before (jiffies, ehci->next_statechange))
199 msleep(5); 200 msleep(5);
@@ -228,7 +229,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
228 229
229 /* Some controller/firmware combinations need a delay during which 230 /* Some controller/firmware combinations need a delay during which
230 * they set up the port statuses. See Bugzilla #8190. */ 231 * they set up the port statuses. See Bugzilla #8190. */
231 mdelay(8); 232 spin_unlock_irq(&ehci->lock);
233 msleep(8);
234 spin_lock_irq(&ehci->lock);
232 235
233 /* manually resume the ports we suspended during bus_suspend() */ 236 /* manually resume the ports we suspended during bus_suspend() */
234 i = HCS_N_PORTS (ehci->hcs_params); 237 i = HCS_N_PORTS (ehci->hcs_params);
@@ -236,12 +239,21 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
236 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 239 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
237 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 240 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
238 if (test_bit(i, &ehci->bus_suspended) && 241 if (test_bit(i, &ehci->bus_suspended) &&
239 (temp & PORT_SUSPEND)) 242 (temp & PORT_SUSPEND)) {
240 temp |= PORT_RESUME; 243 temp |= PORT_RESUME;
244 resume_needed = 1;
245 }
241 ehci_writel(ehci, temp, &ehci->regs->port_status [i]); 246 ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
242 } 247 }
248
249 /* msleep for 20ms only if code is trying to resume port */
250 if (resume_needed) {
251 spin_unlock_irq(&ehci->lock);
252 msleep(20);
253 spin_lock_irq(&ehci->lock);
254 }
255
243 i = HCS_N_PORTS (ehci->hcs_params); 256 i = HCS_N_PORTS (ehci->hcs_params);
244 mdelay (20);
245 while (i--) { 257 while (i--) {
246 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 258 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
247 if (test_bit(i, &ehci->bus_suspended) && 259 if (test_bit(i, &ehci->bus_suspended) &&
@@ -422,8 +434,15 @@ static int check_reset_complete (
422 port_status &= ~PORT_RWC_BITS; 434 port_status &= ~PORT_RWC_BITS;
423 ehci_writel(ehci, port_status, status_reg); 435 ehci_writel(ehci, port_status, status_reg);
424 436
425 } else 437 /* ensure 440EPX ohci controller state is operational */
438 if (ehci->has_amcc_usb23)
439 set_ohci_hcfs(ehci, 1);
440 } else {
426 ehci_dbg (ehci, "port %d high speed\n", index + 1); 441 ehci_dbg (ehci, "port %d high speed\n", index + 1);
442 /* ensure 440EPx ohci controller state is suspended */
443 if (ehci->has_amcc_usb23)
444 set_ohci_hcfs(ehci, 0);
445 }
427 446
428 return port_status; 447 return port_status;
429} 448}