I'm confused about how to figure determine the interrupt source when you get an IRQ or FIQ interrupt. The manual lists 128 IRQ's but how do you determine which one you got in the IRQ_Handler? Is there a register I need to read or something?
Hi @dhague262
Are you talking about the M core program?
The chip uses GICv3 IP, you can refer gic_irq_domain_translate function in the gicv3 driver.
switch (fwspec->param[0]) {
case 0: /* SPI */
*hwirq = fwspec->param[1] + 32;
break;
case 1: /* PPI */
*hwirq = fwspec->param[1] + 16;
break;
case 2: /* ESPI */
*hwirq = fwspec->param[1] + ESPI_BASE_INTID;
break;
case 3: /* EPPI */
*hwirq = fwspec->param[1] + EPPI_BASE_INTID;
break;
case GIC_IRQ_TYPE_LPI: /* LPI */
*hwirq = fwspec->param[1];
break;
case GIC_IRQ_TYPE_PARTITION:
*hwirq = fwspec->param[1];
if (fwspec->param[1] >= 16)
*hwirq += EPPI_BASE_INTID - 16;
else
*hwirq += 16;
break;
default:
return -EINVAL;
}
*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
There will be a software irq corresponding to the hardware irq(hwirq)
struct irq_data {
u32 mask;
unsigned int irq;------------------------>software irq
unsigned long hwirq;---------------------->hardware irq
struct irq_common_data *common;
struct irq_chip *chip;-------------------->chip ops
struct irq_domain *domain;
void *chip_data;
};
The irq like 128 in manual actually is irq offset, if the irq is SPI type, you can see that the gicv3 driver willl calculate the real irq number: 128+32. When the GICV3 driver detect the hardware irq signal, the kernel will find it's struct irq_data and the software irq(struct irq_data->irq).
We will register the software irq number and irq handler in driver using request_threaded_irq in driver. Fill the irq handler to the struct irqaction.
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
Now, we have the hardware irq, software irq and it's handler.
When the interrupt is detected, the GICv3 driver will use generic_handle_irq(irq) to handle the interrupt. For example, if the interrupt is SPI type, the kernel will goto the handle_fasteoi_irq.
In this function, the calltrace of irq handler we define is below, as the struct irq_desc maintain the hwirq, irq and irqaction->handler, the kernel will use hwirq to find the irq and then find the handler.
handle_irq_event
->handle_irq_event_percpu
->__handle_irq_event_percpu
->res = action->handler(irq, action->dev_id)---->the handler we define
Thanks, QMiller! This is good info. But where can I find the gicv3 driver? I'm writing bare-metal code to run under ThreadX so I don't have this driver. I'm guessing its a Linux driver somewhere but I could certainly use it as a reference.
You can refer below files:
1.exception vector: arch/arm64/kernel/entry.S
2.GICv3 driver: drivers/irqchip/irq-gic-v3.c