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