diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index c403b4ba45ab..b773c28a20b6 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -347,6 +347,7 @@ xhci_start_controller(struct xhci_softc *sc) struct usb_page_search buf_res; struct xhci_hw_root *phwr; struct xhci_dev_ctx_addr *pdctxa; + usb_error_t err; uint64_t addr; uint32_t temp; uint16_t i; @@ -358,22 +359,9 @@ xhci_start_controller(struct xhci_softc *sc) sc->sc_command_ccs = 1; sc->sc_command_idx = 0; - /* Reset controller */ - XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST); - - for (i = 0; i != 100; i++) { - usb_pause_mtx(NULL, hz / 100); - temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) | - (XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR); - if (!temp) - break; - } - - if (temp) { - device_printf(sc->sc_bus.parent, "Controller " - "reset timeout.\n"); - return (USB_ERR_IOERROR); - } + err = xhci_reset_controller(sc); + if (err) + return (err); /* set up number of device slots */ DPRINTF("CONFIG=0x%08x -> 0x%08x\n", @@ -520,6 +508,33 @@ xhci_halt_controller(struct xhci_softc *sc) return (0); } +usb_error_t +xhci_reset_controller(struct xhci_softc *sc) +{ + uint32_t temp = 0; + uint16_t i; + + DPRINTF("\n"); + + /* Reset controller */ + XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST); + + for (i = 0; i != 100; i++) { + usb_pause_mtx(NULL, hz / 100); + temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) | + (XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR); + if (!temp) + break; + } + + if (temp) { + device_printf(sc->sc_bus.parent, "Controller " + "reset timeout.\n"); + return (USB_ERR_IOERROR); + } + return (0); +} + usb_error_t xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) { @@ -671,10 +686,12 @@ xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) case USB_HW_POWER_SUSPEND: DPRINTF("Stopping the XHCI\n"); xhci_halt_controller(sc); + xhci_reset_controller(sc); break; case USB_HW_POWER_SHUTDOWN: DPRINTF("Stopping the XHCI\n"); xhci_halt_controller(sc); + xhci_reset_controller(sc); break; case USB_HW_POWER_RESUME: DPRINTF("Starting the XHCI\n"); diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h index e8bc9addb6f8..8ca628580c94 100644 --- a/sys/dev/usb/controller/xhci.h +++ b/sys/dev/usb/controller/xhci.h @@ -525,6 +525,7 @@ struct xhci_softc { uint8_t xhci_use_polling(void); usb_error_t xhci_halt_controller(struct xhci_softc *); +usb_error_t xhci_reset_controller(struct xhci_softc *); usb_error_t xhci_init(struct xhci_softc *, device_t, uint8_t); usb_error_t xhci_start_controller(struct xhci_softc *); void xhci_interrupt(struct xhci_softc *); diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index cb0f3dafef5e..cada25ad5003 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -348,6 +348,7 @@ xhci_pci_detach(device_t self) usb_callout_drain(&sc->sc_callout); xhci_halt_controller(sc); + xhci_reset_controller(sc); pci_disable_busmaster(self);