summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/include/intr_machdep.h1
-rw-r--r--sys/powerpc/include/openpicvar.h1
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c16
-rw-r--r--sys/powerpc/mpc85xx/opic.c1
-rw-r--r--sys/powerpc/powermac/openpic_macio.c1
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c130
-rw-r--r--sys/powerpc/powerpc/openpic.c20
-rw-r--r--sys/powerpc/powerpc/pic_if.m7
-rw-r--r--sys/powerpc/psim/openpic_iobus.c1
9 files changed, 136 insertions, 42 deletions
diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h
index ebab93b39d04..0cadf0ce4669 100644
--- a/sys/powerpc/include/intr_machdep.h
+++ b/sys/powerpc/include/intr_machdep.h
@@ -43,5 +43,6 @@ int powerpc_enable_intr(void);
int powerpc_setup_intr(const char *, u_int, driver_filter_t,
driver_intr_t, void *, enum intr_type, void **);
int powerpc_teardown_intr(void *);
+int powerpc_config_intr(int, enum intr_trigger, enum intr_polarity);
#endif /* _MACHINE_INTR_MACHDEP_H_ */
diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h
index f1db26c3b2d1..403823bc745f 100644
--- a/sys/powerpc/include/openpicvar.h
+++ b/sys/powerpc/include/openpicvar.h
@@ -54,6 +54,7 @@ int openpic_attach(device_t);
/*
* PIC interface.
*/
+void openpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity);
void openpic_dispatch(device_t, struct trapframe *);
void openpic_enable(device_t, u_int, u_int);
void openpic_eoi(device_t, u_int);
diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c
index 9099fa7ce62c..cc6c724dcb0b 100644
--- a/sys/powerpc/mpc85xx/ocpbus.c
+++ b/sys/powerpc/mpc85xx/ocpbus.c
@@ -76,6 +76,8 @@ static int ocpbus_read_ivar(device_t, device_t, int, uintptr_t *);
static int ocpbus_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int ocpbus_teardown_intr(device_t, device_t, struct resource *, void *);
+static int ocpbus_config_intr(device_t, int, enum intr_trigger,
+ enum intr_polarity);
/*
* Bus interface definition
@@ -91,6 +93,7 @@ static device_method_t ocpbus_methods[] = {
DEVMETHOD(bus_read_ivar, ocpbus_read_ivar),
DEVMETHOD(bus_setup_intr, ocpbus_setup_intr),
DEVMETHOD(bus_teardown_intr, ocpbus_teardown_intr),
+ DEVMETHOD(bus_config_intr, ocpbus_config_intr),
DEVMETHOD(bus_get_resource, ocpbus_get_resource),
DEVMETHOD(bus_alloc_resource, ocpbus_alloc_resource),
@@ -279,6 +282,9 @@ ocpbus_attach (device_t dev)
device_printf(dev, "PORDEVSR=%08x, PORDEVSR2=%08x\n",
in32(OCP85XX_PORDEVSR), in32(OCP85XX_PORDEVSR2));
+ for (i = 0; i < 4; i++)
+ powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
+
return (bus_generic_attach(dev));
}
@@ -594,3 +600,13 @@ ocpbus_teardown_intr(device_t dev, device_t child, struct resource *res,
return (powerpc_teardown_intr(cookie));
}
+
+static int
+ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+
+ if (irq < PIC_IRQ_START)
+ return (EINVAL);
+ return (powerpc_config_intr(irq - PIC_IRQ_START, trig, pol));
+}
diff --git a/sys/powerpc/mpc85xx/opic.c b/sys/powerpc/mpc85xx/opic.c
index aff8f3652491..529226a5014e 100644
--- a/sys/powerpc/mpc85xx/opic.c
+++ b/sys/powerpc/mpc85xx/opic.c
@@ -56,6 +56,7 @@ static device_method_t openpic_ocpbus_methods[] = {
DEVMETHOD(device_attach, openpic_attach),
/* PIC interface */
+ DEVMETHOD(pic_config, openpic_config),
DEVMETHOD(pic_dispatch, openpic_dispatch),
DEVMETHOD(pic_enable, openpic_enable),
DEVMETHOD(pic_eoi, openpic_eoi),
diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c
index 7d4a9c8d8dad..49d935a4d459 100644
--- a/sys/powerpc/powermac/openpic_macio.c
+++ b/sys/powerpc/powermac/openpic_macio.c
@@ -67,6 +67,7 @@ static device_method_t openpic_macio_methods[] = {
DEVMETHOD(device_attach, openpic_attach),
/* PIC interface */
+ DEVMETHOD(pic_config, openpic_config),
DEVMETHOD(pic_dispatch, openpic_dispatch),
DEVMETHOD(pic_enable, openpic_enable),
DEVMETHOD(pic_eoi, openpic_eoi),
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index 3449b74aa0a3..2055519c740b 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -89,7 +89,10 @@ MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
struct powerpc_intr {
struct intr_event *event;
long *cntp;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
u_int irq;
+ u_int vector;
};
static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
@@ -98,6 +101,56 @@ static u_int stray_count;
device_t pic;
+static struct powerpc_intr *
+intr_lookup(u_int irq)
+{
+ struct powerpc_intr *i, *iscan;
+ int vector;
+
+ for (vector = 0; vector < nvectors; vector++) {
+ i = powerpc_intrs[vector];
+ if (i != NULL && i->irq == irq)
+ return (i);
+ }
+
+ i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
+ if (i == NULL)
+ return (NULL);
+
+ i->event = NULL;
+ i->cntp = NULL;
+ i->trig = INTR_TRIGGER_CONFORM;
+ i->pol = INTR_POLARITY_CONFORM;
+ i->irq = irq;
+ i->vector = -1;
+
+ /* XXX LOCK */
+
+ for (vector = 0; vector < INTR_VECTORS && vector <= nvectors;
+ vector++) {
+ iscan = powerpc_intrs[vector];
+ if (iscan != NULL && iscan->irq == irq)
+ break;
+ if (iscan == NULL && i->vector == -1)
+ i->vector = vector;
+ iscan = NULL;
+ }
+
+ if (iscan == NULL && i->vector != -1) {
+ powerpc_intrs[i->vector] = i;
+ nvectors++;
+ }
+
+ /* XXX UNLOCK */
+
+ if (iscan != NULL || i->vector == -1) {
+ free(i, M_INTR);
+ i = iscan;
+ }
+
+ return (i);
+}
+
static void
intrcnt_setname(const char *name, int index)
{
@@ -149,7 +202,12 @@ powerpc_enable_intr(void)
if (i == NULL)
continue;
- PIC_ENABLE(pic, i->irq, vector);
+ if (i->trig != INTR_TRIGGER_CONFORM ||
+ i->pol != INTR_POLARITY_CONFORM)
+ PIC_CONFIG(pic, i->irq, i->trig, i->pol);
+
+ if (i->event != NULL)
+ PIC_ENABLE(pic, i->irq, vector);
}
return (0);
@@ -160,64 +218,31 @@ powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
{
struct powerpc_intr *i;
- u_int vector;
int error;
- /* XXX lock */
-
- i = NULL;
- for (vector = 0; vector < nvectors; vector++) {
- i = powerpc_intrs[vector];
- if (i == NULL)
- continue;
- if (i->irq == irq)
- break;
- i = NULL;
- }
-
- if (i == NULL) {
- if (nvectors >= INTR_VECTORS) {
- /* XXX unlock */
- return (ENOENT);
- }
+ i = intr_lookup(irq);
+ if (i == NULL)
+ return (ENOMEM);
- i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
- if (i == NULL) {
- /* XXX unlock */
- return (ENOMEM);
- }
+ if (i->event == NULL) {
error = intr_event_create(&i->event, (void *)irq, 0,
powerpc_intr_unmask,
#ifdef INTR_FILTER
powerpc_intr_eoi, powerpc_intr_mask,
#endif
"irq%u:", irq);
- if (error) {
- /* XXX unlock */
- free(i, M_INTR);
+ if (error)
return (error);
- }
-
- vector = nvectors++;
- powerpc_intrs[vector] = i;
- i->irq = irq;
-
- /* XXX unlock */
-
- i->cntp = &intrcnt[vector];
- intrcnt_setname(i->event->ie_fullname, vector);
+ i->cntp = &intrcnt[i->vector];
if (!cold)
- PIC_ENABLE(pic, i->irq, vector);
- } else {
- /* XXX unlock */
+ PIC_ENABLE(pic, i->irq, i->vector);
}
error = intr_event_add_handler(i->event, name, filter, handler, arg,
intr_priority(flags), flags, cookiep);
- if (!error)
- intrcnt_setname(i->event->ie_fullname, vector);
+ intrcnt_setname(i->event->ie_fullname, i->vector);
return (error);
}
@@ -228,6 +253,27 @@ powerpc_teardown_intr(void *cookie)
return (intr_event_remove_handler(cookie));
}
+int
+powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
+{
+ struct powerpc_intr *i;
+
+ if (trig == INTR_TRIGGER_CONFORM && pol == INTR_POLARITY_CONFORM)
+ return (0);
+
+ i = intr_lookup(irq);
+ if (i == NULL)
+ return (ENOMEM);
+
+ i->trig = trig;
+ i->pol = pol;
+
+ if (!cold)
+ PIC_CONFIG(pic, irq, trig, pol);
+
+ return (0);
+}
+
void
powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
{
diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c
index 6d8458f92276..c778a2495d8f 100644
--- a/sys/powerpc/powerpc/openpic.c
+++ b/sys/powerpc/powerpc/openpic.c
@@ -181,6 +181,26 @@ openpic_attach(device_t dev)
*/
void
+openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+ struct openpic_softc *sc;
+ uint32_t x;
+
+ sc = device_get_softc(dev);
+ x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+ if (pol == INTR_POLARITY_LOW)
+ x &= ~OPENPIC_POLARITY_POSITIVE;
+ else
+ x |= OPENPIC_POLARITY_POSITIVE;
+ if (trig == INTR_TRIGGER_EDGE)
+ x &= ~OPENPIC_SENSE_LEVEL;
+ else
+ x |= OPENPIC_SENSE_LEVEL;
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+}
+
+void
openpic_dispatch(device_t dev, struct trapframe *tf)
{
struct openpic_softc *sc;
diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m
index a569331f99b2..2fc507122340 100644
--- a/sys/powerpc/powerpc/pic_if.m
+++ b/sys/powerpc/powerpc/pic_if.m
@@ -32,6 +32,13 @@
INTERFACE pic;
+METHOD void config {
+ device_t dev;
+ u_int irq;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
+};
+
METHOD void dispatch {
device_t dev;
struct trapframe *tf;
diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c
index 96d5d4d649cc..4710f597a3b6 100644
--- a/sys/powerpc/psim/openpic_iobus.c
+++ b/sys/powerpc/psim/openpic_iobus.c
@@ -71,6 +71,7 @@ static device_method_t openpic_iobus_methods[] = {
DEVMETHOD(device_attach, openpic_attach),
/* PIC interface */
+ DEVMETHOD(pic_config, openpic_config),
DEVMETHOD(pic_dispatch, openpic_dispatch),
DEVMETHOD(pic_enable, openpic_enable),
DEVMETHOD(pic_eoi, openpic_eoi),