summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/controller')
-rw-r--r--sys/dev/usb/controller/xhci.c15
-rw-r--r--sys/dev/usb/controller/xhcireg.h2
2 files changed, 15 insertions, 2 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;
diff --git a/sys/dev/usb/controller/xhcireg.h b/sys/dev/usb/controller/xhcireg.h
index 71c5c28..8be502e 100644
--- a/sys/dev/usb/controller/xhcireg.h
+++ b/sys/dev/usb/controller/xhcireg.h
@@ -133,7 +133,7 @@
#define XHCI_PS_WOE 0x08000000 /* RW - wake on over-current enable */
#define XHCI_PS_DR 0x40000000 /* RO - device removable */
#define XHCI_PS_WPR 0x80000000U /* RW - warm port reset */
-#define XHCI_PS_CLEAR 0x80FF00F7U /* command bits */
+#define XHCI_PS_CLEAR 0x80FF01FFU /* command bits */
#define XHCI_PORTPMSC(n) (0x3F4 + (0x10 * (n))) /* XHCI status and control */
#define XHCI_PM3_U1TO_GET(x) (((x) >> 0) & 0xFF) /* RW - U1 timeout */
OpenPOWER on IntegriCloud