diff options
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ohci-ep93xx.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 43 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 43 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sm501.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-ssb.c | 1 |
8 files changed, 54 insertions, 49 deletions
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index d72dc07dda01..e534f9de0f05 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -348,6 +348,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) if (!clocked) at91_start_clock(); + ohci_finish_controller_resume(hcd); return 0; } #else diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 40c683f8987d..5adaf36e47d0 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -192,8 +192,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) ohci->next_statechange = jiffies; ep93xx_start_hc(&pdev->dev); - usb_hcd_resume_root_hub(hcd); + ohci_finish_controller_resume(hcd); return 0; } #endif diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index c638e6b33c43..28d6d775eb5f 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -326,6 +326,49 @@ static int ohci_bus_resume (struct usb_hcd *hcd) return rc; } +/* Carry out the final steps of resuming the controller device */ +static void ohci_finish_controller_resume(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int port; + bool need_reinit = false; + + /* See if the controller is already running or has been reset */ + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { + need_reinit = true; + } else { + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + case OHCI_USB_RESET: + need_reinit = true; + } + } + + /* If needed, reinitialize and suspend the root hub */ + if (need_reinit) { + spin_lock_irq(&ohci->lock); + hcd->state = HC_STATE_RESUMING; + ohci_rh_resume(ohci); + hcd->state = HC_STATE_QUIESCING; + ohci_rh_suspend(ohci, 0); + hcd->state = HC_STATE_SUSPENDED; + spin_unlock_irq(&ohci->lock); + } + + /* Normally just turn on port power and enable interrupts */ + else { + ohci_dbg(ohci, "powerup ports\n"); + for (port = 0; port < ohci->num_ports; port++) + ohci_writel(ohci, RH_PS_PPS, + &ohci->regs->roothub.portstatus[port]); + + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); + ohci_readl(ohci, &ohci->regs->intrenable); + msleep(20); + } +} + /* Carry out polling-, autostop-, and autoresume-related state changes */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 2aafa7b6c81f..3a7c24c03671 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -510,14 +510,15 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message) static int ohci_omap_resume(struct platform_device *dev) { - struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(dev)); + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; omap_ohci_clock_power(1); - usb_hcd_resume_root_hub(platform_get_drvdata(dev)); + ohci_finish_controller_resume(hcd); return 0; } diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 40b62a35fd3c..4696cc912e16 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -238,42 +238,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) return ret; } -#if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \ - defined(CONFIG_USB_EHCI_HCD_MODULE)) - -/* Following a power loss, we must prepare to regain control of the ports - * we used to own. This means turning on the port power before ehci-hcd - * tries to switch ownership. - * - * This isn't a 100% perfect solution. On most systems the OHCI controllers - * lie at lower PCI addresses than the EHCI controller, so they will be - * discovered (and hence resumed) first. But there is no guarantee things - * will always work this way. If the EHCI controller is resumed first and - * the OHCI ports are unpowered, then the handover will fail. - */ -static void prepare_for_handover(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int port; - - /* Here we "know" root ports should always stay powered */ - ohci_dbg(ohci, "powerup ports\n"); - for (port = 0; port < ohci->num_ports; port++) - ohci_writel(ohci, RH_PS_PPS, - &ohci->regs->roothub.portstatus[port]); - - /* Flush those writes */ - ohci_readl(ohci, &ohci->regs->control); - msleep(20); -} - -#else - -static inline void prepare_for_handover(struct usb_hcd *hcd) -{ } - -#endif /* CONFIG_USB_PERSIST etc. */ - #ifdef CONFIG_PM static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) @@ -312,13 +276,8 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) static int ohci_pci_resume (struct usb_hcd *hcd) { - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* FIXME: we should try to detect loss of VBUS power here */ - prepare_for_handover(hcd); - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); + ohci_finish_controller_resume(hcd); return 0; } diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 5d470263eed8..d4ee27d92be8 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -356,8 +356,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) if ((status = pxa27x_start_hc(&pdev->dev)) < 0) return status; - usb_hcd_resume_root_hub(hcd); - + ohci_finish_controller_resume(hcd); return 0; } #endif diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 54b6ac2e3e4a..4a11e1816017 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -231,14 +231,15 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg) static int ohci_sm501_resume(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev)); + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); - usb_hcd_resume_root_hub(platform_get_drvdata(pdev)); + ohci_finish_controller_resume(hcd); return 0; } #else diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index 7879f2fdad84..7275186db315 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -189,6 +189,7 @@ static int ssb_ohci_resume(struct ssb_device *dev) ssb_device_enable(dev, ohcidev->enable_flags); + ohci_finish_controller_resume(hcd); return 0; } |