diff options
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 27 |
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 | } |