diff options
author | Ian Moffett <ian@osmora.org> | 2025-01-08 22:00:42 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-01-08 22:01:34 -0500 |
commit | b5c65e3022f285d389759bb699a9cefee79c5fd0 (patch) | |
tree | be502cdeae88c38fd270bfb2e447295f0ba78517 | |
parent | a5da98ef1f85a78d935a8ba048487eb650b7eb07 (diff) |
kernel: xhci: Add xHC interrupt management
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/dev/usb/xhci.c | 44 | ||||
-rw-r--r-- | sys/include/dev/usb/xhciregs.h | 5 | ||||
-rw-r--r-- | sys/include/dev/usb/xhcivar.h | 1 |
3 files changed, 50 insertions, 0 deletions
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. @@ -215,6 +221,19 @@ xhci_alloc_dcbaa(struct xhci_hc *hc) } /* + * 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. */ static void @@ -313,6 +332,27 @@ xhci_reset(struct xhci_hc *hc) } /* + * 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) |