aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-01-23 18:28:07 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 17:49:56 -0500
commit6a9062f393fa48125df23c5491543828a21e1ae0 (patch)
treeca79e036f5a00253af790b45da6a6102b58ff97c /drivers/usb
parentb1e8f0a6a8805c971857cd10a65cf8caa4c1a672 (diff)
[PATCH] USB: ohci uses driver model wakeup flags
This makes OHCI use the driver model wakeup control bits for its root hub (e.g. disable on amd756, because of chip erratum) and for the controller itself. It no longer uses the hcd glue bits with those roles, and depends on the previous patch making the root hub available earlier. Note that on most platforms (boot code properly setting the RWC bit) this gives a partial workaround for the way PCI isn't currently flagging devices that support PME# signals. (Because of odd PCI init sequencing on PPC.) That's because many OHCI controllers support "legacy PCI PM" ... without involving any PCI PM capability. USB wakeup from STR, if it works on your system, may still involve tweaking things by hand in /proc/acpi/wakeup. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ohci-hcd.c49
-rw-r--r--drivers/usb/host/ohci-hub.c12
-rw-r--r--drivers/usb/host/ohci-pci.c15
3 files changed, 46 insertions, 30 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 2990be269000..544f7589912f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -443,11 +443,16 @@ ohci_reboot (struct notifier_block *block, unsigned long code, void *null)
443static int ohci_init (struct ohci_hcd *ohci) 443static int ohci_init (struct ohci_hcd *ohci)
444{ 444{
445 int ret; 445 int ret;
446 struct usb_hcd *hcd = ohci_to_hcd(ohci);
446 447
447 disable (ohci); 448 disable (ohci);
448 ohci->regs = ohci_to_hcd(ohci)->regs; 449 ohci->regs = hcd->regs;
449 ohci->next_statechange = jiffies; 450 ohci->next_statechange = jiffies;
450 451
452 /* REVISIT this BIOS handshake is now moved into PCI "quirks", and
453 * was never needed for most non-PCI systems ... remove the code?
454 */
455
451#ifndef IR_DISABLE 456#ifndef IR_DISABLE
452 /* SMM owns the HC? not for long! */ 457 /* SMM owns the HC? not for long! */
453 if (!no_handshake && ohci_readl (ohci, 458 if (!no_handshake && ohci_readl (ohci,
@@ -478,8 +483,10 @@ static int ohci_init (struct ohci_hcd *ohci)
478 483
479 /* Disable HC interrupts */ 484 /* Disable HC interrupts */
480 ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); 485 ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
481 // flush the writes 486
482 (void) ohci_readl (ohci, &ohci->regs->control); 487 /* flush the writes, and save key bits like RWC */
488 if (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_RWC)
489 ohci->hc_control |= OHCI_CTRL_RWC;
483 490
484 /* Read the number of ports unless overridden */ 491 /* Read the number of ports unless overridden */
485 if (ohci->num_ports == 0) 492 if (ohci->num_ports == 0)
@@ -488,16 +495,19 @@ static int ohci_init (struct ohci_hcd *ohci)
488 if (ohci->hcca) 495 if (ohci->hcca)
489 return 0; 496 return 0;
490 497
491 ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller, 498 ohci->hcca = dma_alloc_coherent (hcd->self.controller,
492 sizeof *ohci->hcca, &ohci->hcca_dma, 0); 499 sizeof *ohci->hcca, &ohci->hcca_dma, 0);
493 if (!ohci->hcca) 500 if (!ohci->hcca)
494 return -ENOMEM; 501 return -ENOMEM;
495 502
496 if ((ret = ohci_mem_init (ohci)) < 0) 503 if ((ret = ohci_mem_init (ohci)) < 0)
497 ohci_stop (ohci_to_hcd(ohci)); 504 ohci_stop (hcd);
505 else {
506 register_reboot_notifier (&ohci->reboot_notifier);
507 create_debug_files (ohci);
508 }
498 509
499 return ret; 510 return ret;
500
501} 511}
502 512
503/*-------------------------------------------------------------------------*/ 513/*-------------------------------------------------------------------------*/
@@ -510,6 +520,7 @@ static int ohci_run (struct ohci_hcd *ohci)
510{ 520{
511 u32 mask, temp; 521 u32 mask, temp;
512 int first = ohci->fminterval == 0; 522 int first = ohci->fminterval == 0;
523 struct usb_hcd *hcd = ohci_to_hcd(ohci);
513 524
514 disable (ohci); 525 disable (ohci);
515 526
@@ -525,18 +536,17 @@ static int ohci_run (struct ohci_hcd *ohci)
525 /* also: power/overcurrent flags in roothub.a */ 536 /* also: power/overcurrent flags in roothub.a */
526 } 537 }
527 538
528 /* Reset USB nearly "by the book". RemoteWakeupConnected 539 /* Reset USB nearly "by the book". RemoteWakeupConnected was
529 * saved if boot firmware (BIOS/SMM/...) told us it's connected 540 * saved if boot firmware (BIOS/SMM/...) told us it's connected,
530 * (for OHCI integrated on mainboard, it normally is) 541 * or if bus glue did the same (e.g. for PCI add-in cards with
542 * PCI PM support).
531 */ 543 */
532 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
533 ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", 544 ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
534 hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), 545 hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
535 ohci->hc_control); 546 ohci_readl (ohci, &ohci->regs->control));
536 547 if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
537 if (ohci->hc_control & OHCI_CTRL_RWC 548 && !device_may_wakeup(hcd->self.controller))
538 && !(ohci->flags & OHCI_QUIRK_AMD756)) 549 device_init_wakeup(hcd->self.controller, 1);
539 ohci_to_hcd(ohci)->can_wakeup = 1;
540 550
541 switch (ohci->hc_control & OHCI_CTRL_HCFS) { 551 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
542 case OHCI_USB_OPER: 552 case OHCI_USB_OPER:
@@ -632,7 +642,7 @@ retry:
632 ohci->hc_control &= OHCI_CTRL_RWC; 642 ohci->hc_control &= OHCI_CTRL_RWC;
633 ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; 643 ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
634 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 644 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
635 ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; 645 hcd->state = HC_STATE_RUNNING;
636 646
637 /* wake on ConnectStatusChange, matching external hubs */ 647 /* wake on ConnectStatusChange, matching external hubs */
638 ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); 648 ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -667,15 +677,10 @@ retry:
667 677
668 // POTPGT delay is bits 24-31, in 2 ms units. 678 // POTPGT delay is bits 24-31, in 2 ms units.
669 mdelay ((temp >> 23) & 0x1fe); 679 mdelay ((temp >> 23) & 0x1fe);
670 ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; 680 hcd->state = HC_STATE_RUNNING;
671 681
672 ohci_dump (ohci, 1); 682 ohci_dump (ohci, 1);
673 683
674 if (ohci_to_hcd(ohci)->self.root_hub == NULL) {
675 register_reboot_notifier (&ohci->reboot_notifier);
676 create_debug_files (ohci);
677 }
678
679 return 0; 684 return 0;
680} 685}
681 686
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 4b2226d77b34..0bb972b58336 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -107,7 +107,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
107 &ohci->regs->intrstatus); 107 &ohci->regs->intrstatus);
108 108
109 /* maybe resume can wake root hub */ 109 /* maybe resume can wake root hub */
110 if (hcd->remote_wakeup) 110 if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
111 ohci->hc_control |= OHCI_CTRL_RWE; 111 ohci->hc_control |= OHCI_CTRL_RWE;
112 else 112 else
113 ohci->hc_control &= ~OHCI_CTRL_RWE; 113 ohci->hc_control &= ~OHCI_CTRL_RWE;
@@ -246,9 +246,9 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
246 (void) ohci_readl (ohci, &ohci->regs->control); 246 (void) ohci_readl (ohci, &ohci->regs->control);
247 msleep (3); 247 msleep (3);
248 248
249 temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; 249 temp = ohci->hc_control;
250 if (hcd->can_wakeup) 250 temp &= OHCI_CTRL_RWC;
251 temp |= OHCI_CTRL_RWC; 251 temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
252 ohci->hc_control = temp; 252 ohci->hc_control = temp;
253 ohci_writel (ohci, temp, &ohci->regs->control); 253 ohci_writel (ohci, temp, &ohci->regs->control);
254 (void) ohci_readl (ohci, &ohci->regs->control); 254 (void) ohci_readl (ohci, &ohci->regs->control);
@@ -302,7 +302,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
302{ 302{
303 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 303 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
304 int i, changed = 0, length = 1; 304 int i, changed = 0, length = 1;
305 int can_suspend = hcd->can_wakeup; 305 int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
306 unsigned long flags; 306 unsigned long flags;
307 307
308 spin_lock_irqsave (&ohci->lock, flags); 308 spin_lock_irqsave (&ohci->lock, flags);
@@ -354,7 +354,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
354 */ 354 */
355 if (!(status & RH_PS_CCS)) 355 if (!(status & RH_PS_CCS))
356 continue; 356 continue;
357 if ((status & RH_PS_PSS) && hcd->remote_wakeup) 357 if ((status & RH_PS_PSS) && can_suspend)
358 continue; 358 continue;
359 can_suspend = 0; 359 can_suspend = 0;
360 } 360 }
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1b09dde068e1..1bfe96f4d045 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd)
35 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 35 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
36 int ret; 36 int ret;
37 37
38 if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { 38 /* REVISIT this whole block should move to reset(), which handles
39 * all the other one-time init.
40 */
41 if (hcd->self.controller) {
39 struct pci_dev *pdev = to_pci_dev(hcd->self.controller); 42 struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
40 43
41 /* AMD 756, for most chips (early revs), corrupts register 44 /* AMD 756, for most chips (early revs), corrupts register
@@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd)
45 && pdev->device == 0x740c) { 48 && pdev->device == 0x740c) {
46 ohci->flags = OHCI_QUIRK_AMD756; 49 ohci->flags = OHCI_QUIRK_AMD756;
47 ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); 50 ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
48 // also somewhat erratum 10 (suspend/resume issues) 51 /* also erratum 10 (suspend/resume issues) */
52 device_init_wakeup(&hcd->self.root_hub->dev, 0);
49 } 53 }
50 54
51 /* FIXME for some of the early AMD 760 southbridges, OHCI 55 /* FIXME for some of the early AMD 760 southbridges, OHCI
@@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd)
88 ohci_dbg (ohci, 92 ohci_dbg (ohci,
89 "enabled Compaq ZFMicro chipset quirk\n"); 93 "enabled Compaq ZFMicro chipset quirk\n");
90 } 94 }
95
96 /* RWC may not be set for add-in PCI cards, since boot
97 * firmware probably ignored them. This transfers PCI
98 * PM wakeup capabilities (once the PCI layer is fixed).
99 */
100 if (device_may_wakeup(&pdev->dev))
101 ohci->hc_control |= OHCI_CTRL_RWC;
91 } 102 }
92 103
93 /* NOTE: there may have already been a first reset, to 104 /* NOTE: there may have already been a first reset, to