aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-06-15 15:08:48 +0000
committerPeter Maydell <peter.maydell@linaro.org>2011-06-15 15:08:48 +0000
commit2d601b5fb663bb2876b85bec255d73bba01e38e6 (patch)
tree71417c64a721b4190186c60b906c39a02933cd1b
parent1f84962a0a5207906b86a725bd45e4e58ca2800d (diff)
hw/usb-ohci.c: Correct handling of OHCI wakeup2011.06-0
Fix some issues with the implementation of OHCI wakeup that meant that we didn't always wake up properly and the keyboard would appear to stop working. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/usb-ohci.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 23a5e66b0..3f9861793 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -373,14 +373,25 @@ static void ohci_wakeup(USBDevice *dev)
OHCIState *s = container_of(bus, OHCIState, bus);
int portnum = dev->port->index;
OHCIPort *port = &s->rhport[portnum];
+ uint32_t intr = 0;
if (port->ctrl & OHCI_PORT_PSS) {
DPRINTF("usb-ohci: port %d: wakeup\n", portnum);
port->ctrl |= OHCI_PORT_PSSC;
port->ctrl &= ~OHCI_PORT_PSS;
- if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
- ohci_set_interrupt(s, OHCI_INTR_RD);
- }
+ intr = OHCI_INTR_RHSC;
+ }
+ /* Note that the controller can be suspended even if this port is not */
+ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+ DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
+ /* This is the one state transition the controller can do by itself */
+ s->ctl &= ~OHCI_CTL_HCFS;
+ s->ctl |= OHCI_USB_RESUME;
+ /* In suspend mode only ResumeDetected is possible, not RHSC:
+ * see the OHCI spec 5.1.2.3.
+ */
+ intr = OHCI_INTR_RD;
}
+ ohci_set_interrupt(s, intr);
}
/* Reset the controller */