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.
This commit is contained in:
Nathan Whitehorn 2013-10-24 15:37:32 +00:00
parent 6495f64998
commit 544234026d
6 changed files with 133 additions and 10 deletions

View File

@ -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_ */

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
@ -503,6 +513,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)
{

View File

@ -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

View File

@ -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;