summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller/xhci.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2011-10-26 17:43:27 +0000
committerhselasky <hselasky@FreeBSD.org>2011-10-26 17:43:27 +0000
commitd16be1d43585dd21b7cefb1b2d1c7d65968ee7cb (patch)
tree61cae9efa2e722177b98d8b8f0321329ef7db193 /sys/dev/usb/controller/xhci.c
parent6ae1a53eda68ab65a69718a023f2b6cd2b3dce28 (diff)
downloadFreeBSD-src-d16be1d43585dd21b7cefb1b2d1c7d65968ee7cb.zip
FreeBSD-src-d16be1d43585dd21b7cefb1b2d1c7d65968ee7cb.tar.gz
Fix suspend and resume of FULL and HIGH speed USB devices
in the generic XHCI driver. There appears to be some minor logic missing for this feature to work. MFC after: 3 days
Diffstat (limited to 'sys/dev/usb/controller/xhci.c')
-rw-r--r--sys/dev/usb/controller/xhci.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index f6c8c0e..0df4c4d 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -3048,7 +3048,9 @@ xhci_roothub_exec(struct usb_device *udev,
}
port = XHCI_PORTSC(index);
- v = XREAD4(sc, oper, port) & ~XHCI_PS_CLEAR;
+ v = XREAD4(sc, oper, port);
+ i = XHCI_PS_PLS_GET(v);
+ v &= ~XHCI_PS_CLEAR;
switch (value) {
case UHF_C_BH_PORT_RESET:
@@ -3082,6 +3084,17 @@ xhci_roothub_exec(struct usb_device *udev,
XWRITE4(sc, oper, port, v & ~XHCI_PS_PIC_SET(3));
break;
case UHF_PORT_SUSPEND:
+
+ /* U3 -> U15 */
+ if (i == 3) {
+ XWRITE4(sc, oper, port, v |
+ XHCI_PS_PLS_SET(0xF) | XHCI_PS_LWS);
+ }
+
+ /* wait 20ms for resume sequence to complete */
+ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
+
+ /* U0 */
XWRITE4(sc, oper, port, v |
XHCI_PS_PLS_SET(0) | XHCI_PS_LWS);
break;
OpenPOWER on IntegriCloud