aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-pci.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-06-28 11:19:02 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-09 11:54:18 -0400
commitc5cf9212a368d88fe1e25797699b167f6daa64a5 (patch)
treecaaa246923f277de3a72e4d642f9fa914ba98a31 /drivers/usb/host/ehci-pci.c
parent336c5c310e8f0d5baba7973765339eaf5d989fe1 (diff)
EHCI: centralize controller suspend/resume
This patch (as1563) removes a lot of duplicated code by moving the EHCI controller suspend/resume routines into the core driver, where the various platform drivers can invoke them as needed. Not only does this simplify these platform drivers, this also makes it easier for other platform drivers to add suspend/resume support in the future. Note: The patch does not touch the ehci-fsl.c file, because its approach to suspend and resume is so different from all the others. It will have to be handled specially by its maintainer. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-pci.c')
-rw-r--r--drivers/usb/host/ehci-pci.c74
1 files changed, 3 insertions, 71 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 123481793a47..6e767bce0605 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -331,29 +331,7 @@ done:
331 331
332static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) 332static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
333{ 333{
334 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 334 return ehci_suspend(hcd, do_wakeup);
335 unsigned long flags;
336 int rc = 0;
337
338 if (time_before(jiffies, ehci->next_statechange))
339 msleep(10);
340
341 /* Root hub was already suspended. Disable irq emission and
342 * mark HW unaccessible. The PM and USB cores make sure that
343 * the root hub is either suspended or stopped.
344 */
345 ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
346 spin_lock_irqsave (&ehci->lock, flags);
347 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
348 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
349
350 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
351 spin_unlock_irqrestore (&ehci->lock, flags);
352
353 // could save FLADJ in case of Vaux power loss
354 // ... we'd only use it to handle clock skew
355
356 return rc;
357} 335}
358 336
359static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) 337static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
@@ -402,54 +380,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
402 if (usb_is_intel_switchable_ehci(pdev)) 380 if (usb_is_intel_switchable_ehci(pdev))
403 ehci_enable_xhci_companion(); 381 ehci_enable_xhci_companion();
404 382
405 // maybe restore FLADJ 383 if (ehci_resume(hcd, hibernated) != 0)
406 384 (void) ehci_pci_reinit(ehci, pdev);
407 if (time_before(jiffies, ehci->next_statechange))
408 msleep(100);
409
410 /* Mark hardware accessible again as we are out of D3 state by now */
411 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
412
413 /* If CF is still set and we aren't resuming from hibernation
414 * then we maintained PCI Vaux power.
415 * Just undo the effect of ehci_pci_suspend().
416 */
417 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
418 !hibernated) {
419 int mask = INTR_MASK;
420
421 ehci_prepare_ports_for_controller_resume(ehci);
422 if (!hcd->self.root_hub->do_remote_wakeup)
423 mask &= ~STS_PCD;
424 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
425 ehci_readl(ehci, &ehci->regs->intr_enable);
426 return 0;
427 }
428
429 usb_root_hub_lost_power(hcd->self.root_hub);
430
431 /* Else reset, to cope with power loss or flush-to-storage
432 * style "resume" having let BIOS kick in during reboot.
433 */
434 (void) ehci_halt(ehci);
435 (void) ehci_reset(ehci);
436 (void) ehci_pci_reinit(ehci, pdev);
437
438 /* emptying the schedule aborts any urbs */
439 spin_lock_irq(&ehci->lock);
440 if (ehci->reclaim)
441 end_unlink_async(ehci);
442 ehci_work(ehci);
443 spin_unlock_irq(&ehci->lock);
444
445 ehci_writel(ehci, ehci->command, &ehci->regs->command);
446 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
447 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
448
449 /* here we "know" root ports should always stay powered */
450 ehci_port_power(ehci, 1);
451
452 ehci->rh_state = EHCI_RH_SUSPENDED;
453 return 0; 385 return 0;
454} 386}
455#endif 387#endif