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:
parent
e42bbd58d9
commit
0e390441a7
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user