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
This commit is contained in:
Icenowy Zheng
2026-03-21 17:20:30 +08:00
committed by Thomas Gleixner
parent 41bf87bcac
commit 29c10a0af0

View File

@@ -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 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
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;
}