From 73017ad048c1844a74d7057b195a2fac16f5747e Mon Sep 17 00:00:00 2001 From: kettenis Date: Tue, 19 Jan 2021 19:46:40 +0000 Subject: [PATCH] Implement intx support. ok patrick@ --- sys/dev/fdt/mvkpcie.c | 142 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 123 insertions(+), 19 deletions(-) diff --git a/sys/dev/fdt/mvkpcie.c b/sys/dev/fdt/mvkpcie.c index 511f403bb8e..b037d7dd9d3 100644 --- a/sys/dev/fdt/mvkpcie.c +++ b/sys/dev/fdt/mvkpcie.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mvkpcie.c,v 1.7 2020/07/17 08:07:34 patrick Exp $ */ +/* $OpenBSD: mvkpcie.c,v 1.8 2021/01/19 19:46:40 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis * Copyright (c) 2020 Patrick Wildt @@ -193,6 +193,8 @@ struct mvkpcie_softc { uint32_t sc_bridge_io_hi; uint32_t sc_bridge_mem; + struct interrupt_controller sc_ic; + struct intrhand *sc_intx_handlers[4]; struct interrupt_controller sc_msi_ic; struct intrhand *sc_msi_handlers[32]; struct mvkpcie_dmamem *sc_msi_addr; @@ -242,6 +244,9 @@ int mvkpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); int mvkpcie_intc_intr(void *); +void *mvkpcie_intc_intr_establish(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); +void mvkpcie_intc_intr_disestablish(void *); void *mvkpcie_intc_intr_establish_msi(void *, uint64_t *, uint64_t *, int , struct cpu_info *, int (*)(void *), void *, char *); void mvkpcie_intc_intr_disestablish_msi(void *); @@ -267,6 +272,7 @@ mvkpcie_attach(struct device *parent, struct device *self, void *aux) int i, j, nranges, rangeslen; pcireg_t csr, bir, blr; uint32_t reg; + int node; int timo; if (faa->fa_nreg < 1) { @@ -529,6 +535,15 @@ mvkpcie_attach(struct device *parent, struct device *self, void *aux) pba.pba_bus = sc->sc_bus; pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; + node = OF_getnodebyname(faa->fa_node, "interrupt-controller"); + if (node) { + sc->sc_ic.ic_node = node; + sc->sc_ic.ic_cookie = self; + sc->sc_ic.ic_establish = mvkpcie_intc_intr_establish; + sc->sc_ic.ic_disestablish = mvkpcie_intc_intr_disestablish; + arm_intr_register_fdt(&sc->sc_ic); + } + sc->sc_msi_ic.ic_node = faa->fa_node; sc->sc_msi_ic.ic_cookie = self; sc->sc_msi_ic.ic_establish_msi = mvkpcie_intc_intr_establish_msi; @@ -715,7 +730,20 @@ mvkpcie_conf_write(void *v, pcitag_t tag, int off, pcireg_t data) int mvkpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { - return -1; + int pin = pa->pa_rawintrpin; + + if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX) + return -1; + + if (pa->pa_tag == 0) + return -1; + + ihp->ih_pc = pa->pa_pc; + ihp->ih_tag = pa->pa_intrtag; + ihp->ih_intrpin = pa->pa_intrpin; + ihp->ih_type = PCI_INTX; + + return 0; } const char * @@ -835,29 +863,105 @@ mvkpcie_intc_intr(void *cookie) if (!(HREAD4(sc, HOST_CTRL_INT_STATUS) & HOST_CTRL_INT_MASK_CORE_INT)) return 0; - if (!(HREAD4(sc, PCIE_CORE_ISR0_STATUS) & PCIE_CORE_ISR0_MASK_MSI_INT)) - return 0; + if (HREAD4(sc, PCIE_CORE_ISR0_STATUS) & PCIE_CORE_ISR0_MASK_MSI_INT) { + pending = HREAD4(sc, PCIE_CORE_MSI_STATUS); + while (pending) { + i = ffs(pending) - 1; + HWRITE4(sc, PCIE_CORE_MSI_STATUS, (1 << i)); + pending &= ~(1 << i); + + i = HREAD4(sc, PCIE_CORE_MSI_PAYLOAD) & 0xff; + if ((ih = sc->sc_msi_handlers[i]) != NULL) { + s = splraise(ih->ih_ipl); + if (ih->ih_func(ih->ih_arg)) + ih->ih_count.ec_count++; + splx(s); + } + } + HWRITE4(sc, PCIE_CORE_ISR0_STATUS, PCIE_CORE_ISR0_MASK_MSI_INT); + } - pending = HREAD4(sc, PCIE_CORE_MSI_STATUS); - while (pending) { - i = ffs(pending) - 1; - HWRITE4(sc, PCIE_CORE_MSI_STATUS, (1 << i)); - pending &= ~(1 << i); - - i = HREAD4(sc, PCIE_CORE_MSI_PAYLOAD) & 0xff; - if ((ih = sc->sc_msi_handlers[i]) != NULL) { - s = splraise(ih->ih_ipl); - if (ih->ih_func(ih->ih_arg)) - ih->ih_count.ec_count++; - splx(s); + pending = HREAD4(sc, PCIE_CORE_ISR1_STATUS); + for (i = 0; i < nitems(sc->sc_intx_handlers); i++) { + if (pending & PCIE_CORE_ISR1_MASK_INTX(i)) { + if ((ih = sc->sc_intx_handlers[i]) != NULL) { + s = splraise(ih->ih_ipl); + if (ih->ih_func(ih->ih_arg)) + ih->ih_count.ec_count++; + splx(s); + } } } + HWRITE4(sc, PCIE_CORE_ISR1_STATUS, pending); - HWRITE4(sc, PCIE_CORE_ISR0_STATUS, PCIE_CORE_ISR0_MASK_MSI_INT); HWRITE4(sc, HOST_CTRL_INT_STATUS, HOST_CTRL_INT_MASK_CORE_INT); return 1; } +void * +mvkpcie_intc_intr_establish(void *cookie, int *cell, int level, + struct cpu_info *ci, int (*func)(void *), void *arg, char *name) +{ + struct mvkpcie_softc *sc = (struct mvkpcie_softc *)cookie; + struct intrhand *ih; + int irq = cell[0]; + int s; + + if (ci != NULL && !CPU_IS_PRIMARY(ci)) + return NULL; + + if (irq < 0 || irq > nitems(sc->sc_intx_handlers)) + return NULL; + + /* Don't allow shared interrupts for now. */ + if (sc->sc_intx_handlers[irq]) + return NULL; + + ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK); + ih->ih_func = func; + ih->ih_arg = arg; + ih->ih_ipl = level & IPL_IRQMASK; + ih->ih_irq = irq; + ih->ih_name = name; + ih->ih_sc = sc; + + s = splhigh(); + + sc->sc_intx_handlers[irq] = ih; + + if (name != NULL) + evcount_attach(&ih->ih_count, name, &ih->ih_irq); + + mvkpcie_intc_recalc_ipl(sc); + + splx(s); + + HCLR4(sc, PCIE_CORE_ISR1_MASK, PCIE_CORE_ISR1_MASK_INTX(irq)); + + return (ih); +} + +void +mvkpcie_intc_intr_disestablish(void *cookie) +{ + struct intrhand *ih = cookie; + struct mvkpcie_softc *sc = ih->ih_sc; + int s; + + HSET4(sc, PCIE_CORE_ISR1_MASK, PCIE_CORE_ISR1_MASK_INTX(ih->ih_irq)); + + s = splhigh(); + + sc->sc_intx_handlers[ih->ih_irq] = NULL; + if (ih->ih_name != NULL) + evcount_detach(&ih->ih_count); + free(ih, M_DEVBUF, sizeof(*ih)); + + mvkpcie_intc_recalc_ipl(sc); + + splx(s); +} + void * mvkpcie_intc_intr_establish_msi(void *cookie, uint64_t *addr, uint64_t *data, int level, struct cpu_info *ci, int (*func)(void *), void *arg, char *name) @@ -937,8 +1041,8 @@ mvkpcie_intc_recalc_ipl(struct mvkpcie_softc *sc) int min = IPL_HIGH; int irq; - for (irq = 0; irq < nitems(sc->sc_msi_handlers); irq++) { - ih = sc->sc_msi_handlers[irq]; + for (irq = 0; irq < nitems(sc->sc_intx_handlers); irq++) { + ih = sc->sc_intx_handlers[irq]; if (ih == NULL) continue; -- 2.20.1