diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/powerpc/include/intr_machdep.h | 4 | ||||
-rw-r--r-- | sys/powerpc/include/openpicreg.h | 71 | ||||
-rw-r--r-- | sys/powerpc/include/openpicvar.h | 1 | ||||
-rw-r--r-- | sys/powerpc/powermac/hrowpic.c | 10 | ||||
-rw-r--r-- | sys/powerpc/powermac/openpic_macio.c | 1 | ||||
-rw-r--r-- | sys/powerpc/powerpc/intr_machdep.c | 2 | ||||
-rw-r--r-- | sys/powerpc/powerpc/openpic.c | 107 | ||||
-rw-r--r-- | sys/powerpc/powerpc/pic_if.m | 5 | ||||
-rw-r--r-- | sys/powerpc/psim/openpic_iobus.c | 1 |
9 files changed, 143 insertions, 59 deletions
diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h index 25f47f0..ebab93b 100644 --- a/sys/powerpc/include/intr_machdep.h +++ b/sys/powerpc/include/intr_machdep.h @@ -34,7 +34,9 @@ extern device_t pic; struct trapframe; -void powerpc_register_pic(device_t); +driver_filter_t powerpc_ipi_handler; + +void powerpc_register_pic(device_t, u_int); void powerpc_dispatch_intr(u_int, struct trapframe *); int powerpc_enable_intr(void); diff --git a/sys/powerpc/include/openpicreg.h b/sys/powerpc/include/openpicreg.h index 2fa393d..525e66f 100644 --- a/sys/powerpc/include/openpicreg.h +++ b/sys/powerpc/include/openpicreg.h @@ -33,16 +33,35 @@ #define OPENPIC_SIZE 0x40000 /* - * GLOBAL/TIMER register (IDU base + 0x1000) + * Per Processor Registers [private access] (0x00000 - 0x00fff) + */ + +/* IPI dispatch command reg */ +#define OPENPIC_IPI_DISPATCH(ipi) (0x40 + (ipi) * 0x10) + +/* current task priority reg */ +#define OPENPIC_TPR 0x80 +#define OPENPIC_TPR_MASK 0x0000000f + +#define OPENPIC_WHOAMI 0x90 + +/* interrupt acknowledge reg */ +#define OPENPIC_IACK 0xa0 + +/* end of interrupt reg */ +#define OPENPIC_EOI 0xb0 + +/* + * Global registers (0x01000-0x0ffff) */ /* feature reporting reg 0 */ #define OPENPIC_FEATURE 0x1000 -#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff -#define OPENPIC_FEATURE_LAST_CPU_MASK 0x00001f00 -#define OPENPIC_FEATURE_LAST_CPU_SHIFT 8 -#define OPENPIC_FEATURE_LAST_IRQ_MASK 0x07ff0000 -#define OPENPIC_FEATURE_LAST_IRQ_SHIFT 16 +#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff +#define OPENPIC_FEATURE_LAST_CPU_MASK 0x00001f00 +#define OPENPIC_FEATURE_LAST_CPU_SHIFT 8 +#define OPENPIC_FEATURE_LAST_IRQ_MASK 0x07ff0000 +#define OPENPIC_FEATURE_LAST_IRQ_SHIFT 16 /* global config reg 0 */ #define OPENPIC_CONFIG 0x1020 @@ -51,9 +70,9 @@ /* interrupt configuration mode (direct or serial) */ #define OPENPIC_ICR 0x1030 -#define OPENPIC_ICR_SERIAL_MODE (1 << 27) -#define OPENPIC_ICR_SERIAL_RATIO_MASK (0x7 << 28) -#define OPENPIC_ICR_SERIAL_RATIO_SHIFT 28 +#define OPENPIC_ICR_SERIAL_MODE (1 << 27) +#define OPENPIC_ICR_SERIAL_RATIO_MASK (0x7 << 28) +#define OPENPIC_ICR_SERIAL_RATIO_SHIFT 28 /* vendor ID */ #define OPENPIC_VENDOR_ID 0x1080 @@ -67,9 +86,16 @@ /* spurious intr. vector */ #define OPENPIC_SPURIOUS_VECTOR 0x10e0 +/* Timer registers */ +#define OPENPIC_TIMERS 4 +#define OPENPIC_TFREQ 0x10f0 +#define OPENPIC_TCNT(t) (0x1100 + (t) * 0x40) +#define OPENPIC_TBASE(t) (0x1110 + (t) * 0x40) +#define OPENPIC_TVEC(t) (0x1120 + (t) * 0x40) +#define OPENPIC_TDST(t) (0x1130 + (t) * 0x40) /* - * INTERRUPT SOURCE register (IDU base + 0x10000) + * Interrupt Source Configuration Registers (0x10000 - 0x1ffff) */ /* interrupt vector/priority reg */ @@ -92,18 +118,23 @@ #endif /* - * PROCESSOR register (IDU base + 0x20000) + * Per Processor Registers [global access] (0x20000 - 0x3ffff) */ -/* IPI command reg */ -#define OPENPIC_IPI(cpu, ipi) (0x20040 + (cpu) * 0x1000 + (ipi)) +#define OPENPIC_PCPU_BASE(cpu) (0x20000 + (cpu) * 0x1000) -/* current task priority reg */ -#define OPENPIC_CPU_PRIORITY(cpu) (0x20080 + (cpu) * 0x1000) -#define OPENPIC_CPU_PRIORITY_MASK 0x0000000f +#define OPENPIC_PCPU_IPI_DISPATCH(cpu, ipi) \ + (OPENPIC_PCPU_BASE(cpu) + OPENPIC_IPI_DISPATCH(ipi)) -/* interrupt acknowledge reg */ -#define OPENPIC_IACK(cpu) (0x200a0 + (cpu) * 0x1000) +#define OPENPIC_PCPU_TPR(cpu) \ + (OPENPIC_PCPU_BASE(cpu) + OPENPIC_TPR) + +#define OPENPIC_PCPU_WHOAMI(cpu) \ + (OPENPIC_PCPU_BASE(cpu) + OPENPIC_WHOAMI) + +#define OPENPIC_PCPU_IACK(cpu) \ + (OPENPIC_PCPU_BASE(cpu) + OPENPIC_IACK) + +#define OPENPIC_PCPU_EOI(cpu) \ + (OPENPIC_PCPU_BASE(cpu) + OPENPIC_EOI) -/* end of interrupt reg */ -#define OPENPIC_EOI(cpu) (0x200b0 + (cpu) * 0x1000) diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h index 081cf7a..f1db26c 100644 --- a/sys/powerpc/include/openpicvar.h +++ b/sys/powerpc/include/openpicvar.h @@ -57,6 +57,7 @@ int openpic_attach(device_t); void openpic_dispatch(device_t, struct trapframe *); void openpic_enable(device_t, u_int, u_int); void openpic_eoi(device_t, u_int); +void openpic_ipi(device_t, u_int); void openpic_mask(device_t, u_int); void openpic_unmask(device_t, u_int); diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c index cf8a462..59bb82b 100644 --- a/sys/powerpc/powermac/hrowpic.c +++ b/sys/powerpc/powermac/hrowpic.c @@ -68,6 +68,7 @@ static int hrowpic_attach(device_t); static void hrowpic_dispatch(device_t, struct trapframe *); static void hrowpic_enable(device_t, u_int, u_int); static void hrowpic_eoi(device_t, u_int); +static void hrowpic_ipi(device_t, u_int); static void hrowpic_mask(device_t, u_int); static void hrowpic_unmask(device_t, u_int); @@ -80,6 +81,7 @@ static device_method_t hrowpic_methods[] = { DEVMETHOD(pic_dispatch, hrowpic_dispatch), DEVMETHOD(pic_enable, hrowpic_enable), DEVMETHOD(pic_eoi, hrowpic_eoi), + DEVMETHOD(pic_ipi, hrowpic_ipi), DEVMETHOD(pic_mask, hrowpic_mask), DEVMETHOD(pic_unmask, hrowpic_unmask), @@ -167,7 +169,7 @@ hrowpic_attach(device_t dev) hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0); hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff); - powerpc_register_pic(dev); + powerpc_register_pic(dev, 64); return (0); } @@ -250,6 +252,12 @@ hrowpic_eoi(device_t dev __unused, u_int irq __unused) } static void +hrowpic_ipi(device_t dev, u_int irq) +{ + /* No SMP support. */ +} + +static void hrowpic_mask(device_t dev, u_int irq) { struct hrowpic_softc *sc; diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c index 822804e..7d4a9c8 100644 --- a/sys/powerpc/powermac/openpic_macio.c +++ b/sys/powerpc/powermac/openpic_macio.c @@ -70,6 +70,7 @@ static device_method_t openpic_macio_methods[] = { DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), + DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c index 7653347..3449b74 100644 --- a/sys/powerpc/powerpc/intr_machdep.c +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -132,7 +132,7 @@ powerpc_intr_unmask(void *arg) } void -powerpc_register_pic(device_t dev) +powerpc_register_pic(device_t dev, u_int ipi) { pic = dev; diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c index c6a0863..6d8458f 100644 --- a/sys/powerpc/powerpc/openpic.c +++ b/sys/powerpc/powerpc/openpic.c @@ -66,21 +66,23 @@ openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val) } static __inline void -openpic_set_priority(struct openpic_softc *sc, int cpu, int pri) +openpic_set_priority(struct openpic_softc *sc, int pri) { + u_int tpr; uint32_t x; - x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu)); - x &= ~OPENPIC_CPU_PRIORITY_MASK; + tpr = OPENPIC_PCPU_TPR(PCPU_GET(cpuid)); + x = openpic_read(sc, tpr); + x &= ~OPENPIC_TPR_MASK; x |= pri; - openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x); + openpic_write(sc, tpr, x); } int openpic_attach(device_t dev) { struct openpic_softc *sc; - u_int irq; + u_int ipi, irq; u_int32_t x; sc = device_get_softc(dev); @@ -130,11 +132,25 @@ openpic_attach(device_t dev) "Version %s, supports %d CPUs and %d irqs\n", sc->sc_version, sc->sc_ncpu, sc->sc_nirq); - /* disable all interrupts */ - for (irq = 0; irq < sc->sc_nirq; irq++) - openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); + /* Reset and disable all interrupts. */ + for (irq = 0; irq < sc->sc_nirq; irq++) { + x = irq; /* irq == vector. */ + x |= OPENPIC_IMASK; + x |= OPENPIC_POLARITY_POSITIVE; + x |= OPENPIC_SENSE_LEVEL; + x |= 8 << OPENPIC_PRIORITY_SHIFT; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + } - openpic_set_priority(sc, 0, 15); + /* Reset and disable all IPIs. */ + for (ipi = 0; ipi < 4; ipi++) { + x = sc->sc_nirq + ipi; + x |= OPENPIC_IMASK; + x |= 15 << OPENPIC_PRIORITY_SHIFT; + openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x); + } + + openpic_set_priority(sc, 15); /* we don't need 8259 passthrough mode */ x = openpic_read(sc, OPENPIC_CONFIG); @@ -145,27 +161,17 @@ openpic_attach(device_t dev) for (irq = 0; irq < sc->sc_nirq; irq++) openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0); - for (irq = 0; irq < sc->sc_nirq; irq++) { - x = irq; /* irq == vector. */ - x |= OPENPIC_IMASK; - x |= OPENPIC_POLARITY_POSITIVE; - x |= OPENPIC_SENSE_LEVEL; - x |= 8 << OPENPIC_PRIORITY_SHIFT; - openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); - } - - /* XXX IPI */ /* XXX set spurious intr vector */ - openpic_set_priority(sc, 0, 0); + openpic_set_priority(sc, 0); /* clear all pending interrupts */ for (irq = 0; irq < sc->sc_nirq; irq++) { - (void)openpic_read(sc, OPENPIC_IACK(0)); - openpic_write(sc, OPENPIC_EOI(0), 0); + (void)openpic_read(sc, OPENPIC_PCPU_IACK(PCPU_GET(cpuid))); + openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0); } - powerpc_register_pic(dev); + powerpc_register_pic(dev, sc->sc_nirq); return (0); } @@ -182,7 +188,7 @@ openpic_dispatch(device_t dev, struct trapframe *tf) sc = device_get_softc(dev); while (1) { - vector = openpic_read(sc, OPENPIC_IACK(0)); + vector = openpic_read(sc, OPENPIC_PCPU_IACK(PCPU_GET(cpuid))); vector &= OPENPIC_VECTOR_MASK; if (vector == 255) break; @@ -197,10 +203,17 @@ openpic_enable(device_t dev, u_int irq, u_int vector) uint32_t x; sc = device_get_softc(dev); - x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); - x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); - x |= vector; - openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + if (irq < sc->sc_nirq) { + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); + x |= vector; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + } else { + x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); + x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); + x |= vector; + openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); + } } void @@ -209,7 +222,17 @@ openpic_eoi(device_t dev, u_int irq __unused) struct openpic_softc *sc; sc = device_get_softc(dev); - openpic_write(sc, OPENPIC_EOI(0), 0); + openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0); +} + +void +openpic_ipi(device_t dev, u_int cpu) +{ + struct openpic_softc *sc; + + sc = device_get_softc(dev); + openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0), + 1u << cpu); } void @@ -219,10 +242,16 @@ openpic_mask(device_t dev, u_int irq) uint32_t x; sc = device_get_softc(dev); - x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); - x |= OPENPIC_IMASK; - openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); - openpic_write(sc, OPENPIC_EOI(0), 0); + if (irq < sc->sc_nirq) { + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x |= OPENPIC_IMASK; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + } else { + x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); + x |= OPENPIC_IMASK; + openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); + } + openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0); } void @@ -232,7 +261,13 @@ openpic_unmask(device_t dev, u_int irq) uint32_t x; sc = device_get_softc(dev); - x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); - x &= ~OPENPIC_IMASK; - openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + if (irq < sc->sc_nirq) { + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x &= ~OPENPIC_IMASK; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + } else { + x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); + x &= ~OPENPIC_IMASK; + openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); + } } diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m index 9db9c16..a569331 100644 --- a/sys/powerpc/powerpc/pic_if.m +++ b/sys/powerpc/powerpc/pic_if.m @@ -48,6 +48,11 @@ METHOD void eoi { u_int irq; }; +METHOD void ipi { + device_t dev; + u_int cpu; +}; + METHOD void mask { device_t dev; u_int irq; diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c index a3a69d3..96d5d4d 100644 --- a/sys/powerpc/psim/openpic_iobus.c +++ b/sys/powerpc/psim/openpic_iobus.c @@ -74,6 +74,7 @@ static device_method_t openpic_iobus_methods[] = { DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), + DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), |