Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/loongson-eiointc: Route interrupt parsed from bios table

Interrupt controller eiointc routes interrupts to CPU interface IP0 - IP7.

It is currently hard-coded that eiointc routes interrupts to the CPU
starting from IP1, but it should base that decision on the parent
interrupt, which is provided by ACPI or DTS.

Retrieve the parent's hardware interrupt number and store it in the
descriptor of the eointc instance, so that the routing function can utilize
it for the correct route settings.

[ tglx: Massaged change log ]

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250804081946.1456573-2-maobibo@loongson.cn

authored by

Bibo Mao and committed by
Thomas Gleixner
7fb83eb6 adecf78d

+17 -4
+17 -4
drivers/irqchip/irq-loongson-eiointc.c
··· 68 68 struct fwnode_handle *domain_handle; 69 69 struct irq_domain *eiointc_domain; 70 70 int flags; 71 + irq_hw_number_t parent_hwirq; 71 72 }; 72 73 73 74 static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; ··· 212 211 } 213 212 214 213 for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { 215 - bit = BIT(1 + index); /* Route to IP[1 + index] */ 214 + /* 215 + * Route to interrupt pin, relative offset used here 216 + * Offset 0 means routing to IP0 and so on 217 + * Every 32 vector routing to one interrupt pin 218 + */ 219 + bit = BIT(eiointc_priv[index]->parent_hwirq - INT_HWI0); 216 220 data = bit | (bit << 8) | (bit << 16) | (bit << 24); 217 221 iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); 218 222 } ··· 501 495 502 496 priv->vec_count = VEC_COUNT; 503 497 priv->node = acpi_eiointc->node; 504 - 498 + priv->parent_hwirq = acpi_eiointc->cascade; 505 499 parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); 506 500 507 501 ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); ··· 533 527 static int __init eiointc_of_init(struct device_node *of_node, 534 528 struct device_node *parent) 535 529 { 536 - int parent_irq, ret; 537 530 struct eiointc_priv *priv; 531 + struct irq_data *irq_data; 532 + int parent_irq, ret; 538 533 539 534 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 540 535 if (!priv) ··· 551 544 if (ret < 0) 552 545 goto out_free_priv; 553 546 547 + irq_data = irq_get_irq_data(parent_irq); 548 + if (!irq_data) { 549 + ret = -ENODEV; 550 + goto out_free_priv; 551 + } 552 + 554 553 /* 555 554 * In particular, the number of devices supported by the LS2K0500 556 555 * extended I/O interrupt vector is 128. ··· 565 552 priv->vec_count = 128; 566 553 else 567 554 priv->vec_count = VEC_COUNT; 568 - 555 + priv->parent_hwirq = irqd_to_hwirq(irq_data); 569 556 priv->node = 0; 570 557 priv->domain_handle = of_fwnode_handle(of_node); 571 558