summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2013-10-24 15:37:32 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2013-10-24 15:37:32 +0000
commit55228c4ed428f052b8aea65e57455a06b1e0e8ef (patch)
tree705fa458ac7137cc1f70a273a36d290ad5333965
parent9d4ffc738979d501190db026f145b32d5da827c7 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/powerpc/mpc85xx/atpic.c37
-rw-r--r--sys/powerpc/ofw/openpic_ofw.c36
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c46
-rw-r--r--sys/powerpc/powerpc/nexus.c4
-rw-r--r--sys/powerpc/powerpc/pic_if.m19
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;
OpenPOWER on IntegriCloud