[v2] irqchip: loongson-liointc: add hierarchy irq support

Message ID 20221209033309.4374-1-zhuyinbo@loongson.cn
State New
Headers
Series [v2] irqchip: loongson-liointc: add hierarchy irq support |

Commit Message

Yinbo Zhu Dec. 9, 2022, 3:33 a.m. UTC
  When the irq of hierarchical interrupt chip was routed to liointc
that asked liointc driver to support hierarchy irq and this patch
was to add such support.

Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
---
Change in v2:
		1. Keep consistent approach for irq handle of dts and acpi.
		2. Use a domain to cover all case.
		3. Fixup the commit log.

 drivers/irqchip/Kconfig                |  1 +
 drivers/irqchip/irq-loongson-liointc.c | 53 +++++++++++++++++---------
 2 files changed, 37 insertions(+), 17 deletions(-)
  

Patch

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d07568a2c539..97f589d681c6 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -593,6 +593,7 @@  config LOONGSON_LIOINTC
 	default y
 	select IRQ_DOMAIN
 	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN_HIERARCHY
 	help
 	  Support for the Loongson Local I/O Interrupt Controller.
 
diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 85b754f7f4e6..e5670cc6123a 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -160,26 +160,48 @@  static u32 parent_int_map[LIOINTC_NUM_PARENT];
 static const char *const parent_names[] = {"int0", "int1", "int2", "int3"};
 static const char *const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"};
 
-static int liointc_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
-			     const u32 *intspec, unsigned int intsize,
-			     unsigned long *out_hwirq, unsigned int *out_type)
+static int liointc_irq_domain_translate(struct irq_domain *d,
+			struct irq_fwspec *fwspec, unsigned long *out_hwirq,
+			unsigned int *out_type)
 {
-	if (WARN_ON(intsize < 1))
+	if (WARN_ON(fwspec->param_count < 1))
 		return -EINVAL;
-	*out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ;
 
-	if (intsize > 1)
-		*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	if (!acpi_disabled)
+		*out_hwirq = fwspec->param[0] - GSI_MIN_CPU_IRQ;
+	else
+		*out_hwirq = fwspec->param[0];
+
+	if (fwspec->param_count > 1)
+		*out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
 	else
 		*out_type = IRQ_TYPE_NONE;
 
 	return 0;
 }
 
-static const struct irq_domain_ops acpi_irq_gc_ops = {
-	.map	= irq_map_generic_chip,
-	.unmap  = irq_unmap_generic_chip,
-	.xlate	= liointc_domain_xlate,
+static int liointc_irq_domain_alloc(struct irq_domain *domain,
+		unsigned int virq, unsigned int nr_irqs, void *arg)
+{
+	int i, ret;
+	irq_hw_number_t hwirq;
+	unsigned int type = IRQ_TYPE_NONE;
+	struct irq_fwspec *fwspec = arg;
+
+	ret = liointc_irq_domain_translate(domain, fwspec, &hwirq, &type);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_map_generic_chip(domain, virq + i, hwirq + i);
+
+	return 0;
+}
+
+static const struct irq_domain_ops irq_gc_ops = {
+	.translate = liointc_irq_domain_translate,
+	.alloc     = liointc_irq_domain_alloc,
+	.free      = irq_domain_free_irqs_top,
 };
 
 static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
@@ -222,12 +244,9 @@  static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
 	}
 
 	/* Setup IRQ domain */
-	if (!acpi_disabled)
-		domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
-					&acpi_irq_gc_ops, priv);
-	else
-		domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
-					&irq_generic_chip_ops, priv);
+	domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
+					  &irq_gc_ops, priv);
+
 	if (!domain) {
 		pr_err("loongson-liointc: cannot add IRQ domain\n");
 		goto out_iounmap;