aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ohci-at91.c1
-rw-r--r--drivers/usb/host/ohci-ep93xx.c2
-rw-r--r--drivers/usb/host/ohci-hub.c43
-rw-r--r--drivers/usb/host/ohci-omap.c5
-rw-r--r--drivers/usb/host/ohci-pci.c43
-rw-r--r--drivers/usb/host/ohci-pxa27x.c3
-rw-r--r--drivers/usb/host/ohci-sm501.c5
-rw-r--r--drivers/usb/host/ohci-ssb.c1
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)
348 if (!clocked) 348 if (!clocked)
349 at91_start_clock(); 349 at91_start_clock();
350 350
351 ohci_finish_controller_resume(hcd);
351 return 0; 352 return 0;
352} 353}
353#else 354#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)
192 ohci->next_statechange = jiffies; 192 ohci->next_statechange = jiffies;
193 193
194 ep93xx_start_hc(&pdev->dev); 194 ep93xx_start_hc(&pdev->dev);
195 usb_hcd_resume_root_hub(hcd);
196 195
196 ohci_finish_controller_resume(hcd);
197 return 0; 197 return 0;
198} 198}
199#endif 199#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)
326 return rc; 326 return rc;
327} 327}
328 328
329/* Carry out the final steps of resuming the controller device */
330static void ohci_finish_controller_resume(struct usb_hcd *hcd)
331{
332 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
333 int port;
334 bool need_reinit = false;
335
336 /* See if the controller is already running or has been reset */
337 ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
338 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
339 need_reinit = true;
340 } else {
341 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
342 case OHCI_USB_OPER:
343 case OHCI_USB_RESET:
344 need_reinit = true;
345 }
346 }
347
348 /* If needed, reinitialize and suspend the root hub */
349 if (need_reinit) {
350 spin_lock_irq(&ohci->lock);
351 hcd->state = HC_STATE_RESUMING;
352 ohci_rh_resume(ohci);
353 hcd->state = HC_STATE_QUIESCING;
354 ohci_rh_suspend(ohci, 0);
355 hcd->state = HC_STATE_SUSPENDED;
356 spin_unlock_irq(&ohci->lock);
357 }
358
359 /* Normally just turn on port power and enable interrupts */
360 else {
361 ohci_dbg(ohci, "powerup ports\n");
362 for (port = 0; port < ohci->num_ports; port++)
363 ohci_writel(ohci, RH_PS_PPS,
364 &ohci->regs->roothub.portstatus[port]);
365
366 ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
367 ohci_readl(ohci, &ohci->regs->intrenable);
368 msleep(20);
369 }
370}
371
329/* Carry out polling-, autostop-, and autoresume-related state changes */ 372/* Carry out polling-, autostop-, and autoresume-related state changes */
330static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, 373static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
331 int any_connected) 374 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)
510 510
511static int ohci_omap_resume(struct platform_device *dev) 511static int ohci_omap_resume(struct platform_device *dev)
512{ 512{
513 struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(dev)); 513 struct usb_hcd *hcd = platform_get_drvdata(dev);
514 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
514 515
515 if (time_before(jiffies, ohci->next_statechange)) 516 if (time_before(jiffies, ohci->next_statechange))
516 msleep(5); 517 msleep(5);
517 ohci->next_statechange = jiffies; 518 ohci->next_statechange = jiffies;
518 519
519 omap_ohci_clock_power(1); 520 omap_ohci_clock_power(1);
520 usb_hcd_resume_root_hub(platform_get_drvdata(dev)); 521 ohci_finish_controller_resume(hcd);
521 return 0; 522 return 0;
522} 523}
523 524
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)
238 return ret; 238 return ret;
239} 239}
240 240
241#if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
242 defined(CONFIG_USB_EHCI_HCD_MODULE))
243
244/* Following a power loss, we must prepare to regain control of the ports
245 * we used to own. This means turning on the port power before ehci-hcd
246 * tries to switch ownership.
247 *
248 * This isn't a 100% perfect solution. On most systems the OHCI controllers
249 * lie at lower PCI addresses than the EHCI controller, so they will be
250 * discovered (and hence resumed) first. But there is no guarantee things
251 * will always work this way. If the EHCI controller is resumed first and
252 * the OHCI ports are unpowered, then the handover will fail.
253 */
254static void prepare_for_handover(struct usb_hcd *hcd)
255{
256 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
257 int port;
258
259 /* Here we "know" root ports should always stay powered */
260 ohci_dbg(ohci, "powerup ports\n");
261 for (port = 0; port < ohci->num_ports; port++)
262 ohci_writel(ohci, RH_PS_PPS,
263 &ohci->regs->roothub.portstatus[port]);
264
265 /* Flush those writes */
266 ohci_readl(ohci, &ohci->regs->control);
267 msleep(20);
268}
269
270#else
271
272static inline void prepare_for_handover(struct usb_hcd *hcd)
273{ }
274
275#endif /* CONFIG_USB_PERSIST etc. */
276
277#ifdef CONFIG_PM 241#ifdef CONFIG_PM
278 242
279static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) 243static 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)
312 276
313static int ohci_pci_resume (struct usb_hcd *hcd) 277static int ohci_pci_resume (struct usb_hcd *hcd)
314{ 278{
315 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
316
317 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 279 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
318 280 ohci_finish_controller_resume(hcd);
319 /* FIXME: we should try to detect loss of VBUS power here */
320 prepare_for_handover(hcd);
321 ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
322 return 0; 281 return 0;
323} 282}
324 283
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)
356 if ((status = pxa27x_start_hc(&pdev->dev)) < 0) 356 if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
357 return status; 357 return status;
358 358
359 usb_hcd_resume_root_hub(hcd); 359 ohci_finish_controller_resume(hcd);
360
361 return 0; 360 return 0;
362} 361}
363#endif 362#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)
231static int ohci_sm501_resume(struct platform_device *pdev) 231static int ohci_sm501_resume(struct platform_device *pdev)
232{ 232{
233 struct device *dev = &pdev->dev; 233 struct device *dev = &pdev->dev;
234 struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev)); 234 struct usb_hcd *hcd = platform_get_drvdata(pdev);
235 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
235 236
236 if (time_before(jiffies, ohci->next_statechange)) 237 if (time_before(jiffies, ohci->next_statechange))
237 msleep(5); 238 msleep(5);
238 ohci->next_statechange = jiffies; 239 ohci->next_statechange = jiffies;
239 240
240 sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); 241 sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
241 usb_hcd_resume_root_hub(platform_get_drvdata(pdev)); 242 ohci_finish_controller_resume(hcd);
242 return 0; 243 return 0;
243} 244}
244#else 245#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)
189 189
190 ssb_device_enable(dev, ohcidev->enable_flags); 190 ssb_device_enable(dev, ohcidev->enable_flags);
191 191
192 ohci_finish_controller_resume(hcd);
192 return 0; 193 return 0;
193} 194}
194 195