mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 10:11:38 -04:00
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:
committed by
Thomas Gleixner
parent
41bf87bcac
commit
29c10a0af0
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user