From 3537d35f0dd3fad8a819578adeca75ed120b5966 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 8 Aug 2025 23:08:16 -0400 Subject: kernel: xhci: Add xhci_stop_hc() to stop the xHC Implement a new xhci_stop_hc() an call it before we perform a reset. We cannot be certain that the firmware (e.g., UEFI, BIOS) took the care to stop the xHCI before passing control over to us. Signed-off-by: Ian Moffett --- sys/dev/usb/xhci.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index 32c4315..2206bb7 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -379,6 +379,26 @@ xhci_start_hc(struct xhci_hc *hc) return 0; } +/* + * Stop and bring down the host controller. + * Returns 0 on success. + */ +static int +xhci_stop_hc(struct xhci_hc *hc) +{ + struct xhci_opregs *opregs = hc->opregs; + uint32_t usbcmd; + + /* Don't continue if we aren't running */ + usbcmd = mmio_read32(&opregs->usbcmd); + if (!ISSET(usbcmd, USBCMD_RUN)) + return 0; + + usbcmd &= ~USBCMD_RUN; + mmio_write32(&opregs->usbcmd, usbcmd); + return 0; +} + static int xhci_init_ports(struct xhci_hc *hc) { @@ -461,6 +481,12 @@ xhci_init_hc(struct xhci_hc *hc) return -1; } + pr_trace("stopping xHC chip...\n"); + if ((error = xhci_stop_hc(hc)) != 0) { + pr_error("run/stop timeout\n"); + return error; + } + pr_trace("resetting xHC chip...\n"); if ((error = xhci_reset(hc)) != 0) { pr_error("reset timeout\n"); -- cgit v1.2.3