Interrupt controller eiointc routes irq to cpu interface IP0 - IP7, now it is hard-coded that eiointc routes irq to CPU started from IP1. It can be parsed from acpi table, instead hwirq is used for function irq_create_mapping() already, routed interrupt pin must be the same with parent hwirq. Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx> --- drivers/irqchip/irq-loongson-eiointc.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index b1f2080be2be..e9ec63d85ee8 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -42,6 +42,7 @@ struct eiointc_priv { cpumask_t cpuspan_map; struct fwnode_handle *domain_handle; struct irq_domain *eiointc_domain; + int parent_hwirq; }; static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; @@ -159,7 +160,12 @@ static int eiointc_router_init(unsigned int cpu) } for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { - bit = BIT(1 + index); /* Route to IP[1 + index] */ + /* + * Route to interrupt pin, using offset minus INT_HWI0 + * Offset 0 means IP0 and so on + * Every 32 vector routing to one interrupt pin + */ + bit = BIT(eiointc_priv[index]->parent_hwirq - INT_HWI0); data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); } @@ -424,7 +430,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent, priv->vec_count = VEC_COUNT; priv->node = acpi_eiointc->node; - + priv->parent_hwirq = acpi_eiointc->cascade; parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); @@ -458,6 +464,7 @@ static int __init eiointc_of_init(struct device_node *of_node, { int parent_irq, ret; struct eiointc_priv *priv; + struct irq_data *irq_data; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -473,6 +480,12 @@ static int __init eiointc_of_init(struct device_node *of_node, if (ret < 0) goto out_free_priv; + irq_data = irq_get_irq_data(parent_irq); + if (!irq_data) { + ret = -ENODEV; + goto out_free_priv; + } + /* * In particular, the number of devices supported by the LS2K0500 * extended I/O interrupt vector is 128. @@ -484,7 +497,7 @@ static int __init eiointc_of_init(struct device_node *of_node, priv->node = 0; priv->domain_handle = of_node_to_fwnode(of_node); - + priv->parent_hwirq = irqd_to_hwirq(irq_data); ret = eiointc_init(priv, parent_irq, 0); if (ret < 0) goto out_free_priv; -- 2.39.3