Index: sys/riscv/riscv/plic.c =================================================================== --- sys/riscv/riscv/plic.c +++ sys/riscv/riscv/plic.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -126,11 +127,11 @@ sc = device_get_softc(dev); src = (struct plic_irqsrc *)isrc; - cpu = PCPU_GET(cpuid); - - reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); - reg &= ~(1 << (src->irq % 32)); - WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); + CPU_FOREACH(cpu) { + reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); + reg &= ~(1 << (src->irq % 32)); + WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); + } } static void @@ -144,13 +145,11 @@ sc = device_get_softc(dev); src = (struct plic_irqsrc *)isrc; - WR4(sc, PLIC_PRIORITY(src->irq), 1); - - cpu = PCPU_GET(cpuid); - - reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); - reg |= (1 << (src->irq % 32)); - WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); + CPU_FOREACH(cpu) { + reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); + reg |= (1 << (src->irq % 32)); + WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); + } } static int @@ -196,6 +195,7 @@ struct plic_softc *sc; struct intr_pic *pic; uint32_t irq; + uint32_t reg; const char *name; phandle_t node; phandle_t xref; @@ -233,7 +233,6 @@ isrcs = sc->isrcs; name = device_get_nameunit(sc->dev); - cpu = PCPU_GET(cpuid); for (irq = 1; irq <= sc->ndev; irq++) { isrcs[irq].irq = irq; error = intr_isrc_register(&isrcs[irq].isrc, sc->dev, @@ -241,10 +240,20 @@ if (error != 0) return (error); + /* + * Disable all interrupts by lowering the priority and clearing + * the enable bit. They will be enabled later on during + * plic_setup_intr() and plic_enable_intr(). + */ WR4(sc, PLIC_PRIORITY(irq), 0); - WR4(sc, PLIC_ENABLE(irq, cpu), 0); + CPU_FOREACH(cpu) { + reg = RD4(sc, PLIC_ENABLE(irq, cpu)); + reg &= ~(1 << (irq % 32)); + WR4(sc, PLIC_ENABLE(irq, cpu), reg); + } } - WR4(sc, PLIC_THRESHOLD(cpu), 0); + CPU_FOREACH(cpu) + WR4(sc, PLIC_THRESHOLD(cpu), 0); xref = OF_xref_from_node(node); pic = intr_pic_register(sc->dev, xref); @@ -280,6 +289,22 @@ WR4(sc, PLIC_PRIORITY(src->irq), 1); } +static int +plic_setup_intr(device_t dev, struct intr_irqsrc *isrc, + struct resource *res, struct intr_map_data *data) +{ + struct plic_softc *sc; + struct plic_irqsrc *src; + + if (isrc->isrc_handlers == 0) { + sc = device_get_softc(dev); + src = (struct plic_irqsrc *)isrc; + WR4(sc, PLIC_PRIORITY(src->irq), 1); + } + + return (0); +} + static device_method_t plic_methods[] = { DEVMETHOD(device_probe, plic_probe), DEVMETHOD(device_attach, plic_attach), @@ -289,6 +314,7 @@ DEVMETHOD(pic_map_intr, plic_map_intr), DEVMETHOD(pic_pre_ithread, plic_pre_ithread), DEVMETHOD(pic_post_ithread, plic_post_ithread), + DEVMETHOD(pic_setup_intr, plic_setup_intr), DEVMETHOD_END };