All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jianmin Lv <lvjianmin@loongson.cn>
To: Thomas Gleixner <tglx@linutronix.de>, Marc Zyngier <maz@kernel.org>
Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev,
	Hanjun Guo <guohanjun@huawei.com>,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Jiaxun Yang <jiaxun.yang@flygoat.com>,
	Huacai Chen <chenhuacai@loongson.cn>
Subject: [PATCH V18 10/13] irqchip/loongson-liointc: Add ACPI init support
Date: Wed, 20 Jul 2022 18:51:29 +0800	[thread overview]
Message-ID: <1658314292-35346-11-git-send-email-lvjianmin@loongson.cn> (raw)
In-Reply-To: <1658314292-35346-1-git-send-email-lvjianmin@loongson.cn>

From: Huacai Chen <chenhuacai@loongson.cn>

LIOINTC stands for "Legacy I/O Interrupts" that described in Section
11.1 of "Loongson 3A5000 Processor Reference Manual". For more
information please refer Documentation/loongarch/irq-chip-model.rst.

Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/include/asm/irq.h            |   4 +-
 arch/loongarch/kernel/irq.c                 |   1 -
 arch/mips/include/asm/mach-loongson64/irq.h |   1 +
 drivers/irqchip/irq-loongson-liointc.c      | 203 ++++++++++++++++++----------
 4 files changed, 131 insertions(+), 78 deletions(-)

diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h
index e9039f2..c847300 100644
--- a/arch/loongarch/include/asm/irq.h
+++ b/arch/loongarch/include/asm/irq.h
@@ -105,7 +105,7 @@ static inline void eiointc_enable(void)
 
 struct irq_domain *loongarch_cpu_irq_init(void);
 
-struct irq_domain *liointc_acpi_init(struct irq_domain *parent,
+int liointc_acpi_init(struct irq_domain *parent,
 					struct acpi_madt_lio_pic *acpi_liointc);
 struct irq_domain *eiointc_acpi_init(struct irq_domain *parent,
 					struct acpi_madt_eio_pic *acpi_eiointc);
@@ -138,7 +138,7 @@ int pch_pic_acpi_init(struct irq_domain *parent,
 extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
 
 extern struct irq_domain *cpu_domain;
-extern struct irq_domain *liointc_domain;
+extern struct fwnode_handle *liointc_handle;
 extern struct fwnode_handle *pch_lpc_handle;
 extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
 
diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c
index 066f892..da131f5 100644
--- a/arch/loongarch/kernel/irq.c
+++ b/arch/loongarch/kernel/irq.c
@@ -26,7 +26,6 @@
 EXPORT_PER_CPU_SYMBOL(irq_stat);
 
 struct irq_domain *cpu_domain;
-struct irq_domain *liointc_domain;
 
 struct acpi_vector_group pch_group[MAX_IO_PICS];
 struct acpi_vector_group msi_group[MAX_IO_PICS];
diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h
index 55e0dee..67c15f3 100644
--- a/arch/mips/include/asm/mach-loongson64/irq.h
+++ b/arch/mips/include/asm/mach-loongson64/irq.h
@@ -9,6 +9,7 @@
 #define NR_IRQS			(NR_IRQS_LEGACY + NR_MIPS_CPU_IRQS + NR_MAX_CHAINED_IRQS + 256)
 #define MAX_IO_PICS		1
 #define MIPS_CPU_IRQ_BASE 	NR_IRQS_LEGACY
+#define GSI_MIN_CPU_IRQ		0
 
 #include <asm/mach-generic/irq.h>
 
diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 8d05d8b..c4f3c886a 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -23,7 +23,7 @@
 #endif
 
 #define LIOINTC_CHIP_IRQ	32
-#define LIOINTC_NUM_PARENT 4
+#define LIOINTC_NUM_PARENT	4
 #define LIOINTC_NUM_CORES	4
 
 #define LIOINTC_INTC_CHIP_START	0x20
@@ -58,6 +58,8 @@ struct liointc_priv {
 	bool				has_lpc_irq_errata;
 };
 
+struct fwnode_handle *liointc_handle;
+
 static void liointc_chained_handle_irq(struct irq_desc *desc)
 {
 	struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
@@ -153,97 +155,79 @@ static void liointc_resume(struct irq_chip_generic *gc)
 	irq_gc_unlock_irqrestore(gc, flags);
 }
 
-static const char * const parent_names[] = {"int0", "int1", "int2", "int3"};
-static const char * const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"};
+static int parent_irq[LIOINTC_NUM_PARENT];
+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 void __iomem *liointc_get_reg_byname(struct device_node *node,
-						const char *name)
+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)
 {
-	int index = of_property_match_string(node, "reg-names", name);
-
-	if (index < 0)
-		return NULL;
-
-	return of_iomap(node, index);
+	if (WARN_ON(intsize < 1))
+		return -EINVAL;
+	*out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ;
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
 }
 
-static int __init liointc_of_init(struct device_node *node,
-				  struct device_node *parent)
+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_init(phys_addr_t addr, unsigned long size, int revision,
+		struct fwnode_handle *domain_handle, struct device_node *node)
 {
+	int i, err;
+	void __iomem *base;
+	struct irq_chip_type *ct;
 	struct irq_chip_generic *gc;
 	struct irq_domain *domain;
-	struct irq_chip_type *ct;
 	struct liointc_priv *priv;
-	void __iomem *base;
-	u32 of_parent_int_map[LIOINTC_NUM_PARENT];
-	int parent_irq[LIOINTC_NUM_PARENT];
-	bool have_parent = FALSE;
-	int sz, i, err = 0;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	if (of_device_is_compatible(node, "loongson,liointc-2.0")) {
-		base = liointc_get_reg_byname(node, "main");
-		if (!base) {
-			err = -ENODEV;
-			goto out_free_priv;
-		}
+	base = ioremap(addr, size);
+	if (!base)
+		goto out_free_priv;
 
-		for (i = 0; i < LIOINTC_NUM_CORES; i++)
-			priv->core_isr[i] = liointc_get_reg_byname(node, core_reg_names[i]);
-		if (!priv->core_isr[0]) {
-			err = -ENODEV;
-			goto out_iounmap_base;
-		}
-	} else {
-		base = of_iomap(node, 0);
-		if (!base) {
-			err = -ENODEV;
-			goto out_free_priv;
-		}
+	for (i = 0; i < LIOINTC_NUM_CORES; i++)
+		priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS;
 
-		for (i = 0; i < LIOINTC_NUM_CORES; i++)
-			priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS;
-	}
+	for (i = 0; i < LIOINTC_NUM_PARENT; i++)
+		priv->handler[i].parent_int_map = parent_int_map[i];
 
-	for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
-		parent_irq[i] = of_irq_get_byname(node, parent_names[i]);
-		if (parent_irq[i] > 0)
-			have_parent = TRUE;
-	}
-	if (!have_parent) {
-		err = -ENODEV;
-		goto out_iounmap_isr;
-	}
+	if (revision > 1) {
+		for (i = 0; i < LIOINTC_NUM_CORES; i++) {
+			int index = of_property_match_string(node,
+					"reg-names", core_reg_names[i]);
 
-	sz = of_property_read_variable_u32_array(node,
-						"loongson,parent_int_map",
-						&of_parent_int_map[0],
-						LIOINTC_NUM_PARENT,
-						LIOINTC_NUM_PARENT);
-	if (sz < 4) {
-		pr_err("loongson-liointc: No parent_int_map\n");
-		err = -ENODEV;
-		goto out_iounmap_isr;
-	}
+			if (index < 0)
+				return -EINVAL;
 
-	for (i = 0; i < LIOINTC_NUM_PARENT; i++)
-		priv->handler[i].parent_int_map = of_parent_int_map[i];
+			priv->core_isr[i] = of_iomap(node, index);
+		}
+	}
 
 	/* Setup IRQ domain */
-	domain = irq_domain_add_linear(node, 32,
+	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);
 	if (!domain) {
 		pr_err("loongson-liointc: cannot add IRQ domain\n");
-		err = -EINVAL;
-		goto out_iounmap_isr;
+		goto out_iounmap;
 	}
 
-	err = irq_alloc_domain_generic_chips(domain, 32, 1,
-					node->full_name, handle_level_irq,
-					IRQ_NOPROBE, 0, 0);
+	err = irq_alloc_domain_generic_chips(domain, LIOINTC_CHIP_IRQ, 1,
+					(node ? node->full_name : "LIOINTC"),
+					handle_level_irq, 0, IRQ_NOPROBE, 0);
 	if (err) {
 		pr_err("loongson-liointc: unable to register IRQ domain\n");
 		goto out_free_domain;
@@ -299,24 +283,93 @@ static int __init liointc_of_init(struct device_node *node,
 				liointc_chained_handle_irq, &priv->handler[i]);
 	}
 
+	liointc_handle = domain_handle;
 	return 0;
 
 out_free_domain:
 	irq_domain_remove(domain);
-out_iounmap_isr:
-	for (i = 0; i < LIOINTC_NUM_CORES; i++) {
-		if (!priv->core_isr[i])
-			continue;
-		iounmap(priv->core_isr[i]);
-	}
-out_iounmap_base:
+out_iounmap:
 	iounmap(base);
 out_free_priv:
 	kfree(priv);
 
-	return err;
+	return -EINVAL;
+}
+
+#ifdef CONFIG_OF
+
+static int __init liointc_of_init(struct device_node *node,
+				  struct device_node *parent)
+{
+	bool have_parent = FALSE;
+	int sz, i, index, revision, err = 0;
+	struct resource res;
+
+	if (!of_device_is_compatible(node, "loongson,liointc-2.0")) {
+		index = 0;
+		revision = 1;
+	} else {
+		index = of_property_match_string(node, "reg-names", "main");
+		revision = 2;
+	}
+
+	if (of_address_to_resource(node, index, &res))
+		return -EINVAL;
+
+	for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
+		parent_irq[i] = of_irq_get_byname(node, parent_names[i]);
+		if (parent_irq[i] > 0)
+			have_parent = TRUE;
+	}
+	if (!have_parent)
+		return -ENODEV;
+
+	sz = of_property_read_variable_u32_array(node,
+						"loongson,parent_int_map",
+						&parent_int_map[0],
+						LIOINTC_NUM_PARENT,
+						LIOINTC_NUM_PARENT);
+	if (sz < 4) {
+		pr_err("loongson-liointc: No parent_int_map\n");
+		return -ENODEV;
+	}
+
+	err = liointc_init(res.start, resource_size(&res),
+			revision, of_node_to_fwnode(node), node);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_init);
 IRQCHIP_DECLARE(loongson_liointc_1_0a, "loongson,liointc-1.0a", liointc_of_init);
 IRQCHIP_DECLARE(loongson_liointc_2_0, "loongson,liointc-2.0", liointc_of_init);
+
+#endif
+
+#ifdef CONFIG_ACPI
+int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc)
+{
+	int ret;
+	struct fwnode_handle *domain_handle;
+
+	parent_int_map[0] = acpi_liointc->cascade_map[0];
+	parent_int_map[1] = acpi_liointc->cascade_map[1];
+
+	parent_irq[0] = irq_create_mapping(parent, acpi_liointc->cascade[0]);
+	parent_irq[1] = irq_create_mapping(parent, acpi_liointc->cascade[1]);
+
+	domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_liointc);
+	if (!domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		return -ENOMEM;
+	}
+	ret = liointc_init(acpi_liointc->address, acpi_liointc->size,
+			   1, domain_handle, NULL);
+	if (ret)
+		irq_domain_free_fwnode(domain_handle);
+
+	return ret;
+}
+#endif
-- 
1.8.3.1


  parent reply	other threads:[~2022-07-20 10:51 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-20 10:51 [PATCH V18 00/13] irqchip: Add LoongArch-related irqchip drivers Jianmin Lv
2022-07-20 10:51 ` [PATCH V18 01/13] LoongArch: Provisionally add ACPICA data structures Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Marc Zyngier
2022-07-20 10:51 ` [PATCH V18 02/13] APCI: irq: Add support for multiple GSI domains Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Marc Zyngier
2022-07-20 10:51 ` [PATCH V18 03/13] ACPI: irq: Allow acpi_gsi_to_irq() to have an arch-specific fallback Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Marc Zyngier
2022-07-20 10:51 ` [PATCH V18 04/13] genirq/generic_chip: export irq_unmap_generic_chip Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] genirq/generic_chip: Export irq_unmap_generic_chip irqchip-bot for Jianmin Lv
2022-07-20 10:51 ` [PATCH V18 05/13] LoongArch: Use ACPI_GENERIC_GSI for gsi handling Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Jianmin Lv
2022-07-20 10:51 ` [PATCH V18 06/13] LoongArch: Prepare to support multiple pch-pic and pch-msi irqdomain Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Jianmin Lv
2022-07-20 10:51 ` [PATCH V18 07/13] irqchip: Add Loongson PCH LPC controller support Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` [PATCH V18 08/13] irqchip/loongson-pch-pic: Add ACPI init support Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` [PATCH V18 09/13] irqchip/loongson-pch-msi: " Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` Jianmin Lv [this message]
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] irqchip/loongson-liointc: " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` [PATCH V18 11/13] irqchip: Add Loongson Extended I/O interrupt controller support Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` [PATCH V18 12/13] irqchip: Add LoongArch CPU " Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Huacai Chen
2022-07-20 10:51 ` [PATCH V18 13/13] irqchip / ACPI: Introduce ACPI_IRQ_MODEL_LPIC for LoongArch Jianmin Lv
2022-07-20 11:27   ` [irqchip: irq/irqchip-next] " irqchip-bot for Jianmin Lv
2022-07-20 11:03 ` [PATCH V18 00/13] irqchip: Add LoongArch-related irqchip drivers Marc Zyngier
2022-07-20 12:06   ` Jianmin Lv
2022-07-22  2:25   ` Huacai Chen
2022-07-22  8:07     ` Marc Zyngier
2022-07-22 10:16       ` Huacai Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1658314292-35346-11-git-send-email-lvjianmin@loongson.cn \
    --to=lvjianmin@loongson.cn \
    --cc=chenhuacai@loongson.cn \
    --cc=guohanjun@huawei.com \
    --cc=jiaxun.yang@flygoat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=loongarch@lists.linux.dev \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=maz@kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.