diff options
| author | Icenowy Zheng <zhengxingda@iscas.ac.cn> | 2026-03-21 12:20:30 +0300 |
|---|---|---|
| committer | Thomas Gleixner <tglx@kernel.org> | 2026-03-26 18:15:03 +0300 |
| commit | 29c10a0af04e9b3eb7b06e72e9f75fccca45205e (patch) | |
| tree | 3975d7a8bc95cf97c6a03650ddc9f7644fd2c3b1 | |
| parent | 41bf87bcac02cd788d4325415d4b2e31bf2a694d (diff) | |
| download | linux-29c10a0af04e9b3eb7b06e72e9f75fccca45205e.tar.xz | |
irqchip/loongson-pch-lpc: Extract non-ACPI-related code from ACPI init
A lot of code can be shared between the existing ACPI init flow with the
upcoming OF init flow.
Extract it into a dedicated function.
The re-ordering of parent interrupt allocation requires the architecture
code to reserve legacy interrupts from the dynamic allocation by overriding
arch_dynirq_lower_bound(), otherwise the parent of LPC irqchip will be
allocated in the intended static range of LPC interrupts, which leads to
allocation failure of LPC interrupts.
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Huacai Chen <chenhuacai@loongson.cn>
Link: https://patch.msgid.link/20260321092032.3502701-5-zhengxingda@iscas.ac.cn
| -rw-r--r-- | drivers/irqchip/irq-loongson-pch-lpc.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c index 3ad46ec94e3c..2bb6659e9a93 100644 --- a/drivers/irqchip/irq-loongson-pch-lpc.c +++ b/drivers/irqchip/irq-loongson-pch-lpc.c @@ -175,13 +175,10 @@ static struct syscore pch_lpc_syscore = { .ops = &pch_lpc_syscore_ops, }; -int __init pch_lpc_acpi_init(struct irq_domain *parent, - struct acpi_madt_lpc_pic *acpi_pchlpc) +static int __init pch_lpc_init(phys_addr_t addr, unsigned long size, + struct fwnode_handle *irq_handle, int parent_irq) { - int parent_irq; struct pch_lpc *priv; - struct irq_fwspec fwspec; - struct fwnode_handle *irq_handle; priv = kzalloc_obj(*priv); if (!priv) @@ -189,7 +186,7 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, raw_spin_lock_init(&priv->lpc_lock); - priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size); + priv->base = ioremap(addr, size); if (!priv->base) goto free_priv; @@ -198,12 +195,6 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, goto iounmap_base; } - irq_handle = irq_domain_alloc_named_fwnode("lpcintc"); - if (!irq_handle) { - pr_err("Unable to allocate domain handle\n"); - goto iounmap_base; - } - /* * The LPC interrupt controller is a legacy i8259-compatible device, * which requires a static 1:1 mapping for IRQs 0-15. @@ -213,15 +204,10 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, &pch_lpc_domain_ops, priv); if (!priv->lpc_domain) { pr_err("Failed to create IRQ domain\n"); - goto free_irq_handle; + goto iounmap_base; } pch_lpc_reset(priv); - fwspec.fwnode = parent->fwnode; - fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; - fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; - fwspec.param_count = 2; - parent_irq = irq_create_fwspec_mapping(&fwspec); irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv); pch_lpc_priv = priv; @@ -230,8 +216,6 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, return 0; -free_irq_handle: - irq_domain_free_fwnode(irq_handle); iounmap_base: iounmap(priv->base); free_priv: @@ -239,3 +223,36 @@ free_priv: return -ENOMEM; } + +int __init pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc) +{ + struct fwnode_handle *irq_handle; + struct irq_fwspec fwspec; + int parent_irq, ret; + + irq_handle = irq_domain_alloc_named_fwnode("lpcintc"); + if (!irq_handle) { + pr_err("Unable to allocate domain handle\n"); + return -ENOMEM; + } + + fwspec.fwnode = parent->fwnode; + fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; + fwspec.param_count = 2; + parent_irq = irq_create_fwspec_mapping(&fwspec); + if (parent_irq <= 0) { + pr_err("Unable to map LPC parent interrupt\n"); + irq_domain_free_fwnode(irq_handle); + return -ENOMEM; + } + + ret = pch_lpc_init(acpi_pchlpc->address, acpi_pchlpc->size, irq_handle, parent_irq); + if (ret) { + irq_dispose_mapping(parent_irq); + irq_domain_free_fwnode(irq_handle); + return ret; + } + + return 0; +} |
