Index: sys/arm64/arm64/intr_machdep.c =================================================================== --- sys/arm64/arm64/intr_machdep.c +++ sys/arm64/arm64/intr_machdep.c @@ -81,6 +81,7 @@ enum intr_trigger i_trig; enum intr_polarity i_pol; + int fwcode; /* Code from HW description */ u_int i_hw_irq; /* Physical interrupt number */ u_int i_cntidx; /* Index in intrcnt table */ @@ -170,6 +171,7 @@ intr->i_handlers = 0; intr->i_trig = INTR_TRIGGER_CONFORM; intr->i_pol = INTR_POLARITY_CONFORM; + intr->fwcode = -1; intr->i_cntidx = atomic_fetchadd_int(&intrcntidx, 1); intr->i_cntp = &intrcnt[intr->i_cntidx]; intr->i_hw_irq = hw_irq; @@ -315,6 +317,7 @@ arm_enable_intr(void) { struct arm64_intr_entry *intr; + int error; if (root_pic == NULL) panic("Cannot enable interrupts. No PIC configured"); @@ -343,10 +346,19 @@ PIC_MASK(root_pic, intr->i_hw_irq); } + if (intr->i_trig == INTR_TRIGGER_CONFORM && + intr->i_pol == INTR_POLARITY_CONFORM) { + PIC_TRANSLATE_CODE(root_pic, intr->i_hw_irq, + intr->fwcode, &intr->i_trig, &intr->i_pol); + } if (intr->i_trig != INTR_TRIGGER_CONFORM || intr->i_pol != INTR_POLARITY_CONFORM) { - PIC_CONFIG(root_pic, intr->i_hw_irq, + error = PIC_CONFIG(root_pic, intr->i_hw_irq, intr->i_trig, intr->i_pol); + if (error != 0) + printf("Error: Cannot configure irq %u.\n", + intr->i_hw_irq); + } if (intr->i_handlers > 0) @@ -394,13 +406,19 @@ intr->i_handlers++; if (!cold && (root_pic != NULL) && (intr->i_handlers == 1)) { + if (intr->i_trig == INTR_TRIGGER_CONFORM && + intr->i_pol == INTR_POLARITY_CONFORM) { + PIC_TRANSLATE_CODE(root_pic, hw_irq, + intr->fwcode, &intr->i_trig, &intr->i_pol); + } if (intr->i_trig != INTR_TRIGGER_CONFORM || intr->i_pol != INTR_POLARITY_CONFORM) { - PIC_CONFIG(root_pic, intr->i_hw_irq, intr->i_trig, - intr->i_pol); + error = PIC_CONFIG(root_pic, intr->i_hw_irq, + intr->i_trig, intr->i_pol); } - PIC_UNMASK(root_pic, intr->i_hw_irq); + if (!error) + PIC_UNMASK(root_pic, intr->i_hw_irq); } } @@ -449,6 +467,36 @@ return (rv); } +int +arm_fw_config_intr(u_int hw_irq, int sense_code) +{ + struct arm64_intr_entry *intr; + int rv; + + intr = intr_allocate(hw_irq); + if (intr == NULL) + return (ENOMEM); + + /* + * Store FW code to be able to translate it later if root_pic is not + * currently available + */ + intr->fwcode = sense_code; + + rv = 0; + if (!cold && root_pic != NULL) { + if (intr->i_trig == INTR_TRIGGER_CONFORM && + intr->i_pol == INTR_POLARITY_CONFORM) { + PIC_TRANSLATE_CODE(root_pic, hw_irq, intr->fwcode, + &intr->i_trig, &intr->i_pol); + rv = PIC_CONFIG(root_pic, hw_irq, intr->i_trig, + intr->i_pol); + } + } + + return (rv); +} + void arm_dispatch_intr(u_int hw_irq, struct trapframe *tf) { Index: sys/arm64/arm64/nexus.c =================================================================== --- sys/arm64/arm64/nexus.c +++ sys/arm64/arm64/nexus.c @@ -72,6 +72,13 @@ #include #endif +/* Interpretation of "interrupts" cells in FDT */ +#ifdef FDT +#define FDT_CELL_IRQ_TYPE (0) +#define FDT_CELL_IRQ_NUM (1) +#define FDT_CELL_IRQ_TRIG (2) +#endif + extern struct bus_space memmap_bus; static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); @@ -429,14 +436,20 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - int irq; + int irq, error; - if (icells == 3) { - irq = intr[1]; - if (intr[0] == 0) + if (icells >= 3) { + irq = intr[FDT_CELL_IRQ_NUM]; + if (intr[FDT_CELL_IRQ_TYPE] == 0) irq += 32; /* SPI */ else irq += 16; /* PPI */ + + error = arm_fw_config_intr(irq, intr[FDT_CELL_IRQ_TRIG]); + if (error != 0) + device_printf(dev, "%s: Failed to" + " configure trigger and polarity for IRQ%d" + " (error %d)\n", __func__, irq, error); } else irq = intr[0]; Index: sys/arm64/include/intr.h =================================================================== --- sys/arm64/include/intr.h +++ sys/arm64/include/intr.h @@ -32,6 +32,7 @@ int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity); void intr_irq_handler(struct trapframe *); int intr_irq_remove_handler(device_t, u_int, void *); +int arm_fw_config_intr(u_int hw_irq, int sense_code); void arm_dispatch_intr(u_int, struct trapframe *); int arm_enable_intr(void);