Add support for the BUS_CONFIG_INTR() method to the platform and to
openpic(4). Make use of it in ocpbus(4). On the MPC85xxCDS, IRQ0:4 are active-low.
This commit is contained in:
parent
cbff2d5782
commit
df20e17353
@ -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_ */
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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 = intr_lookup(irq);
|
||||
if (i == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
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 = 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)
|
||||
{
|
||||
|
@ -180,6 +180,26 @@ openpic_attach(device_t dev)
|
||||
* PIC I/F methods
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user