summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/powerpc/include/intr_machdep.h4
-rw-r--r--sys/powerpc/include/openpicreg.h71
-rw-r--r--sys/powerpc/include/openpicvar.h1
-rw-r--r--sys/powerpc/powermac/hrowpic.c10
-rw-r--r--sys/powerpc/powermac/openpic_macio.c1
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c2
-rw-r--r--sys/powerpc/powerpc/openpic.c107
-rw-r--r--sys/powerpc/powerpc/pic_if.m5
-rw-r--r--sys/powerpc/psim/openpic_iobus.c1
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),
OpenPOWER on IntegriCloud