From b5c65e3022f285d389759bb699a9cefee79c5fd0 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 8 Jan 2025 22:00:42 -0500 Subject: kernel: xhci: Add xHC interrupt management Signed-off-by: Ian Moffett --- sys/dev/usb/xhci.c | 44 ++++++++++++++++++++++++++++++++++++++++++ sys/include/dev/usb/xhciregs.h | 5 +++++ sys/include/dev/usb/xhcivar.h | 1 + 3 files changed, 50 insertions(+) (limited to 'sys') diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index ad99f72..d2c671f 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -55,6 +55,12 @@ static struct pci_device *hci_dev; static struct timer tmr; +__attribute__((__interrupt__)) static void +xhci_common_isr(void *sf) +{ + pr_trace("Received xHCI interrupt (via PCI MSI-X)\n"); +} + /* * Get port status and control register for a specific * port. @@ -214,6 +220,19 @@ xhci_alloc_dcbaa(struct xhci_hc *hc) return VIRT_TO_PHYS(hc->dcbaap); } +/* + * Initialize MSI-X interrupts. + */ +static int +xhci_init_msix(struct xhci_hc *hc) +{ + struct msi_intr intr; + + intr.name = "xHCI MSI-X"; + intr.handler = xhci_common_isr; + return pci_enable_msix(hci_dev, &intr); +} + /* * Sets up the event ring. */ @@ -312,6 +331,27 @@ xhci_reset(struct xhci_hc *hc) return 0; } +/* + * Enable or disable xHC interrupts. + */ +static void +xhci_set_intr(struct xhci_hc *hc, int enable) +{ + struct xhci_opregs *opregs = hc->opregs; + uint32_t usbcmd; + + enable &= 1; + usbcmd = mmio_read32(&opregs->usbcmd); + + if (enable == 1) { + usbcmd |= USBCMD_INTE; + } else { + usbcmd &= ~USBCMD_INTE; + } + + mmio_write32(&opregs->usbcmd, usbcmd); +} + /* * Start up the host controller and put it into * a running state. Returns 0 on success. @@ -419,9 +459,13 @@ xhci_init_hc(struct xhci_hc *hc) mmio_write64(&opregs->cmd_ring, cmdring); hc->cr_cycle = 1; + xhci_init_msix(hc); xhci_init_evring(hc); xhci_parse_ecp(hc); xhci_start_hc(hc); + + /* Allow the xHC to generate interrupts */ + xhci_set_intr(hc, 1); xhci_init_ports(hc); return 0; } diff --git a/sys/include/dev/usb/xhciregs.h b/sys/include/dev/usb/xhciregs.h index 8c47739..0416601 100644 --- a/sys/include/dev/usb/xhciregs.h +++ b/sys/include/dev/usb/xhciregs.h @@ -73,6 +73,7 @@ struct xhci_opregs { /* USBCMD bits */ #define USBCMD_RUN BIT(0) /* Run/stop */ #define USBCMD_HCRST BIT(1) /* xHC reset */ +#define USBCMD_INTE BIT(2) /* Interrupt Enable */ /* USBSTS bits */ #define USBSTS_HCH BIT(0) /* HC halted */ @@ -113,4 +114,8 @@ struct xhci_opregs { #define XHCI_BIOS_SEM BIT(16) #define XHCI_OS_SEM BIT(24) +/* IMAN bits */ +#define XHCI_IMAN_IP BIT(0) +#define XHCI_IMAN_IE BIT(1) + #endif /* !_USB_XHCIREGS_H_ */ diff --git a/sys/include/dev/usb/xhcivar.h b/sys/include/dev/usb/xhcivar.h index cd445c8..4b0f1bf 100644 --- a/sys/include/dev/usb/xhcivar.h +++ b/sys/include/dev/usb/xhcivar.h @@ -39,6 +39,7 @@ #define XHCI_EVRING_LEN 16 #define XHCI_TRB_SIZE 16 /* In bytes */ #define XHCI_MAX_PROTOS 4 +#define XHCI_IMOD_DEFAULT 0 /* * USB proto (USB 2.0 or 3.0) -- cgit v1.2.3