drivers/irqchip/irq-loongson-eiointc.c | 119 ++++++++++++++++++------- 1 file changed, 85 insertions(+), 34 deletions(-)
Add DT support for EIOINTC irqchip, which is needed for the Loongson-2K
series, e.g. Loongson-2K500 soc.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/irqchip/irq-loongson-eiointc.c | 119 ++++++++++++++++++-------
1 file changed, 85 insertions(+), 34 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
index d15fd38c1756..d5e1ee6aada6 100644
--- a/drivers/irqchip/irq-loongson-eiointc.c
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -39,6 +39,7 @@ static int nr_pics;
struct eiointc_priv {
u32 node;
+ u32 vec_count;
nodemask_t node_map;
cpumask_t cpuspan_map;
struct fwnode_handle *domain_handle;
@@ -156,18 +157,19 @@ static int eiointc_router_init(unsigned int cpu)
if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) {
eiointc_enable();
- for (i = 0; i < VEC_COUNT / 32; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) {
+ pr_info("");
data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2)));
iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4);
}
- for (i = 0; i < VEC_COUNT / 32 / 4; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) {
bit = BIT(1 + index); /* Route to IP[1 + index] */
data = bit | (bit << 8) | (bit << 16) | (bit << 24);
iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4);
}
- for (i = 0; i < VEC_COUNT / 4; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) {
/* Route to Node-0 Core-0 */
if (index == 0)
bit = BIT(cpu_logical_map(0));
@@ -178,7 +180,7 @@ static int eiointc_router_init(unsigned int cpu)
iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4);
}
- for (i = 0; i < VEC_COUNT / 32; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) {
data = 0xffffffff;
iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4);
iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4);
@@ -198,7 +200,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc)
chained_irq_enter(chip, desc);
- for (i = 0; i < VEC_REG_COUNT; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) {
pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3));
iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3));
while (pending) {
@@ -316,7 +318,7 @@ static void eiointc_resume(void)
eiointc_router_init(0);
for (i = 0; i < nr_pics; i++) {
- for (j = 0; j < VEC_COUNT; j++) {
+ for (j = 0; j < eiointc_priv[i]->vec_count; j++) {
desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j);
if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) {
raw_spin_lock(&desc->lock);
@@ -373,11 +375,44 @@ static int __init acpi_cascade_irqdomain_init(void)
return 0;
}
+static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq,
+ u64 node_map)
+{
+ int i;
+
+ node_map = node_map ? node_map : -1ULL;
+ for_each_possible_cpu(i) {
+ if (node_map & (1ULL << (cpu_to_eio_node(i)))) {
+ node_set(cpu_to_eio_node(i), priv->node_map);
+ cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map,
+ cpumask_of(i));
+ }
+ }
+
+ priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle,
+ priv->vec_count,
+ &eiointc_domain_ops,
+ priv);
+ if (!priv->eiointc_domain) {
+ pr_err("loongson-extioi: cannot add IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ eiointc_priv[nr_pics++] = priv;
+ eiointc_router_init(0);
+ irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
+ register_syscore_ops(&eiointc_syscore_ops);
+ cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
+ "irqchip/loongarch/intc:starting",
+ eiointc_router_init, NULL);
+
+ return 0;
+}
+
int __init eiointc_acpi_init(struct irq_domain *parent,
struct acpi_madt_eio_pic *acpi_eiointc)
{
- int i, ret, parent_irq;
- unsigned long node_map;
+ int parent_irq, ret;
struct eiointc_priv *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -391,39 +426,20 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
goto out_free_priv;
}
+ priv->vec_count = VEC_COUNT;
priv->node = acpi_eiointc->node;
- node_map = acpi_eiointc->node_map ? : -1ULL;
-
- for_each_possible_cpu(i) {
- if (node_map & (1ULL << cpu_to_eio_node(i))) {
- node_set(cpu_to_eio_node(i), priv->node_map);
- cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i));
- }
- }
-
- /* Setup IRQ domain */
- priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT,
- &eiointc_domain_ops, priv);
- if (!priv->eiointc_domain) {
- pr_err("loongson-eiointc: cannot add IRQ domain\n");
- goto out_free_handle;
- }
-
- eiointc_priv[nr_pics++] = priv;
-
- eiointc_router_init(0);
-
parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
- irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
- register_syscore_ops(&eiointc_syscore_ops);
- cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
- "irqchip/loongarch/intc:starting",
- eiointc_router_init, NULL);
+ ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map);
+ if (ret < 0)
+ goto out_free_handle;
acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group);
acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group);
+
ret = acpi_cascade_irqdomain_init();
+ if (ret < 0)
+ goto out_free_handle;
return ret;
@@ -435,3 +451,39 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
return -ENOMEM;
}
+
+static int __init eiointc_of_init(struct device_node *of_node,
+ struct device_node *parent)
+{
+ int parent_irq, ret;
+ struct eiointc_priv *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ parent_irq = of_irq_get_byname(of_node, "cascade");
+ if (parent_irq <= 0) {
+ ret = -ENODEV;
+ goto out_free_priv;
+ }
+
+ ret = of_property_read_u32(of_node, "vec_count", &priv->vec_count);
+ if (ret < 0)
+ goto out_free_priv;
+
+ priv->node = 0;
+ priv->domain_handle = of_node_to_fwnode(of_node);
+
+ ret = eiointc_init(priv, parent_irq, 0);
+ if (ret < 0)
+ goto out_free_priv;
+
+ return 0;
+
+out_free_priv:
+ kfree(priv);
+ return ret;
+}
+
+IRQCHIP_DECLARE(loongson_eiointc, "loongson,eiointc", eiointc_of_init);
--
2.39.0
On Sat, 11 Feb 2023 02:41:56 +0000, Binbin Zhou <zhoubinbin@loongson.cn> wrote: > > Add DT support for EIOINTC irqchip, which is needed for the Loongson-2K > series, e.g. Loongson-2K500 soc. Where is the binding? I'm pretty sure other drivers need updating. Where are they? M. -- Without deviation from the norm, progress is not possible.
On Sun, Feb 12, 2023 at 7:49 PM Marc Zyngier <maz@kernel.org> wrote: > > On Sat, 11 Feb 2023 02:41:56 +0000, > Binbin Zhou <zhoubinbin@loongson.cn> wrote: > > > > Add DT support for EIOINTC irqchip, which is needed for the Loongson-2K > > series, e.g. Loongson-2K500 soc. > > Where is the binding? I'm pretty sure other drivers need updating. > Where are they? Hi Marc: I will add the binding file in my next version patchset. Thanks. Binbin > > M. > > -- > Without deviation from the norm, progress is not possible. >
Hi, Binbin, On Sat, Feb 11, 2023 at 10:41 AM Binbin Zhou <zhoubinbin@loongson.cn> wrote: > > Add DT support for EIOINTC irqchip, which is needed for the Loongson-2K > series, e.g. Loongson-2K500 soc. Use SOC instead of soc. > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> > --- > drivers/irqchip/irq-loongson-eiointc.c | 119 ++++++++++++++++++------- > 1 file changed, 85 insertions(+), 34 deletions(-) > > diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c > index d15fd38c1756..d5e1ee6aada6 100644 > --- a/drivers/irqchip/irq-loongson-eiointc.c > +++ b/drivers/irqchip/irq-loongson-eiointc.c > @@ -39,6 +39,7 @@ static int nr_pics; > > struct eiointc_priv { > u32 node; > + u32 vec_count; > nodemask_t node_map; > cpumask_t cpuspan_map; > struct fwnode_handle *domain_handle; > @@ -156,18 +157,19 @@ static int eiointc_router_init(unsigned int cpu) > if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { > eiointc_enable(); > > - for (i = 0; i < VEC_COUNT / 32; i++) { > + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { > + pr_info(""); Why print an empty string? Others look good to me. Huacai > data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2))); > iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4); > } > > - for (i = 0; i < VEC_COUNT / 32 / 4; i++) { > + for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { > bit = BIT(1 + index); /* Route to IP[1 + index] */ > data = bit | (bit << 8) | (bit << 16) | (bit << 24); > iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); > } > > - for (i = 0; i < VEC_COUNT / 4; i++) { > + for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) { > /* Route to Node-0 Core-0 */ > if (index == 0) > bit = BIT(cpu_logical_map(0)); > @@ -178,7 +180,7 @@ static int eiointc_router_init(unsigned int cpu) > iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); > } > > - for (i = 0; i < VEC_COUNT / 32; i++) { > + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { > data = 0xffffffff; > iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); > iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); > @@ -198,7 +200,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc) > > chained_irq_enter(chip, desc); > > - for (i = 0; i < VEC_REG_COUNT; i++) { > + for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) { > pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3)); > iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3)); > while (pending) { > @@ -316,7 +318,7 @@ static void eiointc_resume(void) > eiointc_router_init(0); > > for (i = 0; i < nr_pics; i++) { > - for (j = 0; j < VEC_COUNT; j++) { > + for (j = 0; j < eiointc_priv[i]->vec_count; j++) { > desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j); > if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) { > raw_spin_lock(&desc->lock); > @@ -373,11 +375,44 @@ static int __init acpi_cascade_irqdomain_init(void) > return 0; > } > > +static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, > + u64 node_map) > +{ > + int i; > + > + node_map = node_map ? node_map : -1ULL; > + for_each_possible_cpu(i) { > + if (node_map & (1ULL << (cpu_to_eio_node(i)))) { > + node_set(cpu_to_eio_node(i), priv->node_map); > + cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, > + cpumask_of(i)); > + } > + } > + > + priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, > + priv->vec_count, > + &eiointc_domain_ops, > + priv); > + if (!priv->eiointc_domain) { > + pr_err("loongson-extioi: cannot add IRQ domain\n"); > + return -ENOMEM; > + } > + > + eiointc_priv[nr_pics++] = priv; > + eiointc_router_init(0); > + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); > + register_syscore_ops(&eiointc_syscore_ops); > + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, > + "irqchip/loongarch/intc:starting", > + eiointc_router_init, NULL); > + > + return 0; > +} > + > int __init eiointc_acpi_init(struct irq_domain *parent, > struct acpi_madt_eio_pic *acpi_eiointc) > { > - int i, ret, parent_irq; > - unsigned long node_map; > + int parent_irq, ret; > struct eiointc_priv *priv; > > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > @@ -391,39 +426,20 @@ int __init eiointc_acpi_init(struct irq_domain *parent, > goto out_free_priv; > } > > + priv->vec_count = VEC_COUNT; > priv->node = acpi_eiointc->node; > - node_map = acpi_eiointc->node_map ? : -1ULL; > - > - for_each_possible_cpu(i) { > - if (node_map & (1ULL << cpu_to_eio_node(i))) { > - node_set(cpu_to_eio_node(i), priv->node_map); > - cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i)); > - } > - } > - > - /* Setup IRQ domain */ > - priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT, > - &eiointc_domain_ops, priv); > - if (!priv->eiointc_domain) { > - pr_err("loongson-eiointc: cannot add IRQ domain\n"); > - goto out_free_handle; > - } > - > - eiointc_priv[nr_pics++] = priv; > - > - eiointc_router_init(0); > - > parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); > - irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); > > - register_syscore_ops(&eiointc_syscore_ops); > - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, > - "irqchip/loongarch/intc:starting", > - eiointc_router_init, NULL); > + ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); > + if (ret < 0) > + goto out_free_handle; > > acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); > acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); > + > ret = acpi_cascade_irqdomain_init(); > + if (ret < 0) > + goto out_free_handle; > > return ret; > > @@ -435,3 +451,39 @@ int __init eiointc_acpi_init(struct irq_domain *parent, > > return -ENOMEM; > } > + > +static int __init eiointc_of_init(struct device_node *of_node, > + struct device_node *parent) > +{ > + int parent_irq, ret; > + struct eiointc_priv *priv; > + > + priv = kzalloc(sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + parent_irq = of_irq_get_byname(of_node, "cascade"); > + if (parent_irq <= 0) { > + ret = -ENODEV; > + goto out_free_priv; > + } > + > + ret = of_property_read_u32(of_node, "vec_count", &priv->vec_count); > + if (ret < 0) > + goto out_free_priv; > + > + priv->node = 0; > + priv->domain_handle = of_node_to_fwnode(of_node); > + > + ret = eiointc_init(priv, parent_irq, 0); > + if (ret < 0) > + goto out_free_priv; > + > + return 0; > + > +out_free_priv: > + kfree(priv); > + return ret; > +} > + > +IRQCHIP_DECLARE(loongson_eiointc, "loongson,eiointc", eiointc_of_init); > -- > 2.39.0 > >
On Sun, Feb 12, 2023 at 9:53 AM Huacai Chen <chenhuacai@kernel.org> wrote: > > Hi, Binbin, > > On Sat, Feb 11, 2023 at 10:41 AM Binbin Zhou <zhoubinbin@loongson.cn> wrote: > > > > Add DT support for EIOINTC irqchip, which is needed for the Loongson-2K > > series, e.g. Loongson-2K500 soc. > Use SOC instead of soc. > > > > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> > > --- > > drivers/irqchip/irq-loongson-eiointc.c | 119 ++++++++++++++++++------- > > 1 file changed, 85 insertions(+), 34 deletions(-) > > > > diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c > > index d15fd38c1756..d5e1ee6aada6 100644 > > --- a/drivers/irqchip/irq-loongson-eiointc.c > > +++ b/drivers/irqchip/irq-loongson-eiointc.c > > @@ -39,6 +39,7 @@ static int nr_pics; > > > > struct eiointc_priv { > > u32 node; > > + u32 vec_count; > > nodemask_t node_map; > > cpumask_t cpuspan_map; > > struct fwnode_handle *domain_handle; > > @@ -156,18 +157,19 @@ static int eiointc_router_init(unsigned int cpu) > > if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { > > eiointc_enable(); > > > > - for (i = 0; i < VEC_COUNT / 32; i++) { > > + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { > > + pr_info(""); > Why print an empty string? > Sorry, I forgot to remove the debug message. I will fix it. Thanks. Binbin > Others look good to me. > > Huacai > > data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2))); > > iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4); > > } > > > > - for (i = 0; i < VEC_COUNT / 32 / 4; i++) { > > + for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { > > bit = BIT(1 + index); /* Route to IP[1 + index] */ > > data = bit | (bit << 8) | (bit << 16) | (bit << 24); > > iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); > > } > > > > - for (i = 0; i < VEC_COUNT / 4; i++) { > > + for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) { > > /* Route to Node-0 Core-0 */ > > if (index == 0) > > bit = BIT(cpu_logical_map(0)); > > @@ -178,7 +180,7 @@ static int eiointc_router_init(unsigned int cpu) > > iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); > > } > > > > - for (i = 0; i < VEC_COUNT / 32; i++) { > > + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { > > data = 0xffffffff; > > iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); > > iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); > > @@ -198,7 +200,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc) > > > > chained_irq_enter(chip, desc); > > > > - for (i = 0; i < VEC_REG_COUNT; i++) { > > + for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) { > > pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3)); > > iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3)); > > while (pending) { > > @@ -316,7 +318,7 @@ static void eiointc_resume(void) > > eiointc_router_init(0); > > > > for (i = 0; i < nr_pics; i++) { > > - for (j = 0; j < VEC_COUNT; j++) { > > + for (j = 0; j < eiointc_priv[i]->vec_count; j++) { > > desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j); > > if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) { > > raw_spin_lock(&desc->lock); > > @@ -373,11 +375,44 @@ static int __init acpi_cascade_irqdomain_init(void) > > return 0; > > } > > > > +static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, > > + u64 node_map) > > +{ > > + int i; > > + > > + node_map = node_map ? node_map : -1ULL; > > + for_each_possible_cpu(i) { > > + if (node_map & (1ULL << (cpu_to_eio_node(i)))) { > > + node_set(cpu_to_eio_node(i), priv->node_map); > > + cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, > > + cpumask_of(i)); > > + } > > + } > > + > > + priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, > > + priv->vec_count, > > + &eiointc_domain_ops, > > + priv); > > + if (!priv->eiointc_domain) { > > + pr_err("loongson-extioi: cannot add IRQ domain\n"); > > + return -ENOMEM; > > + } > > + > > + eiointc_priv[nr_pics++] = priv; > > + eiointc_router_init(0); > > + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); > > + register_syscore_ops(&eiointc_syscore_ops); > > + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, > > + "irqchip/loongarch/intc:starting", > > + eiointc_router_init, NULL); > > + > > + return 0; > > +} > > + > > int __init eiointc_acpi_init(struct irq_domain *parent, > > struct acpi_madt_eio_pic *acpi_eiointc) > > { > > - int i, ret, parent_irq; > > - unsigned long node_map; > > + int parent_irq, ret; > > struct eiointc_priv *priv; > > > > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > > @@ -391,39 +426,20 @@ int __init eiointc_acpi_init(struct irq_domain *parent, > > goto out_free_priv; > > } > > > > + priv->vec_count = VEC_COUNT; > > priv->node = acpi_eiointc->node; > > - node_map = acpi_eiointc->node_map ? : -1ULL; > > - > > - for_each_possible_cpu(i) { > > - if (node_map & (1ULL << cpu_to_eio_node(i))) { > > - node_set(cpu_to_eio_node(i), priv->node_map); > > - cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i)); > > - } > > - } > > - > > - /* Setup IRQ domain */ > > - priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT, > > - &eiointc_domain_ops, priv); > > - if (!priv->eiointc_domain) { > > - pr_err("loongson-eiointc: cannot add IRQ domain\n"); > > - goto out_free_handle; > > - } > > - > > - eiointc_priv[nr_pics++] = priv; > > - > > - eiointc_router_init(0); > > - > > parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); > > - irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); > > > > - register_syscore_ops(&eiointc_syscore_ops); > > - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, > > - "irqchip/loongarch/intc:starting", > > - eiointc_router_init, NULL); > > + ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); > > + if (ret < 0) > > + goto out_free_handle; > > > > acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); > > acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); > > + > > ret = acpi_cascade_irqdomain_init(); > > + if (ret < 0) > > + goto out_free_handle; > > > > return ret; > > > > @@ -435,3 +451,39 @@ int __init eiointc_acpi_init(struct irq_domain *parent, > > > > return -ENOMEM; > > } > > + > > +static int __init eiointc_of_init(struct device_node *of_node, > > + struct device_node *parent) > > +{ > > + int parent_irq, ret; > > + struct eiointc_priv *priv; > > + > > + priv = kzalloc(sizeof(*priv), GFP_KERNEL); > > + if (!priv) > > + return -ENOMEM; > > + > > + parent_irq = of_irq_get_byname(of_node, "cascade"); > > + if (parent_irq <= 0) { > > + ret = -ENODEV; > > + goto out_free_priv; > > + } > > + > > + ret = of_property_read_u32(of_node, "vec_count", &priv->vec_count); > > + if (ret < 0) > > + goto out_free_priv; > > + > > + priv->node = 0; > > + priv->domain_handle = of_node_to_fwnode(of_node); > > + > > + ret = eiointc_init(priv, parent_irq, 0); > > + if (ret < 0) > > + goto out_free_priv; > > + > > + return 0; > > + > > +out_free_priv: > > + kfree(priv); > > + return ret; > > +} > > + > > +IRQCHIP_DECLARE(loongson_eiointc, "loongson,eiointc", eiointc_of_init); > > -- > > 2.39.0 > > > > >
© 2016 - 2025 Red Hat, Inc.