summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-02-12 18:14:46 +0000
committermarcel <marcel@FreeBSD.org>2008-02-12 18:14:46 +0000
commitab259d0a3365da3cea394ec2b1f50471fad99e97 (patch)
tree0b020d6a62877c2a89a606ad70b55a5d6951fabe
parentd22d4d735788cbfd2d8a91b701bbbf2f3d119055 (diff)
downloadFreeBSD-src-ab259d0a3365da3cea394ec2b1f50471fad99e97.zip
FreeBSD-src-ab259d0a3365da3cea394ec2b1f50471fad99e97.tar.gz
Add PIC support for IPIs. When registering an interrupt handler,
the PIC also informs the platform at which IRQ level it can start assigning IPIs, since this can depend on the number of IRQs supported for external interrupts.
-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