summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2012-01-20 17:09:58 +0100
committerGerd Hoffmann <kraxel@redhat.com>2012-02-10 12:16:31 +0100
commit8c735e431d384663137a709c8207f4ada3146205 (patch)
tree86e18e661ecbb5130834705f45257cafe914cf84 /hw
parentb819d7169a8f026c7b9174b7cbce8ab50fc7908a (diff)
xhci: remote wakeup support
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb-xhci.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 65214af9c4..3026edbcdd 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2698,6 +2698,26 @@ static void xhci_detach(USBPort *usbport)
xhci_update_port(xhci, port, 1);
}
+static void xhci_wakeup(USBPort *usbport)
+{
+ XHCIState *xhci = usbport->opaque;
+ XHCIPort *port = &xhci->ports[usbport->index];
+ int nr = port->port.index + 1;
+ XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+ uint32_t pls;
+
+ pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
+ if (pls != 3) {
+ return;
+ }
+ port->portsc |= 0xf << PORTSC_PLS_SHIFT;
+ if (port->portsc & PORTSC_PLC) {
+ return;
+ }
+ port->portsc |= PORTSC_PLC;
+ xhci_event(xhci, &ev);
+}
+
static void xhci_complete(USBPort *port, USBPacket *packet)
{
XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
@@ -2714,6 +2734,7 @@ static void xhci_child_detach(USBPort *port, USBDevice *child)
static USBPortOps xhci_port_ops = {
.attach = xhci_attach,
.detach = xhci_detach,
+ .wakeup = xhci_wakeup,
.complete = xhci_complete,
.child_detach = xhci_child_detach,
};