Add a common routine for parsing FDT data describing an ARM GIC interrupt.

In the fdt data we've written for ourselves, the interrupt properties
for GIC interrupts have just been a bare interrupt number.  In standard
data that conforms to the published bindings, GIC interrupt properties
contain 3-tuples that describe the interrupt as shared vs private, the
interrupt number within the shared/private address space, and configuration
info such as level vs edge triggered.

The new gic_decode_fdt() function parses both types of data, based on the
#interrupt-cells property.  Previously, each platform implemented a decode
routine and put a pointer to it into fdt_pic_table.  Now they can just
list this function in their table instead if they use arm/gic.c.
This commit is contained in:
Ian Lepore 2014-09-14 21:21:03 +00:00
parent e42bbd58d9
commit 0e390441a7
2 changed files with 47 additions and 0 deletions

View File

@ -185,6 +185,51 @@ gic_init_secondary(void)
gic_d_write_4(GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
}
int
gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
int *trig, int *pol)
{
static u_int num_intr_cells;
if (num_intr_cells == 0) {
if (OF_searchencprop(OF_node_from_xref(iparent),
"#interrupt-cells", &num_intr_cells,
sizeof(num_intr_cells)) == -1) {
num_intr_cells = 1;
}
}
if (num_intr_cells == 1) {
*interrupt = fdt32_to_cpu(intr[0]);
*trig = INTR_TRIGGER_CONFORM;
*pol = INTR_POLARITY_CONFORM;
} else {
if (intr[0] == 0)
*interrupt = fdt32_to_cpu(intr[1]) + 32;
else
*interrupt = fdt32_to_cpu(intr[1]);
/*
* In intr[2], bits[3:0] are trigger type and level flags.
* 1 = low-to-high edge triggered
* 2 = high-to-low edge triggered
* 4 = active high level-sensitive
* 8 = active low level-sensitive
* The hardware only supports active-high-level or rising-edge.
*/
if (intr[2] & 0x0a) {
printf("unsupported trigger/polarity configuration "
"0x%2x\n", intr[2] & 0x0f);
return (ENOTSUP);
}
*pol = INTR_POLARITY_CONFORM;
if (intr[2] & 0x01)
*trig = INTR_TRIGGER_EDGE;
else
*trig = INTR_TRIGGER_LEVEL;
}
return (0);
}
static int
arm_gic_attach(device_t dev)
{

View File

@ -82,5 +82,7 @@ extern int (*arm_config_irq)(int irq, enum intr_trigger trig,
void arm_irq_memory_barrier(uintptr_t);
void gic_init_secondary(void);
int gic_decode_fdt(uint32_t iparentnode, uint32_t *intrcells, int *interrupt,
int *trig, int *pol);
#endif /* _MACHINE_INTR_H */