diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2013-10-24 15:37:32 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2013-10-24 15:37:32 +0000 |
commit | 55228c4ed428f052b8aea65e57455a06b1e0e8ef (patch) | |
tree | 705fa458ac7137cc1f70a273a36d290ad5333965 | |
parent | 9d4ffc738979d501190db026f145b32d5da827c7 (diff) | |
download | FreeBSD-src-55228c4ed428f052b8aea65e57455a06b1e0e8ef.zip FreeBSD-src-55228c4ed428f052b8aea65e57455a06b1e0e8ef.tar.gz |
Allow PIC drivers to translate firmware sense codes for themselves. This
is designed to replace the tables in dev/fdt/fdt_ARCH.c, but will not
happen quite yet.
-rw-r--r-- | sys/powerpc/include/intr_machdep.h | 1 | ||||
-rw-r--r-- | sys/powerpc/mpc85xx/atpic.c | 37 | ||||
-rw-r--r-- | sys/powerpc/ofw/openpic_ofw.c | 36 | ||||
-rw-r--r-- | sys/powerpc/powerpc/intr_machdep.c | 46 | ||||
-rw-r--r-- | sys/powerpc/powerpc/nexus.c | 4 | ||||
-rw-r--r-- | sys/powerpc/powerpc/pic_if.m | 19 |
6 files changed, 133 insertions, 10 deletions
diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h index df73992..c2529d5 100644 --- a/sys/powerpc/include/intr_machdep.h +++ b/sys/powerpc/include/intr_machdep.h @@ -56,5 +56,6 @@ int powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t, int powerpc_teardown_intr(void *); int powerpc_bind_intr(u_int irq, u_char cpu); int powerpc_config_intr(int, enum intr_trigger, enum intr_polarity); +int powerpc_fw_config_intr(int irq, int sense_code); #endif /* _MACHINE_INTR_MACHDEP_H_ */ diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c index a792e54..ef7ab88 100644 --- a/sys/powerpc/mpc85xx/atpic.c +++ b/sys/powerpc/mpc85xx/atpic.c @@ -79,6 +79,9 @@ static void atpic_ipi(device_t, u_int); static void atpic_mask(device_t, u_int); static void atpic_unmask(device_t, u_int); +static void atpic_ofw_translate_code(device_t, u_int irq, int code, + enum intr_trigger *trig, enum intr_polarity *pol); + static device_method_t atpic_isa_methods[] = { /* Device interface */ DEVMETHOD(device_identify, atpic_isa_identify), @@ -94,6 +97,8 @@ static device_method_t atpic_isa_methods[] = { DEVMETHOD(pic_mask, atpic_mask), DEVMETHOD(pic_unmask, atpic_unmask), + DEVMETHOD(pic_translate_code, atpic_ofw_translate_code), + { 0, 0 }, }; @@ -325,3 +330,35 @@ atpic_unmask(device_t dev, u_int irq) atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]); } } + +static void +atpic_ofw_translate_code(device_t dev, u_int irq, int code, + enum intr_trigger *trig, enum intr_polarity *pol) +{ + switch (code) { + case 0: + /* Active L level */ + *trig = INTR_TRIGGER_LEVEL; + *pol = INTR_POLARITY_LOW; + break; + case 1: + /* Active H level */ + *trig = INTR_TRIGGER_LEVEL; + *pol = INTR_POLARITY_HIGH; + break; + case 2: + /* H to L edge */ + *trig = INTR_TRIGGER_EDGE; + *pol = INTR_POLARITY_LOW; + break; + case 3: + /* L to H edge */ + *trig = INTR_TRIGGER_EDGE; + *pol = INTR_POLARITY_HIGH; + break; + default: + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + } +} + diff --git a/sys/powerpc/ofw/openpic_ofw.c b/sys/powerpc/ofw/openpic_ofw.c index 60d8345..0e85dda 100644 --- a/sys/powerpc/ofw/openpic_ofw.c +++ b/sys/powerpc/ofw/openpic_ofw.c @@ -61,6 +61,9 @@ __FBSDID("$FreeBSD$"); static int openpic_ofw_probe(device_t); static int openpic_ofw_attach(device_t); +static void openpic_ofw_translate_code(device_t, u_int irq, int code, + enum intr_trigger *trig, enum intr_polarity *pol); + static device_method_t openpic_ofw_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_ofw_probe), @@ -76,6 +79,8 @@ static device_method_t openpic_ofw_methods[] = { DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), + DEVMETHOD(pic_translate_code, openpic_ofw_translate_code), + DEVMETHOD_END }; @@ -127,3 +132,34 @@ openpic_ofw_attach(device_t dev) return (openpic_common_attach(dev, xref)); } +static void +openpic_ofw_translate_code(device_t dev, u_int irq, int code, + enum intr_trigger *trig, enum intr_polarity *pol) +{ + switch (code) { + case 0: + /* L to H edge */ + *trig = INTR_TRIGGER_EDGE; + *pol = INTR_POLARITY_HIGH; + break; + case 1: + /* Active L level */ + *trig = INTR_TRIGGER_LEVEL; + *pol = INTR_POLARITY_LOW; + break; + case 2: + /* Active H level */ + *trig = INTR_TRIGGER_LEVEL; + *pol = INTR_POLARITY_HIGH; + break; + case 3: + /* H to L edge */ + *trig = INTR_TRIGGER_EDGE; + *pol = INTR_POLARITY_LOW; + break; + default: + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + } +} + diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c index 539d3f6..0b13191 100644 --- a/sys/powerpc/powerpc/intr_machdep.c +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -102,6 +102,7 @@ struct powerpc_intr { cpuset_t cpu; enum intr_trigger trig; enum intr_polarity pol; + int fwcode; }; struct pic { @@ -427,6 +428,9 @@ powerpc_enable_intr(void) if (error) continue; + if (i->trig == -1) + PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, + &i->trig, &i->pol); if (i->trig != INTR_TRIGGER_CONFORM || i->pol != INTR_POLARITY_CONFORM) PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); @@ -469,15 +473,21 @@ powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, if (!cold) { error = powerpc_map_irq(i); - if (!error && (i->trig != INTR_TRIGGER_CONFORM || - i->pol != INTR_POLARITY_CONFORM)) - PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); + if (!error) { + if (i->trig == -1) + PIC_TRANSLATE_CODE(i->pic, i->intline, + i->fwcode, &i->trig, &i->pol); + + if (i->trig != INTR_TRIGGER_CONFORM || + i->pol != INTR_POLARITY_CONFORM) + PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); - if (!error && i->pic == root_pic) - PIC_BIND(i->pic, i->intline, i->cpu); + if (i->pic == root_pic) + PIC_BIND(i->pic, i->intline, i->cpu); - if (!error && enable) - PIC_ENABLE(i->pic, i->intline, i->vector); + if (enable) + PIC_ENABLE(i->pic, i->intline, i->vector); + } } return (error); } @@ -504,6 +514,28 @@ powerpc_bind_intr(u_int irq, u_char cpu) #endif int +powerpc_fw_config_intr(int irq, int sense_code) +{ + struct powerpc_intr *i; + + i = intr_lookup(irq); + if (i == NULL) + return (ENOMEM); + + i->trig = -1; + i->pol = INTR_POLARITY_CONFORM; + i->fwcode = sense_code; + + if (!cold && i->pic != NULL) { + PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, &i->trig, + &i->pol); + PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); + } + + return (0); +} + +int powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol) { struct powerpc_intr *i; diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c index 493bd9a..f7100f1 100644 --- a/sys/powerpc/powerpc/nexus.c +++ b/sys/powerpc/powerpc/nexus.c @@ -166,9 +166,7 @@ static int nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense) { - return (bus_generic_config_intr(child, irq, (sense & 1) ? - INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE, - INTR_POLARITY_LOW)); + return (powerpc_fw_config_intr(irq, sense)); } static int diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m index e429d31..f42c31a 100644 --- a/sys/powerpc/powerpc/pic_if.m +++ b/sys/powerpc/powerpc/pic_if.m @@ -33,12 +33,31 @@ INTERFACE pic; +CODE { + static pic_translate_code_t pic_translate_code_default; + + static void pic_translate_code_default(device_t dev, u_int irq, + int code, enum intr_trigger *trig, enum intr_polarity *pol) + { + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + } +}; + METHOD void bind { device_t dev; u_int irq; cpuset_t cpumask; }; +METHOD void translate_code { + device_t dev; + u_int irq; + int code; + enum intr_trigger *trig; + enum intr_polarity *pol; +} DEFAULT pic_translate_code_default; + METHOD void config { device_t dev; u_int irq; |