-/* $OpenBSD: xhci.c,v 1.132 2024/08/06 17:30:04 kettenis Exp $ */
+/* $OpenBSD: xhci.c,v 1.133 2024/08/15 17:17:05 kettenis Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
{
uint64_t paddr;
uint32_t hcr;
+ int i;
/* Make sure to program a number of device slots we can handle. */
if (sc->sc_noslot > USB_MAX_DEVICES)
DPRINTF(("%s: ERDP=%#x%#x\n", DEVNAME(sc),
XRREAD4(sc, XHCI_ERDP_HI(0)), XRREAD4(sc, XHCI_ERDP_LO(0))));
+ /*
+ * If we successfully saved the state during suspend, restore
+ * it here. Otherwise some Intel controllers don't function
+ * correctly after resume.
+ */
+ if (sc->sc_saved_state) {
+ XOWRITE4(sc, XHCI_USBCMD, XHCI_CMD_CRS); /* Restore state */
+ hcr = XOREAD4(sc, XHCI_USBSTS);
+ for (i = 0; i < 100; i++) {
+ usb_delay_ms(&sc->sc_bus, 1);
+ hcr = XOREAD4(sc, XHCI_USBSTS) & XHCI_STS_RSS;
+ if (!hcr)
+ break;
+ }
+
+ if (hcr)
+ printf("%s: restore state timeout\n", DEVNAME(sc));
+
+ sc->sc_saved_state = 0;
+ }
+
/* Enable interrupts. */
hcr = XRREAD4(sc, XHCI_IMAN(0));
XRWRITE4(sc, XHCI_IMAN(0), hcr | XHCI_IMAN_INTR_ENA);
* unless they have seen a save state command. This in turn
* will prevent the SoC from reaching its lowest idle state.
* So save the state here.
- *
- * Note that we don't restore this saved state anywhere.
- * Instead we reset the controller and reinitialize it from
- * scratch when we resume.
*/
XOWRITE4(sc, XHCI_USBCMD, XHCI_CMD_CSS); /* Save state */
return;
}
+ sc->sc_saved_state = 1;
+
/* Disable interrupts. */
XRWRITE4(sc, XHCI_IMOD(0), 0);
XRWRITE4(sc, XHCI_IMAN(0), 0);