All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers
@ 2021-07-06  3:08 Huacai Chen
  2021-07-06  3:08 ` [PATCH 1/9] irqchip: Adjust Kconfig for Loongson Huacai Chen
                   ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen,
	Chen Zhu

LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V.
LoongArch includes a reduced 32-bit version (LA32R), a standard 32-bit
version (LA32S) and a 64-bit version (LA64). LoongArch use ACPI as its
boot protocol LoongArch-specific interrupt controllers (similar to APIC)
are already added in the next revision of ACPI Specification (current
revision is 6.4).

This patchset adds some irqchip drivers for LoongArch, it is preparing
to add LoongArch support in mainline kernel, we can see a snapshot here:
https://github.com/loongson/linux/tree/loongarch-next

Cross-compile tool chain to build kernel:
https://github.com/loongson/build-tools/releases

Loongson and LoongArch documentations:
https://github.com/loongson/LoongArch-Documentation

LoongArch-specific interrupt controllers:
https://mantis.uefi.org/mantis/view.php?id=2203

Huacai Chen and Chen Zhu(9):
 irqchip: Adjust Kconfig for Loongson.
 irqchip/loongson-pch-pic: Improve edge triggered interrupt support.
 irqchip/loongson-pch-pic: Add ACPI init support.
 irqchip/loongson-pch-msi: Add ACPI init support.
 irqchip/loongson-htvec: Add ACPI init support.
 irqchip/loongson-liointc: Add ACPI init support. 
 irqchip: Add LoongArch CPU interrupt controller support.
 irqchip: Add Loongson Extended I/O interrupt controller.
 irqchip: Add Loongson PCH LPC controller support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Chen Zhu <zhuchen@loongson.cn> 
---
 drivers/irqchip/Kconfig                |  37 +++-
 drivers/irqchip/Makefile               |   3 +
 drivers/irqchip/irq-loongarch-cpu.c    |  87 ++++++++++
 drivers/irqchip/irq-loongson-eiointc.c | 308 +++++++++++++++++++++++++++++++++
 drivers/irqchip/irq-loongson-htvec.c   | 102 ++++++++++-
 drivers/irqchip/irq-loongson-liointc.c | 140 ++++++++++++++-
 drivers/irqchip/irq-loongson-pch-lpc.c | 204 ++++++++++++++++++++++
 drivers/irqchip/irq-loongson-pch-msi.c |  69 +++++++-
 drivers/irqchip/irq-loongson-pch-pic.c | 139 ++++++++++++++-
 include/linux/cpuhotplug.h             |   1 +
 10 files changed, 1069 insertions(+), 21 deletions(-)
 create mode 100644 drivers/irqchip/irq-loongarch-cpu.c
 create mode 100644 drivers/irqchip/irq-loongson-eiointc.c
 create mode 100644 drivers/irqchip/irq-loongson-pch-lpc.c
--
2.27.0


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/9] irqchip: Adjust Kconfig for Loongson
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
@ 2021-07-06  3:08 ` Huacai Chen
  2021-07-06  3:08 ` [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support Huacai Chen
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. HTVEC will be used by more Loongson processors, so we adjust
its description. HTPIC is bound to MIPS-based Loongson, so we add a
MIPS dependency. PCH_PIC and PCH_MSI will have some arch-specific code,
so remove COMPILE_TEST dependency to avoid build warnings.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/Kconfig | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d5924e9f766..084bc4c2eebd 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -539,7 +539,7 @@ config LOONGSON_LIOINTC
 
 config LOONGSON_HTPIC
 	bool "Loongson3 HyperTransport PIC Controller"
-	depends on MACH_LOONGSON64
+	depends on (MACH_LOONGSON64 && MIPS)
 	default y
 	select IRQ_DOMAIN
 	select GENERIC_IRQ_CHIP
@@ -547,16 +547,16 @@ config LOONGSON_HTPIC
 	  Support for the Loongson-3 HyperTransport PIC Controller.
 
 config LOONGSON_HTVEC
-	bool "Loongson3 HyperTransport Interrupt Vector Controller"
+	bool "Loongson HyperTransport Interrupt Vector Controller"
 	depends on MACH_LOONGSON64
 	default MACH_LOONGSON64
 	select IRQ_DOMAIN_HIERARCHY
 	help
-	  Support for the Loongson3 HyperTransport Interrupt Vector Controller.
+	  Support for the Loongson HyperTransport Interrupt Vector Controller.
 
 config LOONGSON_PCH_PIC
 	bool "Loongson PCH PIC Controller"
-	depends on MACH_LOONGSON64 || COMPILE_TEST
+	depends on MACH_LOONGSON64
 	default MACH_LOONGSON64
 	select IRQ_DOMAIN_HIERARCHY
 	select IRQ_FASTEOI_HIERARCHY_HANDLERS
@@ -565,7 +565,7 @@ config LOONGSON_PCH_PIC
 
 config LOONGSON_PCH_MSI
 	bool "Loongson PCH MSI Controller"
-	depends on MACH_LOONGSON64 || COMPILE_TEST
+	depends on MACH_LOONGSON64
 	depends on PCI
 	default MACH_LOONGSON64
 	select IRQ_DOMAIN_HIERARCHY
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
  2021-07-06  3:08 ` [PATCH 1/9] irqchip: Adjust Kconfig for Loongson Huacai Chen
@ 2021-07-06  3:08 ` Huacai Chen
  2021-07-06 13:06   ` Marc Zyngier
  2021-07-06  3:08 ` [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support Huacai Chen
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen,
	Chen Zhu

Edge-triggered mode and level-triggered mode need different handlers,
and edge-triggered mode need a specific ack operation. So improve it.

Signed-off-by: Chen Zhu <zhuchen@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/irq-loongson-pch-pic.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
index f790ca6d78aa..a4eb8a2181c7 100644
--- a/drivers/irqchip/irq-loongson-pch-pic.c
+++ b/drivers/irqchip/irq-loongson-pch-pic.c
@@ -92,18 +92,22 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
 	case IRQ_TYPE_EDGE_RISING:
 		pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
 		pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
+		irq_set_handler_locked(d, handle_edge_irq);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 		pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
 		pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
+		irq_set_handler_locked(d, handle_edge_irq);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
 		pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
 		pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
+		irq_set_handler_locked(d, handle_level_irq);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
 		pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
+		irq_set_handler_locked(d, handle_level_irq);
 		break;
 	default:
 		ret = -EINVAL;
@@ -113,11 +117,24 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
 	return ret;
 }
 
+static void pch_pic_ack_irq(struct irq_data *d)
+{
+	unsigned int reg;
+	struct pch_pic *priv = irq_data_get_irq_chip_data(d);
+
+	reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
+	if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
+		writel(BIT(PIC_REG_BIT(d->hwirq)),
+			priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
+	}
+	irq_chip_ack_parent(d);
+}
+
 static struct irq_chip pch_pic_irq_chip = {
 	.name			= "PCH PIC",
 	.irq_mask		= pch_pic_mask_irq,
 	.irq_unmask		= pch_pic_unmask_irq,
-	.irq_ack		= irq_chip_ack_parent,
+	.irq_ack		= pch_pic_ack_irq,
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 	.irq_set_type		= pch_pic_set_type,
 };
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
  2021-07-06  3:08 ` [PATCH 1/9] irqchip: Adjust Kconfig for Loongson Huacai Chen
  2021-07-06  3:08 ` [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support Huacai Chen
@ 2021-07-06  3:08 ` Huacai Chen
  2021-07-06 13:10   ` Marc Zyngier
  2021-07-06  3:08 ` [PATCH 4/9] irqchip/loongson-pch-msi: " Huacai Chen
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. LoongArch use ACPI other than DT as its boot protocol, so
add ACPI init support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/irq-loongson-pch-pic.c | 120 ++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
index a4eb8a2181c7..62382611995b 100644
--- a/drivers/irqchip/irq-loongson-pch-pic.c
+++ b/drivers/irqchip/irq-loongson-pch-pic.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *			Jianmin Lv <lvjianmin@loongson.cn>
+ *			Huacai Chen <chenhuacai@loongson.cn>
  *  Loongson PCH PIC support
  */
 
@@ -15,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/syscore_ops.h>
 
 /* Registers */
 #define PCH_PIC_MASK		0x20
@@ -32,14 +35,23 @@
 #define PIC_COUNT		(PIC_COUNT_PER_REG * PIC_REG_COUNT)
 #define PIC_REG_IDX(irq_id)	((irq_id) / PIC_COUNT_PER_REG)
 #define PIC_REG_BIT(irq_id)	((irq_id) % PIC_COUNT_PER_REG)
+#define PCH_PIC_SIZE		0x400
+
+static int nr_pch_pics;
 
 struct pch_pic {
 	void __iomem		*base;
 	struct irq_domain	*pic_domain;
+	struct fwnode_handle	*domain_handle;
 	u32			ht_vec_base;
 	raw_spinlock_t		pic_lock;
+	u32			saved_vec_en[PIC_REG_COUNT];
+	u32			saved_vec_pol[PIC_REG_COUNT];
+	u32			saved_vec_edge[PIC_REG_COUNT];
 };
 
+struct pch_pic *pch_pic_priv[4];
+
 static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
 {
 	u32 reg;
@@ -137,6 +149,7 @@ static struct irq_chip pch_pic_irq_chip = {
 	.irq_ack		= pch_pic_ack_irq,
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 	.irq_set_type		= pch_pic_set_type,
+	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
 static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
@@ -180,7 +193,7 @@ static void pch_pic_reset(struct pch_pic *priv)
 	int i;
 
 	for (i = 0; i < PIC_COUNT; i++) {
-		/* Write vectored ID */
+		/* Write vector ID */
 		writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
 		/* Hardcode route to HT0 Lo */
 		writeb(1, priv->base + PCH_INT_ROUTE(i));
@@ -198,6 +211,48 @@ static void pch_pic_reset(struct pch_pic *priv)
 	}
 }
 
+static int pch_pic_suspend(void)
+{
+	int i, j;
+
+	for (i = 0; i < nr_pch_pics; i++) {
+		for (j = 0; j < PIC_REG_COUNT; j++) {
+			pch_pic_priv[i]->saved_vec_pol[j] =
+				readl(pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
+			pch_pic_priv[i]->saved_vec_edge[j] =
+				readl(pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
+			pch_pic_priv[i]->saved_vec_en[j] =
+				readl(pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
+		}
+	}
+
+	return 0;
+}
+
+static void pch_pic_resume(void)
+{
+	int i, j;
+
+	for (i = 0; i < nr_pch_pics; i++) {
+		pch_pic_reset(pch_pic_priv[i]);
+		for (j = 0; j < PIC_REG_COUNT; j++) {
+			writel(pch_pic_priv[i]->saved_vec_pol[j],
+					pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
+			writel(pch_pic_priv[i]->saved_vec_edge[j],
+					pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
+			writel(pch_pic_priv[i]->saved_vec_en[j],
+					pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
+		}
+	}
+}
+
+static struct syscore_ops pch_pic_syscore_ops = {
+	.suspend =  pch_pic_suspend,
+	.resume =  pch_pic_resume,
+};
+
+#ifdef CONFIG_OF
+
 static int pch_pic_of_init(struct device_node *node,
 				struct device_node *parent)
 {
@@ -242,6 +297,9 @@ static int pch_pic_of_init(struct device_node *node,
 	}
 
 	pch_pic_reset(priv);
+	pch_pic_priv[0] = priv;
+
+	register_syscore_ops(&pch_pic_syscore_ops);
 
 	return 0;
 
@@ -254,3 +312,63 @@ static int pch_pic_of_init(struct device_node *node,
 }
 
 IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init);
+
+#endif
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
+					struct acpi_madt_bio_pic *acpi_pchpic)
+{
+	int count;
+	struct pch_pic *priv;
+	struct irq_domain *parent_domain;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	raw_spin_lock_init(&priv->pic_lock);
+	priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
+	if (!priv->base)
+		goto free_priv;
+
+	priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
+	if (!priv->domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		goto iounmap_base;
+	}
+
+	priv->ht_vec_base = acpi_pchpic->gsi_base;
+	count = ((readq(priv->base) >> 48) & 0xff) + 1;
+	parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
+	if (!parent_domain) {
+		pr_err("Failed to find the parent domain\n");
+		goto iounmap_base;
+	}
+
+	priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
+						count, priv->domain_handle,
+						&pch_pic_domain_ops, priv);
+
+	if (!priv->pic_domain) {
+		pr_err("Failed to create IRQ domain\n");
+		goto iounmap_base;
+	}
+
+	pch_pic_reset(priv);
+	pch_pic_priv[nr_pch_pics++] = priv;
+
+	register_syscore_ops(&pch_pic_syscore_ops);
+
+	return priv->domain_handle;
+
+iounmap_base:
+	iounmap(priv->base);
+free_priv:
+	kfree(priv);
+
+	return NULL;
+}
+
+#endif
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 4/9] irqchip/loongson-pch-msi: Add ACPI init support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (2 preceding siblings ...)
  2021-07-06  3:08 ` [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support Huacai Chen
@ 2021-07-06  3:08 ` Huacai Chen
  2021-07-06 13:12   ` Marc Zyngier
  2021-07-06  3:09 ` [PATCH 5/9] irqchip/loongson-htvec: " Huacai Chen
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. LoongArch use ACPI other than DT as its boot protocol, so
add ACPI init support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/irq-loongson-pch-msi.c | 69 ++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
index 32562b7e681b..adfa30046f0a 100644
--- a/drivers/irqchip/irq-loongson-pch-msi.c
+++ b/drivers/irqchip/irq-loongson-pch-msi.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *			Jianmin Lv <lvjianmin@loongson.cn>
+ *			Huacai Chen <chenhuacai@loongson.cn>
  *  Loongson PCH MSI support
  */
 
@@ -21,6 +23,7 @@ struct pch_msi_data {
 	u32		irq_first;	/* The vector number that MSIs starts */
 	u32		num_irqs;	/* The number of vectors for MSIs */
 	unsigned long	*msi_map;
+	struct fwnode_handle *domain_handle;
 };
 
 static void pch_msi_mask_msi_irq(struct irq_data *d)
@@ -159,7 +162,12 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
 {
 	struct irq_domain *middle_domain, *msi_domain;
 
-	middle_domain = irq_domain_create_linear(of_node_to_fwnode(node),
+	if (node)
+		priv->domain_handle = of_node_to_fwnode(node);
+	else
+		priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
+
+	middle_domain = irq_domain_create_linear(priv->domain_handle,
 						priv->num_irqs,
 						&pch_msi_middle_domain_ops,
 						priv);
@@ -171,7 +179,7 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
 	middle_domain->parent = parent;
 	irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
 
-	msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+	msi_domain = pci_msi_create_irq_domain(priv->domain_handle,
 					       &pch_msi_domain_info,
 					       middle_domain);
 	if (!msi_domain) {
@@ -183,8 +191,9 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
 	return 0;
 }
 
-static int pch_msi_init(struct device_node *node,
-			    struct device_node *parent)
+#ifdef CONFIG_OF
+
+int pch_msi_of_init(struct device_node *node, struct device_node *parent)
 {
 	struct pch_msi_data *priv;
 	struct irq_domain *parent_domain;
@@ -247,4 +256,54 @@ static int pch_msi_init(struct device_node *node,
 	return ret;
 }
 
-IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init);
+IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init);
+
+#endif
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle *pch_msi_acpi_init(struct fwnode_handle *parent,
+					struct acpi_madt_msi_pic *acpi_pchmsi)
+{
+	int ret;
+	struct pch_msi_data *priv;
+	struct irq_domain *parent_domain;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	mutex_init(&priv->msi_map_lock);
+
+	priv->doorbell = acpi_pchmsi->msg_address;
+	priv->irq_first = acpi_pchmsi->start;
+	priv->num_irqs = acpi_pchmsi->count;
+
+	parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
+	if (!parent_domain) {
+		pr_err("Failed to find the parent domain\n");
+		return NULL;
+	}
+
+	priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL);
+	if (!priv->msi_map)
+		goto err_priv;
+
+	pr_debug("Registering %d MSIs, starting at %d\n",
+		 priv->num_irqs, priv->irq_first);
+
+	ret = pch_msi_init_domains(priv, NULL, parent_domain);
+	if (ret)
+		goto err_map;
+
+	return priv->domain_handle;
+
+err_map:
+	kfree(priv->msi_map);
+err_priv:
+	kfree(priv);
+
+	return NULL;
+}
+
+#endif
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 5/9] irqchip/loongson-htvec: Add ACPI init support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (3 preceding siblings ...)
  2021-07-06  3:08 ` [PATCH 4/9] irqchip/loongson-pch-msi: " Huacai Chen
@ 2021-07-06  3:09 ` Huacai Chen
  2021-07-06 13:13   ` Marc Zyngier
  2021-07-06  3:09 ` [PATCH 6/9] irqchip/loongson-liointc: " Huacai Chen
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. LoongArch use ACPI other than DT as its boot protocol, so
add ACPI init support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/irq-loongson-htvec.c | 102 ++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c
index 60a335d7e64e..69452d4a33c0 100644
--- a/drivers/irqchip/irq-loongson-htvec.c
+++ b/drivers/irqchip/irq-loongson-htvec.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *			Jianmin Lv <lvjianmin@loongson.cn>
+ *			Huacai Chen <chenhuacai@loongson.cn>
  *  Loongson HyperTransport Interrupt Vector support
  */
 
@@ -16,22 +18,27 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/syscore_ops.h>
 
 /* Registers */
 #define HTVEC_EN_OFF		0x20
 #define HTVEC_MAX_PARENT_IRQ	8
-
 #define VEC_COUNT_PER_REG	32
 #define VEC_REG_IDX(irq_id)	((irq_id) / VEC_COUNT_PER_REG)
 #define VEC_REG_BIT(irq_id)	((irq_id) % VEC_COUNT_PER_REG)
+#define HTVEC_SIZE		0x400
 
 struct htvec {
 	int			num_parents;
 	void __iomem		*base;
 	struct irq_domain	*htvec_domain;
 	raw_spinlock_t		htvec_lock;
+	struct fwnode_handle	*domain_handle;
+	u32			saved_vec_en[HTVEC_MAX_PARENT_IRQ];
 };
 
+struct htvec *htvec_priv;
+
 static void htvec_irq_dispatch(struct irq_desc *desc)
 {
 	int i;
@@ -155,6 +162,31 @@ static void htvec_reset(struct htvec *priv)
 	}
 }
 
+static int htvec_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < htvec_priv->num_parents; i++)
+		htvec_priv->saved_vec_en[i] = readl(htvec_priv->base + HTVEC_EN_OFF + 4 * i);
+
+	return 0;
+}
+
+static void htvec_resume(void)
+{
+	int i;
+
+	for (i = 0; i < htvec_priv->num_parents; i++)
+		writel(htvec_priv->saved_vec_en[i], htvec_priv->base + HTVEC_EN_OFF + 4 * i);
+}
+
+static struct syscore_ops htvec_syscore_ops = {
+	.suspend = htvec_suspend,
+	.resume = htvec_resume,
+};
+
+#ifdef CONFIG_OF
+
 static int htvec_of_init(struct device_node *node,
 				struct device_node *parent)
 {
@@ -202,6 +234,10 @@ static int htvec_of_init(struct device_node *node,
 		irq_set_chained_handler_and_data(parent_irq[i],
 						 htvec_irq_dispatch, priv);
 
+	htvec_priv = priv;
+
+	register_syscore_ops(&htvec_syscore_ops);
+
 	return 0;
 
 irq_dispose:
@@ -216,3 +252,67 @@ static int htvec_of_init(struct device_node *node,
 }
 
 IRQCHIP_DECLARE(htvec, "loongson,htvec-1.0", htvec_of_init);
+
+#endif
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle *htvec_acpi_init(struct fwnode_handle *parent,
+					struct acpi_madt_ht_pic *acpi_htvec)
+{
+	int i, parent_irq[8];
+	struct htvec *priv;
+	struct irq_fwspec fwspec;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	priv->num_parents = HTVEC_MAX_PARENT_IRQ;
+	priv->base = ioremap(acpi_htvec->address, acpi_htvec->size);
+
+	/* Interrupt may come from any of the 8 interrupt lines */
+	for (i = 0; i < priv->num_parents; i++)
+		parent_irq[i] = acpi_htvec->cascade[i];
+
+	priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
+	if (!priv->domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		goto iounmap_base;
+	}
+
+	/* Setup IRQ domain */
+	priv->htvec_domain = irq_domain_create_linear(priv->domain_handle,
+					(VEC_COUNT_PER_REG * priv->num_parents),
+					&htvec_domain_ops, priv);
+	if (!priv->htvec_domain) {
+		pr_err("loongson-htvec: cannot add IRQ domain\n");
+		goto iounmap_base;
+	}
+
+	htvec_reset(priv);
+
+	for (i = 0; i < priv->num_parents; i++) {
+		fwspec.fwnode = parent;
+		fwspec.param[0] = parent_irq[i];
+		fwspec.param_count = 1;
+		parent_irq[i] = irq_create_fwspec_mapping(&fwspec);
+		irq_set_chained_handler_and_data(parent_irq[i],
+						 htvec_irq_dispatch, priv);
+	}
+
+	htvec_priv = priv;
+
+	register_syscore_ops(&htvec_syscore_ops);
+
+	return htvec_priv->domain_handle;
+
+iounmap_base:
+	iounmap(priv->base);
+	priv->domain_handle = NULL;
+	kfree(priv);
+
+	return NULL;
+}
+
+#endif
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 6/9] irqchip/loongson-liointc: Add ACPI init support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (4 preceding siblings ...)
  2021-07-06  3:09 ` [PATCH 5/9] irqchip/loongson-htvec: " Huacai Chen
@ 2021-07-06  3:09 ` Huacai Chen
  2021-07-09  0:59   ` kernel test robot
  2021-07-06  3:09 ` [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support Huacai Chen
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. LoongArch use ACPI other than DT as its boot protocol, so
add ACPI init support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/irq-loongson-liointc.c | 140 +++++++++++++++++++++++--
 1 file changed, 132 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 649c58391618..591fc1192e73 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *			Jianmin Lv <lvjianmin@loongson.cn>
+ *			Huacai Chen <chenhuacai@loongson.cn>
  *  Loongson Local IO Interrupt Controller support
  */
 
@@ -19,7 +21,7 @@
 #include <loongson.h>
 
 #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
@@ -53,7 +55,7 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
 	struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct irq_chip_generic *gc = handler->priv->gc;
-	int core = get_ebase_cpunum() % LIOINTC_NUM_CORES;
+	int core = cpu_logical_map(smp_processor_id()) % LIOINTC_NUM_CORES;
 	u32 pending;
 
 	chained_irq_enter(chip, desc);
@@ -143,8 +145,12 @@ 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"};
+
+#ifdef CONFIG_OF
 
 static void __iomem *liointc_get_reg_byname(struct device_node *node,
 						const char *name)
@@ -165,8 +171,6 @@ static int __init liointc_of_init(struct device_node *node,
 	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;
 
@@ -210,7 +214,7 @@ static int __init liointc_of_init(struct device_node *node,
 
 	sz = of_property_read_variable_u32_array(node,
 						"loongson,parent_int_map",
-						&of_parent_int_map[0],
+						&parent_int_map[0],
 						LIOINTC_NUM_PARENT,
 						LIOINTC_NUM_PARENT);
 	if (sz < 4) {
@@ -220,7 +224,7 @@ static int __init liointc_of_init(struct device_node *node,
 	}
 
 	for (i = 0; i < LIOINTC_NUM_PARENT; i++)
-		priv->handler[i].parent_int_map = of_parent_int_map[i];
+		priv->handler[i].parent_int_map = parent_int_map[i];
 
 	/* Setup IRQ domain */
 	domain = irq_domain_add_linear(node, 32,
@@ -310,3 +314,123 @@ static int __init liointc_of_init(struct device_node *node,
 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
+
+struct fwnode_handle *liointc_acpi_init(struct acpi_madt_lio_pic *acpi_liointc)
+{
+	int i, err;
+	void __iomem *base;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	struct irq_domain *domain;
+	struct liointc_priv *priv;
+	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] = LOONGSON_CPU_IRQ_BASE + acpi_liointc->cascade[0];
+	if (!cpu_has_extioi)
+		parent_irq[1] = LOONGSON_CPU_IRQ_BASE + acpi_liointc->cascade[1];
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	base = ioremap(acpi_liointc->address, acpi_liointc->size);
+	if (!base)
+		goto out_free_priv;
+
+	for (i = 0; i < LIOINTC_NUM_CORES; i++)
+		priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS;
+
+	domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
+	if (!domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		return NULL;
+	}
+
+	for (i = 0; i < LIOINTC_NUM_PARENT; i++)
+		priv->handler[i].parent_int_map = parent_int_map[i];
+
+	/* Setup IRQ domain */
+	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");
+		goto out_iounmap;
+	}
+
+	err = irq_alloc_domain_generic_chips(domain, LIOINTC_CHIP_IRQ, 1,
+					"LIOINTC", handle_level_irq,
+					0, IRQ_NOPROBE, 0);
+	if (err) {
+		pr_err("loongson-liointc: unable to register IRQ domain\n");
+		goto out_free_domain;
+	}
+
+
+	/* Disable all IRQs */
+	writel(0xffffffff, base + LIOINTC_REG_INTC_DISABLE);
+	/* Set to level triggered */
+	writel(0x0, base + LIOINTC_REG_INTC_EDGE);
+
+	/* Generate parent INT part of map cache */
+	for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
+		u32 pending = priv->handler[i].parent_int_map;
+
+		while (pending) {
+			int bit = __ffs(pending);
+
+			priv->map_cache[bit] = BIT(i) << LIOINTC_SHIFT_INTx;
+			pending &= ~BIT(bit);
+		}
+	}
+
+	for (i = 0; i < LIOINTC_CHIP_IRQ; i++) {
+		/* Generate core part of map cache */
+		priv->map_cache[i] |= BIT(loongson_sysconf.boot_cpu_id);
+		writeb(priv->map_cache[i], base + i);
+	}
+
+	gc = irq_get_domain_generic_chip(domain, 0);
+	gc->private = priv;
+	gc->reg_base = base;
+	gc->domain = domain;
+	gc->resume = liointc_resume;
+
+	ct = gc->chip_types;
+	ct->regs.enable = LIOINTC_REG_INTC_ENABLE;
+	ct->regs.disable = LIOINTC_REG_INTC_DISABLE;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
+
+	gc->mask_cache = 0;
+	priv->gc = gc;
+
+	for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
+		if (parent_irq[i] <= 0)
+			continue;
+
+		priv->handler[i].priv = priv;
+		irq_set_chained_handler_and_data(parent_irq[i],
+				liointc_chained_handle_irq, &priv->handler[i]);
+	}
+
+	return domain_handle;
+
+out_free_domain:
+	irq_domain_remove(domain);
+out_iounmap:
+	iounmap(base);
+out_free_priv:
+	kfree(priv);
+
+	return NULL;
+}
+
+#endif
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (5 preceding siblings ...)
  2021-07-06  3:09 ` [PATCH 6/9] irqchip/loongson-liointc: " Huacai Chen
@ 2021-07-06  3:09 ` Huacai Chen
  2021-07-06 13:21   ` Marc Zyngier
  2021-07-06  3:09 ` [PATCH 8/9] irqchip: Add Loongson Extended I/O " Huacai Chen
  2021-07-06  3:09 ` [PATCH 9/9] irqchip: Add Loongson PCH LPC " Huacai Chen
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. This patch add LoongArch CPU interrupt controller support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/Kconfig             | 10 ++++
 drivers/irqchip/Makefile            |  1 +
 drivers/irqchip/irq-loongarch-cpu.c | 87 +++++++++++++++++++++++++++++
 3 files changed, 98 insertions(+)
 create mode 100644 drivers/irqchip/irq-loongarch-cpu.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 084bc4c2eebd..443c3a7a0cc1 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -528,6 +528,16 @@ config EXYNOS_IRQ_COMBINER
 	  Say yes here to add support for the IRQ combiner devices embedded
 	  in Samsung Exynos chips.
 
+config IRQ_LOONGARCH_CPU
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+	select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+	help
+	  Support for the LoongArch CPU Interrupt Controller. For details of
+	  irq chip hierarchy on LoongArch platforms please read the document
+	  Documentation/loongarch/irq-chip-model.rst.
+
 config LOONGSON_LIOINTC
 	bool "Loongson Local I/O Interrupt Controller"
 	depends on MACH_LOONGSON64
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index f88cbf36a9d2..4e34eebe180b 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_LS1X_IRQ)			+= irq-ls1x.o
 obj-$(CONFIG_TI_SCI_INTR_IRQCHIP)	+= irq-ti-sci-intr.o
 obj-$(CONFIG_TI_SCI_INTA_IRQCHIP)	+= irq-ti-sci-inta.o
 obj-$(CONFIG_TI_PRUSS_INTC)		+= irq-pruss-intc.o
+obj-$(CONFIG_IRQ_LOONGARCH_CPU)		+= irq-loongarch-cpu.o
 obj-$(CONFIG_LOONGSON_LIOINTC)		+= irq-loongson-liointc.o
 obj-$(CONFIG_LOONGSON_HTPIC)		+= irq-loongson-htpic.o
 obj-$(CONFIG_LOONGSON_HTVEC)		+= irq-loongson-htvec.o
diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
new file mode 100644
index 000000000000..918d61a5a980
--- /dev/null
+++ b/drivers/irqchip/irq-loongarch-cpu.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Loongson Technologies, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+
+#include <asm/setup.h>
+#include <asm/loongarchregs.h>
+
+static struct irq_domain *irq_domain;
+
+static inline void unmask_loongarch_irq(struct irq_data *d)
+{
+	set_csr_ecfg(ECFGF(d->hwirq));
+}
+
+static inline void mask_loongarch_irq(struct irq_data *d)
+{
+	clear_csr_ecfg(ECFGF(d->hwirq));
+}
+
+#define enable_loongarch_irq  unmask_loongarch_irq
+#define disable_loongarch_irq mask_loongarch_irq
+
+static struct irq_chip loongarch_cpu_irq_controller = {
+	.name		= "LoongArch",
+	.irq_ack	= mask_loongarch_irq,
+	.irq_mask	= mask_loongarch_irq,
+	.irq_mask_ack	= mask_loongarch_irq,
+	.irq_unmask	= unmask_loongarch_irq,
+	.irq_eoi	= unmask_loongarch_irq,
+	.irq_enable	= enable_loongarch_irq,
+	.irq_disable	= disable_loongarch_irq,
+};
+
+asmlinkage void __weak plat_irq_dispatch(int irq)
+{
+	do_IRQ(irq_linear_revmap(irq_domain, irq));
+}
+
+static int loongarch_cpu_intc_map(struct irq_domain *d, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	struct irq_chip *chip;
+
+	chip = &loongarch_cpu_irq_controller;
+	set_vi_handler(EXCCODE_INT_START + hwirq, plat_irq_dispatch);
+	irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
+	.map = loongarch_cpu_intc_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+
+int __init loongarch_cpu_irq_init(struct device_node *of_node, struct device_node *parent)
+{
+	int i;
+
+	/* Mask interrupts. */
+	clear_csr_ecfg(ECFG0_IM);
+	clear_csr_estat(ESTATF_IP);
+
+	irq_alloc_descs(-1, LOONGSON_CPU_IRQ_BASE, EXCCODE_INT_NUM, 0);
+
+	for (i = LOONGSON_CPU_IRQ_BASE; i <= LOONGSON_CPU_LAST_IRQ; i++)
+		irq_set_noprobe(i);
+
+	irq_domain = irq_domain_add_legacy(of_node, EXCCODE_INT_NUM,
+		     LOONGSON_CPU_IRQ_BASE, 0, &loongarch_cpu_intc_irq_domain_ops, NULL);
+
+	if (!irq_domain)
+		panic("Failed to add irqdomain for loongarch CPU");
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(cpu_intc, "loongson,cpu-interrupt-controller", loongarch_cpu_irq_init);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 8/9] irqchip: Add Loongson Extended I/O interrupt controller support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (6 preceding siblings ...)
  2021-07-06  3:09 ` [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support Huacai Chen
@ 2021-07-06  3:09 ` Huacai Chen
  2021-07-08 20:53   ` kernel test robot
  2021-07-06  3:09 ` [PATCH 9/9] irqchip: Add Loongson PCH LPC " Huacai Chen
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. This patch add Loongson Extended I/O CPU interrupt controller
support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/Kconfig                |   9 +
 drivers/irqchip/Makefile               |   1 +
 drivers/irqchip/irq-loongson-eiointc.c | 308 +++++++++++++++++++++++++
 include/linux/cpuhotplug.h             |   1 +
 4 files changed, 319 insertions(+)
 create mode 100644 drivers/irqchip/irq-loongson-eiointc.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 443c3a7a0cc1..895b19fcea59 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -547,6 +547,15 @@ config LOONGSON_LIOINTC
 	help
 	  Support for the Loongson Local I/O Interrupt Controller.
 
+config LOONGSON_EIOINTC
+	bool "Loongson Extend I/O Interrupt Controller"
+	depends on MACH_LOONGSON64
+	default MACH_LOONGSON64
+	select IRQ_DOMAIN_HIERARCHY
+	select GENERIC_IRQ_CHIP
+	help
+	  Support for the Loongson3 Extend I/O Interrupt Vector Controller.
+
 config LOONGSON_HTPIC
 	bool "Loongson3 HyperTransport PIC Controller"
 	depends on (MACH_LOONGSON64 && MIPS)
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4e34eebe180b..eb3fdc6fe808 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_TI_SCI_INTA_IRQCHIP)	+= irq-ti-sci-inta.o
 obj-$(CONFIG_TI_PRUSS_INTC)		+= irq-pruss-intc.o
 obj-$(CONFIG_IRQ_LOONGARCH_CPU)		+= irq-loongarch-cpu.o
 obj-$(CONFIG_LOONGSON_LIOINTC)		+= irq-loongson-liointc.o
+obj-$(CONFIG_LOONGSON_EIOINTC)		+= irq-loongson-eiointc.o
 obj-$(CONFIG_LOONGSON_HTPIC)		+= irq-loongson-htpic.o
 obj-$(CONFIG_LOONGSON_HTVEC)		+= irq-loongson-htvec.o
 obj-$(CONFIG_LOONGSON_PCH_PIC)		+= irq-loongson-pch-pic.o
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
new file mode 100644
index 000000000000..e1590a128284
--- /dev/null
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2020, Jianmin Lv <lvjianmin@loongson.cn>
+ *  Loongson Extend I/O Interrupt Vector support
+ */
+
+#define pr_fmt(fmt) "eiointc: " fmt
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/syscore_ops.h>
+
+#define EIOINTC_REG_NODEMAP	0x14a0
+#define EIOINTC_REG_IPMAP	0x14c0
+#define EIOINTC_REG_ENABLE	0x1600
+#define EIOINTC_REG_BOUNCE	0x1680
+#define EIOINTC_REG_ISR		0x1800
+#define EIOINTC_REG_ROUTE	0x1c00
+
+#define VEC_REG_COUNT		4
+#define VEC_COUNT_PER_REG	64
+#define VEC_COUNT		(VEC_REG_COUNT * VEC_COUNT_PER_REG)
+#define VEC_REG_IDX(irq_id)	((irq_id) / VEC_COUNT_PER_REG)
+#define VEC_REG_BIT(irq_id)     ((irq_id) % VEC_COUNT_PER_REG)
+
+struct eiointc_priv {
+	struct fwnode_handle	*domain_handle;
+	struct irq_domain	*eiointc_domain;
+	u32			eiointc_en[VEC_COUNT/32];
+};
+
+struct eiointc_priv *eiointc_priv;
+
+static void eiointc_set_irq_route(int pos, unsigned int cpu)
+{
+	int node, cpu_node, route_node;
+	unsigned char coremap[MAX_NUMNODES];
+	uint32_t pos_off, data, data_byte, data_mask;
+
+	pos_off = pos & ~3;
+	data_byte = pos & 3;
+	data_mask = ~BIT_MASK(data_byte) & 0xf;
+
+	memset(coremap, 0, sizeof(unsigned char) * MAX_NUMNODES);
+
+	/* Calculate node and coremap of target irq */
+	cpu_node = cpu_to_node(cpu);
+	coremap[cpu_node] |= (1 << (topology_core_id(cpu)));
+
+	for_each_online_node(node) {
+		data = 0ULL;
+
+		/* Node 0 is in charge of inter-node interrupt dispatch */
+		route_node = (node == 0) ? cpu_node : node;
+		data |= ((coremap[node] | (route_node << 4)) << (data_byte * 8));
+
+		csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, node);
+	}
+}
+
+static DEFINE_SPINLOCK(affinity_lock);
+
+int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
+			  bool force)
+{
+	unsigned int cpu;
+	unsigned long flags;
+	uint32_t vector, pos_off;
+
+	if (!IS_ENABLED(CONFIG_SMP))
+		return -EPERM;
+
+	spin_lock_irqsave(&affinity_lock, flags);
+
+	if (!cpumask_intersects(affinity, cpu_online_mask)) {
+		spin_unlock_irqrestore(&affinity_lock, flags);
+		return -EINVAL;
+	}
+	cpu = cpumask_first_and(affinity, cpu_online_mask);
+
+	/*
+	 * Control interrupt enable or disalbe through cpu 0
+	 * which is reponsible for dispatching interrupts.
+	 */
+	vector = d->hwirq;
+	pos_off = vector >> 5;
+
+	csr_any_send(EIOINTC_REG_ENABLE + (pos_off << 2),
+		     eiointc_priv->eiointc_en[pos_off] & (~((1 << (vector & 0x1F)))), 0x0, 0);
+
+	eiointc_set_irq_route(vector, cpu);
+	csr_any_send(EIOINTC_REG_ENABLE + (pos_off << 2),
+		     eiointc_priv->eiointc_en[pos_off], 0x0, 0);
+	irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+	spin_unlock_irqrestore(&affinity_lock, flags);
+
+	return IRQ_SET_MASK_OK;
+}
+
+static int eiointc_router_init(unsigned int cpu)
+{
+	int i, bit;
+	uint32_t data;
+	uint32_t node = cpu_to_node(cpu);
+
+	if (cpu == cpumask_first(cpumask_of_node(node))) {
+		eiointc_enable();
+
+		for (i = 0; i < VEC_COUNT / 32; i++) {
+			data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2)));
+			iocsr_writel(data, EIOINTC_REG_NODEMAP + i * 4);
+		}
+
+		for (i = 0; i < VEC_COUNT / 32 / 4; i++) {
+			data = 0x02020202; /* Route to IP3 */
+			iocsr_writel(data, EIOINTC_REG_IPMAP + i * 4);
+		}
+
+		for (i = 0; i < VEC_COUNT / 4; i++) {
+			/* Route to Node-0 Core-0 */
+			bit = BIT(cpu_logical_map(0));
+			data = bit | (bit << 8) | (bit << 16) | (bit << 24);
+			iocsr_writel(data, EIOINTC_REG_ROUTE + i * 4);
+		}
+
+		for (i = 0; i < VEC_COUNT / 32; i++) {
+			data = 0xffffffff;
+			iocsr_writel(data, EIOINTC_REG_ENABLE + i * 4);
+			iocsr_writel(data, EIOINTC_REG_BOUNCE + i * 4);
+		}
+	}
+
+	return 0;
+}
+
+static void eiointc_irq_dispatch(struct irq_desc *desc)
+{
+	int i;
+	u64 pending;
+	bool handled = false;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct eiointc_priv *priv = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < VEC_REG_COUNT; i++) {
+		pending = iocsr_readq(EIOINTC_REG_ISR + (i << 3));
+		iocsr_writeq(pending, EIOINTC_REG_ISR + (i << 3));
+		while (pending) {
+			int bit = __ffs(pending);
+			int virq = irq_linear_revmap(priv->eiointc_domain, bit + VEC_COUNT_PER_REG * i);
+
+			generic_handle_irq(virq);
+			pending &= ~BIT(bit);
+			handled = true;
+		}
+	}
+
+	if (!handled)
+		spurious_interrupt();
+
+	chained_irq_exit(chip, desc);
+}
+
+static void eiointc_ack_irq(struct irq_data *d)
+{
+}
+
+static void eiointc_mask_irq(struct irq_data *d)
+{
+}
+
+static void eiointc_unmask_irq(struct irq_data *d)
+{
+}
+
+static struct irq_chip eiointc_irq_chip = {
+	.name			= "EIOINTC",
+	.irq_ack		= eiointc_ack_irq,
+	.irq_mask		= eiointc_mask_irq,
+	.irq_unmask		= eiointc_unmask_irq,
+	.irq_set_affinity	= eiointc_set_irq_affinity,
+};
+
+static int eiointc_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				unsigned int nr_irqs, void *arg)
+{
+	int ret;
+	unsigned int i, type;
+	unsigned long hwirq = 0;
+	struct eiointc *priv = domain->host_data;
+
+	ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip,
+					priv, handle_edge_irq, NULL, NULL);
+	}
+
+	return 0;
+}
+
+static void eiointc_domain_free(struct irq_domain *domain, unsigned int virq,
+				unsigned int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+
+		irq_set_handler(virq + i, NULL);
+		irq_domain_reset_irq_data(d);
+	}
+}
+
+static const struct irq_domain_ops eiointc_domain_ops = {
+	.translate	= irq_domain_translate_onecell,
+	.alloc		= eiointc_domain_alloc,
+	.free		= eiointc_domain_free,
+};
+
+static int eiointc_suspend(void)
+{
+	return 0;
+}
+
+static void eiointc_resume(void)
+{
+	int i;
+	struct irq_desc *desc;
+
+	/* init irq en bitmap */
+	for (i = 0; i < VEC_COUNT / 32; i++)
+		eiointc_priv->eiointc_en[i] = 0xffffffff;
+
+	eiointc_router_init(0);
+
+	for (i = 0; i < NR_IRQS; i++) {
+		desc = irq_to_desc(i);
+		if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq)
+			eiointc_set_irq_affinity(&desc->irq_data,
+						 desc->irq_data.common->affinity, 0);
+	}
+}
+
+static struct syscore_ops eiointc_syscore_ops = {
+	.suspend = eiointc_suspend,
+	.resume = eiointc_resume,
+};
+
+struct fwnode_handle *eiointc_acpi_init(struct acpi_madt_eio_pic *acpi_eiointc)
+{
+	int i, parent_irq;
+	struct eiointc_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
+	if (!priv->domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		goto out_free_priv;
+	}
+
+	/* 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_priv;
+	}
+
+	/* init irq en bitmap */
+	for (i = 0; i < VEC_COUNT/32; i++)
+		priv->eiointc_en[i] = 0xffffffff;
+
+	eiointc_priv = priv;
+
+	eiointc_router_init(0);
+
+	parent_irq = LOONGSON_CPU_IRQ_BASE + 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);
+
+	return eiointc_priv->domain_handle;
+
+out_free_priv:
+	priv->domain_handle = NULL;
+	kfree(priv);
+
+	return NULL;
+}
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 47e13582d9fc..45244c1ded6a 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -105,6 +105,7 @@ enum cpuhp_state {
 	CPUHP_AP_IRQ_BCM2836_STARTING,
 	CPUHP_AP_IRQ_MIPS_GIC_STARTING,
 	CPUHP_AP_IRQ_RISCV_STARTING,
+	CPUHP_AP_IRQ_LOONGARCH_STARTING,
 	CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
 	CPUHP_AP_ARM_MVEBU_COHERENCY,
 	CPUHP_AP_MICROCODE_LOADER,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 9/9] irqchip: Add Loongson PCH LPC controller support
  2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
                   ` (7 preceding siblings ...)
  2021-07-06  3:09 ` [PATCH 8/9] irqchip: Add Loongson Extended I/O " Huacai Chen
@ 2021-07-06  3:09 ` Huacai Chen
  2021-07-08 22:27   ` kernel test robot
  8 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-06  3:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang, Huacai Chen

We are preparing to add new Loongson (based on LoongArch, not MIPS)
support. This patch add Loongson PCH LPC interrupt controller support.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/irqchip/Kconfig                |   8 +
 drivers/irqchip/Makefile               |   1 +
 drivers/irqchip/irq-loongson-pch-lpc.c | 204 +++++++++++++++++++++++++
 3 files changed, 213 insertions(+)
 create mode 100644 drivers/irqchip/irq-loongson-pch-lpc.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 895b19fcea59..2ba0f341d976 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -592,6 +592,14 @@ config LOONGSON_PCH_MSI
 	help
 	  Support for the Loongson PCH MSI Controller.
 
+config LOONGSON_PCH_LPC
+	bool "Loongson PCH LPC Controller"
+	depends on MACH_LOONGSON64
+	default MACH_LOONGSON64
+	select IRQ_DOMAIN_HIERARCHY
+	help
+	  Support for the Loongson PCH LPC Controller.
+
 config MST_IRQ
 	bool "MStar Interrupt Controller"
 	depends on ARCH_MEDIATEK || ARCH_MSTARV7 || COMPILE_TEST
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index eb3fdc6fe808..6fd07980fa47 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -112,6 +112,7 @@ obj-$(CONFIG_LOONGSON_HTPIC)		+= irq-loongson-htpic.o
 obj-$(CONFIG_LOONGSON_HTVEC)		+= irq-loongson-htvec.o
 obj-$(CONFIG_LOONGSON_PCH_PIC)		+= irq-loongson-pch-pic.o
 obj-$(CONFIG_LOONGSON_PCH_MSI)		+= irq-loongson-pch-msi.o
+obj-$(CONFIG_LOONGSON_PCH_LPC)		+= irq-loongson-pch-lpc.o
 obj-$(CONFIG_MST_IRQ)			+= irq-mst-intc.o
 obj-$(CONFIG_SL28CPLD_INTC)		+= irq-sl28cpld.o
 obj-$(CONFIG_MACH_REALTEK_RTL)		+= irq-realtek-rtl.o
diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c
new file mode 100644
index 000000000000..e0ec073b1ec2
--- /dev/null
+++ b/drivers/irqchip/irq-loongson-pch-lpc.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2020, Jianmin Lv <lvjianmin@loongson.cn>
+ *  Loongson LPC support
+ */
+
+#define pr_fmt(fmt) "lpc: " fmt
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/syscore_ops.h>
+
+/* Registers */
+#define LPC_INT_CTL		0x00
+#define LPC_INT_ENA		0x04
+#define LPC_INT_STS		0x08
+#define LPC_INT_CLR		0x0c
+#define LPC_INT_POL		0x10
+#define LPC_COUNT		16
+
+struct pch_lpc {
+	void __iomem		*base;
+	struct irq_domain	*lpc_domain;
+	struct fwnode_handle	*domain_handle;
+	raw_spinlock_t		lpc_lock;
+	u32			saved_reg_ctl;
+	u32			saved_reg_ena;
+	u32			saved_reg_pol;
+};
+
+struct pch_lpc *pch_lpc_priv;
+
+static void ack_lpc_irq(struct irq_data *d)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pch_lpc_priv->lpc_lock, flags);
+	writel(0x1 << d->irq, pch_lpc_priv->base + LPC_INT_CLR);
+	raw_spin_unlock_irqrestore(&pch_lpc_priv->lpc_lock, flags);
+}
+static void mask_lpc_irq(struct irq_data *d)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pch_lpc_priv->lpc_lock, flags);
+	writel(readl(pch_lpc_priv->base + LPC_INT_ENA) & (~(0x1 << (d->irq))),
+			pch_lpc_priv->base + LPC_INT_ENA);
+	raw_spin_unlock_irqrestore(&pch_lpc_priv->lpc_lock, flags);
+}
+
+static void mask_ack_lpc_irq(struct irq_data *d)
+{
+}
+
+static void unmask_lpc_irq(struct irq_data *d)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pch_lpc_priv->lpc_lock, flags);
+	writel(readl(pch_lpc_priv->base + LPC_INT_ENA) | (0x1 << (d->irq)),
+			pch_lpc_priv->base + LPC_INT_ENA);
+	raw_spin_unlock_irqrestore(&pch_lpc_priv->lpc_lock, flags);
+}
+
+static struct irq_chip pch_lpc_irq_chip = {
+	.name			= "PCH LPC",
+	.irq_mask		= mask_lpc_irq,
+	.irq_unmask		= unmask_lpc_irq,
+	.irq_ack		= ack_lpc_irq,
+	.irq_mask_ack		= mask_ack_lpc_irq,
+	.irq_eoi		= unmask_lpc_irq,
+	.flags			= IRQCHIP_SKIP_SET_WAKE,
+};
+
+static void lpc_irq_dispatch(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	u32 pending;
+
+	chained_irq_enter(chip, desc);
+
+	pending = readl(pch_lpc_priv->base + LPC_INT_ENA);
+	pending &= readl(pch_lpc_priv->base + LPC_INT_STS);
+	if (!pending)
+		spurious_interrupt();
+
+	while (pending) {
+		int bit = __ffs(pending);
+
+		generic_handle_irq(bit);
+		pending &= ~BIT(bit);
+	}
+	chained_irq_exit(chip, desc);
+}
+
+static int pch_lpc_map(struct irq_domain *d, unsigned int irq,
+			irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &pch_lpc_irq_chip, handle_level_irq);
+	return 0;
+}
+
+static const struct irq_domain_ops pch_lpc_domain_ops = {
+	.map = pch_lpc_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static void pch_lpc_reset(struct pch_lpc *priv)
+{
+	/* Enable the LPC interrupt, bit31: en  bit30: edge */
+	writel(0x80000000, priv->base + LPC_INT_CTL);
+	writel(0, priv->base + LPC_INT_ENA);
+	/* Clear all 18-bit interrpt bit */
+	writel(0x3ffff, priv->base + LPC_INT_CLR);
+}
+
+static int pch_lpc_disabled(struct pch_lpc *priv)
+{
+	return (readl(priv->base + LPC_INT_ENA) == 0xffffffff) &&
+			(readl(priv->base + LPC_INT_STS) == 0xffffffff);
+}
+
+static int pch_lpc_suspend(void)
+{
+	pch_lpc_priv->saved_reg_ctl = readl(pch_lpc_priv->base + LPC_INT_CTL);
+	pch_lpc_priv->saved_reg_ena = readl(pch_lpc_priv->base + LPC_INT_ENA);
+	pch_lpc_priv->saved_reg_pol = readl(pch_lpc_priv->base + LPC_INT_POL);
+	return 0;
+}
+
+static void pch_lpc_resume(void)
+{
+	writel(pch_lpc_priv->saved_reg_ctl, pch_lpc_priv->base + LPC_INT_CTL);
+	writel(pch_lpc_priv->saved_reg_ena, pch_lpc_priv->base + LPC_INT_ENA);
+	writel(pch_lpc_priv->saved_reg_pol, pch_lpc_priv->base + LPC_INT_POL);
+}
+
+static struct syscore_ops pch_lpc_syscore_ops = {
+	.suspend = pch_lpc_suspend,
+	.resume = pch_lpc_resume,
+};
+
+struct fwnode_handle *pch_lpc_acpi_init(struct fwnode_handle *parent,
+					struct acpi_madt_lpc_pic *acpi_pchlpc)
+{
+	int parent_irq;
+	struct pch_lpc *priv;
+	struct irq_fwspec fwspec;
+
+	if (!acpi_pchlpc)
+		return NULL;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return NULL;
+
+	raw_spin_lock_init(&priv->lpc_lock);
+
+	priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size);
+	if (!priv->base)
+		goto free_priv;
+
+	if (pch_lpc_disabled(priv)) {
+		pr_err("Failed to get LPC status\n");
+		goto iounmap_base;
+	}
+
+	priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
+	if (!priv->domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		goto iounmap_base;
+	}
+	priv->lpc_domain = irq_domain_add_legacy(NULL, LPC_COUNT, 0, 0,
+						&pch_lpc_domain_ops,
+						priv);
+	if (!priv->lpc_domain) {
+		pr_err("Failed to create IRQ domain\n");
+		goto iounmap_base;
+	}
+	pch_lpc_reset(priv);
+
+	fwspec.fwnode = parent;
+	fwspec.param[0] = GSI_MIN_PCH_IRQ + acpi_pchlpc->cascade;
+	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;
+
+	register_syscore_ops(&pch_lpc_syscore_ops);
+
+	return priv->domain_handle;
+
+iounmap_base:
+	iounmap(priv->base);
+free_priv:
+	kfree(priv);
+
+	return NULL;
+}
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support
  2021-07-06  3:08 ` [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support Huacai Chen
@ 2021-07-06 13:06   ` Marc Zyngier
  2021-07-09  3:00     ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-07-06 13:06 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Thomas Gleixner, linux-kernel, Xuefeng Li, Huacai Chen,
	Jiaxun Yang, Chen Zhu

On Tue, 06 Jul 2021 04:08:57 +0100,
Huacai Chen <chenhuacai@loongson.cn> wrote:
> 
> Edge-triggered mode and level-triggered mode need different handlers,
> and edge-triggered mode need a specific ack operation. So improve it.
>

Is this a fix? How does it work currently?


> Signed-off-by: Chen Zhu <zhuchen@loongson.cn>
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  drivers/irqchip/irq-loongson-pch-pic.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> index f790ca6d78aa..a4eb8a2181c7 100644
> --- a/drivers/irqchip/irq-loongson-pch-pic.c
> +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> @@ -92,18 +92,22 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
>  	case IRQ_TYPE_EDGE_RISING:
>  		pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
>  		pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
> +		irq_set_handler_locked(d, handle_edge_irq);
>  		break;
>  	case IRQ_TYPE_EDGE_FALLING:
>  		pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
>  		pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
> +		irq_set_handler_locked(d, handle_edge_irq);
>  		break;
>  	case IRQ_TYPE_LEVEL_HIGH:
>  		pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
>  		pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
> +		irq_set_handler_locked(d, handle_level_irq);
>  		break;
>  	case IRQ_TYPE_LEVEL_LOW:
>  		pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
>  		pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
> +		irq_set_handler_locked(d, handle_level_irq);

You are changing the flow for the whole hierarchy. Are all the
irqchips in the stack supporting this?

>  		break;
>  	default:
>  		ret = -EINVAL;
> @@ -113,11 +117,24 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
>  	return ret;
>  }
>  
> +static void pch_pic_ack_irq(struct irq_data *d)
> +{
> +	unsigned int reg;
> +	struct pch_pic *priv = irq_data_get_irq_chip_data(d);
> +
> +	reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
> +	if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
> +		writel(BIT(PIC_REG_BIT(d->hwirq)),
> +			priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
> +	}
> +	irq_chip_ack_parent(d);
> +}
> +
>  static struct irq_chip pch_pic_irq_chip = {
>  	.name			= "PCH PIC",
>  	.irq_mask		= pch_pic_mask_irq,
>  	.irq_unmask		= pch_pic_unmask_irq,
> -	.irq_ack		= irq_chip_ack_parent,
> +	.irq_ack		= pch_pic_ack_irq,
>  	.irq_set_affinity	= irq_chip_set_affinity_parent,
>  	.irq_set_type		= pch_pic_set_type,
>  };

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-07-06  3:08 ` [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support Huacai Chen
@ 2021-07-06 13:10   ` Marc Zyngier
  2021-07-07  4:50     ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-07-06 13:10 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Thomas Gleixner, linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang

On Tue, 06 Jul 2021 04:08:58 +0100,
Huacai Chen <chenhuacai@loongson.cn> wrote:
> 
> We are preparing to add new Loongson (based on LoongArch, not MIPS)
> support. LoongArch use ACPI other than DT as its boot protocol, so
> add ACPI init support.
> 
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  drivers/irqchip/irq-loongson-pch-pic.c | 120 ++++++++++++++++++++++++-
>  1 file changed, 119 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> index a4eb8a2181c7..62382611995b 100644
> --- a/drivers/irqchip/irq-loongson-pch-pic.c
> +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
>   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *			Jianmin Lv <lvjianmin@loongson.cn>
> + *			Huacai Chen <chenhuacai@loongson.cn>

Please drop this change. I'm in a position where I can verify who owns
the copyright to this code, and I seriously doubt that 100 lines of
boilerplate probing code give you any right over it.

>   *  Loongson PCH PIC support
>   */
>  
> @@ -15,6 +17,7 @@
>  #include <linux/of_address.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_platform.h>
> +#include <linux/syscore_ops.h>
>  
>  /* Registers */
>  #define PCH_PIC_MASK		0x20
> @@ -32,14 +35,23 @@
>  #define PIC_COUNT		(PIC_COUNT_PER_REG * PIC_REG_COUNT)
>  #define PIC_REG_IDX(irq_id)	((irq_id) / PIC_COUNT_PER_REG)
>  #define PIC_REG_BIT(irq_id)	((irq_id) % PIC_COUNT_PER_REG)
> +#define PCH_PIC_SIZE		0x400
> +
> +static int nr_pch_pics;
>  
>  struct pch_pic {
>  	void __iomem		*base;
>  	struct irq_domain	*pic_domain;
> +	struct fwnode_handle	*domain_handle;
>  	u32			ht_vec_base;
>  	raw_spinlock_t		pic_lock;
> +	u32			saved_vec_en[PIC_REG_COUNT];
> +	u32			saved_vec_pol[PIC_REG_COUNT];
> +	u32			saved_vec_edge[PIC_REG_COUNT];
>  };
>  
> +struct pch_pic *pch_pic_priv[4];
> +
>  static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
>  {
>  	u32 reg;
> @@ -137,6 +149,7 @@ static struct irq_chip pch_pic_irq_chip = {
>  	.irq_ack		= pch_pic_ack_irq,
>  	.irq_set_affinity	= irq_chip_set_affinity_parent,
>  	.irq_set_type		= pch_pic_set_type,
> +	.flags			= IRQCHIP_SKIP_SET_WAKE,
>  };
>  
>  static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
> @@ -180,7 +193,7 @@ static void pch_pic_reset(struct pch_pic *priv)
>  	int i;
>  
>  	for (i = 0; i < PIC_COUNT; i++) {
> -		/* Write vectored ID */
> +		/* Write vector ID */
>  		writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
>  		/* Hardcode route to HT0 Lo */
>  		writeb(1, priv->base + PCH_INT_ROUTE(i));
> @@ -198,6 +211,48 @@ static void pch_pic_reset(struct pch_pic *priv)
>  	}
>  }
>  
> +static int pch_pic_suspend(void)
> +{
> +	int i, j;
> +
> +	for (i = 0; i < nr_pch_pics; i++) {
> +		for (j = 0; j < PIC_REG_COUNT; j++) {
> +			pch_pic_priv[i]->saved_vec_pol[j] =
> +				readl(pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> +			pch_pic_priv[i]->saved_vec_edge[j] =
> +				readl(pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> +			pch_pic_priv[i]->saved_vec_en[j] =
> +				readl(pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void pch_pic_resume(void)
> +{
> +	int i, j;
> +
> +	for (i = 0; i < nr_pch_pics; i++) {
> +		pch_pic_reset(pch_pic_priv[i]);
> +		for (j = 0; j < PIC_REG_COUNT; j++) {
> +			writel(pch_pic_priv[i]->saved_vec_pol[j],
> +					pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> +			writel(pch_pic_priv[i]->saved_vec_edge[j],
> +					pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> +			writel(pch_pic_priv[i]->saved_vec_en[j],
> +					pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> +		}
> +	}
> +}
> +
> +static struct syscore_ops pch_pic_syscore_ops = {
> +	.suspend =  pch_pic_suspend,
> +	.resume =  pch_pic_resume,
> +};

None of this has anything to do with what is described in the commit
message. Please move this into its own patch.

> +
> +#ifdef CONFIG_OF
> +
>  static int pch_pic_of_init(struct device_node *node,
>  				struct device_node *parent)
>  {
> @@ -242,6 +297,9 @@ static int pch_pic_of_init(struct device_node *node,
>  	}
>  
>  	pch_pic_reset(priv);
> +	pch_pic_priv[0] = priv;
> +
> +	register_syscore_ops(&pch_pic_syscore_ops);
>  
>  	return 0;
>  
> @@ -254,3 +312,63 @@ static int pch_pic_of_init(struct device_node *node,
>  }
>  
>  IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init);
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +
> +struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
> +					struct acpi_madt_bio_pic *acpi_pchpic)
> +{
> +	int count;
> +	struct pch_pic *priv;
> +	struct irq_domain *parent_domain;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return NULL;
> +
> +	raw_spin_lock_init(&priv->pic_lock);
> +	priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
> +	if (!priv->base)
> +		goto free_priv;
> +
> +	priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
> +	if (!priv->domain_handle) {
> +		pr_err("Unable to allocate domain handle\n");
> +		goto iounmap_base;
> +	}
> +
> +	priv->ht_vec_base = acpi_pchpic->gsi_base;
> +	count = ((readq(priv->base) >> 48) & 0xff) + 1;
> +	parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> +	if (!parent_domain) {
> +		pr_err("Failed to find the parent domain\n");
> +		goto iounmap_base;
> +	}
> +
> +	priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
> +						count, priv->domain_handle,
> +						&pch_pic_domain_ops, priv);
> +
> +	if (!priv->pic_domain) {
> +		pr_err("Failed to create IRQ domain\n");
> +		goto iounmap_base;
> +	}
> +
> +	pch_pic_reset(priv);
> +	pch_pic_priv[nr_pch_pics++] = priv;
> +
> +	register_syscore_ops(&pch_pic_syscore_ops);
> +
> +	return priv->domain_handle;
> +
> +iounmap_base:
> +	iounmap(priv->base);
> +free_priv:
> +	kfree(priv);
> +
> +	return NULL;
> +}
> +
> +#endif

A lot of this code is common with its OF counterpart. How about making
this logic common?

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] irqchip/loongson-pch-msi: Add ACPI init support
  2021-07-06  3:08 ` [PATCH 4/9] irqchip/loongson-pch-msi: " Huacai Chen
@ 2021-07-06 13:12   ` Marc Zyngier
  2021-07-07  4:51     ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-07-06 13:12 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Thomas Gleixner, linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang

On Tue, 06 Jul 2021 04:08:59 +0100,
Huacai Chen <chenhuacai@loongson.cn> wrote:
> 
> We are preparing to add new Loongson (based on LoongArch, not MIPS)
> support. LoongArch use ACPI other than DT as its boot protocol, so
> add ACPI init support.
> 
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  drivers/irqchip/irq-loongson-pch-msi.c | 69 ++++++++++++++++++++++++--
>  1 file changed, 64 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
> index 32562b7e681b..adfa30046f0a 100644
> --- a/drivers/irqchip/irq-loongson-pch-msi.c
> +++ b/drivers/irqchip/irq-loongson-pch-msi.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
>   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *			Jianmin Lv <lvjianmin@loongson.cn>
> + *			Huacai Chen <chenhuacai@loongson.cn>

Same thing as the previous patch: drop it.

>   *  Loongson PCH MSI support
>   */
>  
> @@ -21,6 +23,7 @@ struct pch_msi_data {
>  	u32		irq_first;	/* The vector number that MSIs starts */
>  	u32		num_irqs;	/* The number of vectors for MSIs */
>  	unsigned long	*msi_map;
> +	struct fwnode_handle *domain_handle;
>  };
>  
>  static void pch_msi_mask_msi_irq(struct irq_data *d)
> @@ -159,7 +162,12 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
>  {
>  	struct irq_domain *middle_domain, *msi_domain;
>  
> -	middle_domain = irq_domain_create_linear(of_node_to_fwnode(node),
> +	if (node)
> +		priv->domain_handle = of_node_to_fwnode(node);
> +	else
> +		priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
> +
> +	middle_domain = irq_domain_create_linear(priv->domain_handle,
>  						priv->num_irqs,
>  						&pch_msi_middle_domain_ops,
>  						priv);
> @@ -171,7 +179,7 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
>  	middle_domain->parent = parent;
>  	irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
>  
> -	msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
> +	msi_domain = pci_msi_create_irq_domain(priv->domain_handle,
>  					       &pch_msi_domain_info,
>  					       middle_domain);
>  	if (!msi_domain) {
> @@ -183,8 +191,9 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
>  	return 0;
>  }
>  
> -static int pch_msi_init(struct device_node *node,
> -			    struct device_node *parent)
> +#ifdef CONFIG_OF
> +
> +int pch_msi_of_init(struct device_node *node, struct device_node *parent)
>  {
>  	struct pch_msi_data *priv;
>  	struct irq_domain *parent_domain;
> @@ -247,4 +256,54 @@ static int pch_msi_init(struct device_node *node,
>  	return ret;
>  }
>  
> -IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init);
> +IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init);
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +
> +struct fwnode_handle *pch_msi_acpi_init(struct fwnode_handle *parent,
> +					struct acpi_madt_msi_pic *acpi_pchmsi)
> +{
> +	int ret;
> +	struct pch_msi_data *priv;
> +	struct irq_domain *parent_domain;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return NULL;
> +
> +	mutex_init(&priv->msi_map_lock);
> +
> +	priv->doorbell = acpi_pchmsi->msg_address;
> +	priv->irq_first = acpi_pchmsi->start;
> +	priv->num_irqs = acpi_pchmsi->count;
> +
> +	parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> +	if (!parent_domain) {
> +		pr_err("Failed to find the parent domain\n");
> +		return NULL;
> +	}
> +
> +	priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL);
> +	if (!priv->msi_map)
> +		goto err_priv;
> +
> +	pr_debug("Registering %d MSIs, starting at %d\n",
> +		 priv->num_irqs, priv->irq_first);
> +
> +	ret = pch_msi_init_domains(priv, NULL, parent_domain);
> +	if (ret)
> +		goto err_map;
> +
> +	return priv->domain_handle;
> +
> +err_map:
> +	kfree(priv->msi_map);
> +err_priv:
> +	kfree(priv);
> +
> +	return NULL;
> +}
> +
> +#endif

Same thing. You are pointlessly duplicating the logic.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] irqchip/loongson-htvec: Add ACPI init support
  2021-07-06  3:09 ` [PATCH 5/9] irqchip/loongson-htvec: " Huacai Chen
@ 2021-07-06 13:13   ` Marc Zyngier
  2021-07-07  4:52     ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-07-06 13:13 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Thomas Gleixner, linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang

On Tue, 06 Jul 2021 04:09:00 +0100,
Huacai Chen <chenhuacai@loongson.cn> wrote:
> 
> We are preparing to add new Loongson (based on LoongArch, not MIPS)
> support. LoongArch use ACPI other than DT as its boot protocol, so
> add ACPI init support.
> 
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  drivers/irqchip/irq-loongson-htvec.c | 102 ++++++++++++++++++++++++++-
>  1 file changed, 101 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c
> index 60a335d7e64e..69452d4a33c0 100644
> --- a/drivers/irqchip/irq-loongson-htvec.c
> +++ b/drivers/irqchip/irq-loongson-htvec.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
>   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *			Jianmin Lv <lvjianmin@loongson.cn>
> + *			Huacai Chen <chenhuacai@loongson.cn>

Drop this, move the suspend/resume code to its own patch, de-duplicate
the probing code.

Do I sound like a stuck record?

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support
  2021-07-06  3:09 ` [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support Huacai Chen
@ 2021-07-06 13:21   ` Marc Zyngier
  2021-07-07  4:57     ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-07-06 13:21 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Thomas Gleixner, linux-kernel, Xuefeng Li, Huacai Chen, Jiaxun Yang

On Tue, 06 Jul 2021 04:09:02 +0100,
Huacai Chen <chenhuacai@loongson.cn> wrote:
> 
> We are preparing to add new Loongson (based on LoongArch, not MIPS)
> support. This patch add LoongArch CPU interrupt controller support.
> 
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  drivers/irqchip/Kconfig             | 10 ++++
>  drivers/irqchip/Makefile            |  1 +
>  drivers/irqchip/irq-loongarch-cpu.c | 87 +++++++++++++++++++++++++++++
>  3 files changed, 98 insertions(+)
>  create mode 100644 drivers/irqchip/irq-loongarch-cpu.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 084bc4c2eebd..443c3a7a0cc1 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -528,6 +528,16 @@ config EXYNOS_IRQ_COMBINER
>  	  Say yes here to add support for the IRQ combiner devices embedded
>  	  in Samsung Exynos chips.
>  
> +config IRQ_LOONGARCH_CPU
> +	bool
> +	select GENERIC_IRQ_CHIP
> +	select IRQ_DOMAIN
> +	select GENERIC_IRQ_EFFECTIVE_AFF_MASK
> +	help
> +	  Support for the LoongArch CPU Interrupt Controller. For details of
> +	  irq chip hierarchy on LoongArch platforms please read the document
> +	  Documentation/loongarch/irq-chip-model.rst.
> +
>  config LOONGSON_LIOINTC
>  	bool "Loongson Local I/O Interrupt Controller"
>  	depends on MACH_LOONGSON64
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index f88cbf36a9d2..4e34eebe180b 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -105,6 +105,7 @@ obj-$(CONFIG_LS1X_IRQ)			+= irq-ls1x.o
>  obj-$(CONFIG_TI_SCI_INTR_IRQCHIP)	+= irq-ti-sci-intr.o
>  obj-$(CONFIG_TI_SCI_INTA_IRQCHIP)	+= irq-ti-sci-inta.o
>  obj-$(CONFIG_TI_PRUSS_INTC)		+= irq-pruss-intc.o
> +obj-$(CONFIG_IRQ_LOONGARCH_CPU)		+= irq-loongarch-cpu.o
>  obj-$(CONFIG_LOONGSON_LIOINTC)		+= irq-loongson-liointc.o
>  obj-$(CONFIG_LOONGSON_HTPIC)		+= irq-loongson-htpic.o
>  obj-$(CONFIG_LOONGSON_HTVEC)		+= irq-loongson-htvec.o
> diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
> new file mode 100644
> index 000000000000..918d61a5a980
> --- /dev/null
> +++ b/drivers/irqchip/irq-loongarch-cpu.c
> @@ -0,0 +1,87 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Loongson Technologies, Inc.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/irq.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqdomain.h>
> +
> +#include <asm/setup.h>
> +#include <asm/loongarchregs.h>
> +
> +static struct irq_domain *irq_domain;
> +
> +static inline void unmask_loongarch_irq(struct irq_data *d)
> +{
> +	set_csr_ecfg(ECFGF(d->hwirq));
> +}
> +
> +static inline void mask_loongarch_irq(struct irq_data *d)
> +{
> +	clear_csr_ecfg(ECFGF(d->hwirq));
> +}
> +
> +#define enable_loongarch_irq  unmask_loongarch_irq
> +#define disable_loongarch_irq mask_loongarch_irq
> +
> +static struct irq_chip loongarch_cpu_irq_controller = {
> +	.name		= "LoongArch",
> +	.irq_ack	= mask_loongarch_irq,
> +	.irq_mask	= mask_loongarch_irq,
> +	.irq_mask_ack	= mask_loongarch_irq,
> +	.irq_unmask	= unmask_loongarch_irq,
> +	.irq_eoi	= unmask_loongarch_irq,
> +	.irq_enable	= enable_loongarch_irq,
> +	.irq_disable	= disable_loongarch_irq,

NAK. Clearly, you don't understand what these callbacks do.

> +};
> +
> +asmlinkage void __weak plat_irq_dispatch(int irq)
> +{
> +	do_IRQ(irq_linear_revmap(irq_domain, irq));
> +}

NAK. If you are going to add a new architecture to Linux, do not mimic
the MIPS brain-damage. Have your new architecture to support multiple
interrupt controllers from day one without the need to add these silly
weak symbols.

Move the low-level code such as this into the architecture code, and
use the existing domain abstractions.

> +
> +static int loongarch_cpu_intc_map(struct irq_domain *d, unsigned int irq,
> +			     irq_hw_number_t hwirq)
> +{
> +	struct irq_chip *chip;
> +
> +	chip = &loongarch_cpu_irq_controller;
> +	set_vi_handler(EXCCODE_INT_START + hwirq, plat_irq_dispatch);
> +	irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
> +	.map = loongarch_cpu_intc_map,
> +	.xlate = irq_domain_xlate_onecell,

Are all interrupts with the same trigger?

> +};
> +
> +
> +int __init loongarch_cpu_irq_init(struct device_node *of_node, struct device_node *parent)
> +{
> +	int i;
> +
> +	/* Mask interrupts. */
> +	clear_csr_ecfg(ECFG0_IM);
> +	clear_csr_estat(ESTATF_IP);
> +
> +	irq_alloc_descs(-1, LOONGSON_CPU_IRQ_BASE, EXCCODE_INT_NUM, 0);
> +
> +	for (i = LOONGSON_CPU_IRQ_BASE; i <= LOONGSON_CPU_LAST_IRQ; i++)
> +		irq_set_noprobe(i);
> +
> +	irq_domain = irq_domain_add_legacy(of_node, EXCCODE_INT_NUM,
> +		     LOONGSON_CPU_IRQ_BASE, 0, &loongarch_cpu_intc_irq_domain_ops, NULL);

Oh, the irony of using irq_domain_add_legacy() for a brand new
architecture...

> +
> +	if (!irq_domain)
> +		panic("Failed to add irqdomain for loongarch CPU");
> +
> +	return 0;
> +}
> +
> +IRQCHIP_DECLARE(cpu_intc, "loongson,cpu-interrupt-controller", loongarch_cpu_irq_init);

As it stands, this driver has zero chance of being merged. You
seriously need to move your low-level interrupt handling code into the
21st century.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-07-06 13:10   ` Marc Zyngier
@ 2021-07-07  4:50     ` Huacai Chen
  2021-08-12 12:23       ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-07  4:50 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Tue, Jul 6, 2021 at 9:10 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 06 Jul 2021 04:08:58 +0100,
> Huacai Chen <chenhuacai@loongson.cn> wrote:
> >
> > We are preparing to add new Loongson (based on LoongArch, not MIPS)
> > support. LoongArch use ACPI other than DT as its boot protocol, so
> > add ACPI init support.
> >
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  drivers/irqchip/irq-loongson-pch-pic.c | 120 ++++++++++++++++++++++++-
> >  1 file changed, 119 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> > index a4eb8a2181c7..62382611995b 100644
> > --- a/drivers/irqchip/irq-loongson-pch-pic.c
> > +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> > @@ -1,6 +1,8 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> >   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *                   Jianmin Lv <lvjianmin@loongson.cn>
> > + *                   Huacai Chen <chenhuacai@loongson.cn>
>
> Please drop this change. I'm in a position where I can verify who owns
> the copyright to this code, and I seriously doubt that 100 lines of
> boilerplate probing code give you any right over it.
OK, thanks.

>
> >   *  Loongson PCH PIC support
> >   */
> >
> > @@ -15,6 +17,7 @@
> >  #include <linux/of_address.h>
> >  #include <linux/of_irq.h>
> >  #include <linux/of_platform.h>
> > +#include <linux/syscore_ops.h>
> >
> >  /* Registers */
> >  #define PCH_PIC_MASK         0x20
> > @@ -32,14 +35,23 @@
> >  #define PIC_COUNT            (PIC_COUNT_PER_REG * PIC_REG_COUNT)
> >  #define PIC_REG_IDX(irq_id)  ((irq_id) / PIC_COUNT_PER_REG)
> >  #define PIC_REG_BIT(irq_id)  ((irq_id) % PIC_COUNT_PER_REG)
> > +#define PCH_PIC_SIZE         0x400
> > +
> > +static int nr_pch_pics;
> >
> >  struct pch_pic {
> >       void __iomem            *base;
> >       struct irq_domain       *pic_domain;
> > +     struct fwnode_handle    *domain_handle;
> >       u32                     ht_vec_base;
> >       raw_spinlock_t          pic_lock;
> > +     u32                     saved_vec_en[PIC_REG_COUNT];
> > +     u32                     saved_vec_pol[PIC_REG_COUNT];
> > +     u32                     saved_vec_edge[PIC_REG_COUNT];
> >  };
> >
> > +struct pch_pic *pch_pic_priv[4];
> > +
> >  static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
> >  {
> >       u32 reg;
> > @@ -137,6 +149,7 @@ static struct irq_chip pch_pic_irq_chip = {
> >       .irq_ack                = pch_pic_ack_irq,
> >       .irq_set_affinity       = irq_chip_set_affinity_parent,
> >       .irq_set_type           = pch_pic_set_type,
> > +     .flags                  = IRQCHIP_SKIP_SET_WAKE,
> >  };
> >
> >  static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
> > @@ -180,7 +193,7 @@ static void pch_pic_reset(struct pch_pic *priv)
> >       int i;
> >
> >       for (i = 0; i < PIC_COUNT; i++) {
> > -             /* Write vectored ID */
> > +             /* Write vector ID */
> >               writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
> >               /* Hardcode route to HT0 Lo */
> >               writeb(1, priv->base + PCH_INT_ROUTE(i));
> > @@ -198,6 +211,48 @@ static void pch_pic_reset(struct pch_pic *priv)
> >       }
> >  }
> >
> > +static int pch_pic_suspend(void)
> > +{
> > +     int i, j;
> > +
> > +     for (i = 0; i < nr_pch_pics; i++) {
> > +             for (j = 0; j < PIC_REG_COUNT; j++) {
> > +                     pch_pic_priv[i]->saved_vec_pol[j] =
> > +                             readl(pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> > +                     pch_pic_priv[i]->saved_vec_edge[j] =
> > +                             readl(pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> > +                     pch_pic_priv[i]->saved_vec_en[j] =
> > +                             readl(pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static void pch_pic_resume(void)
> > +{
> > +     int i, j;
> > +
> > +     for (i = 0; i < nr_pch_pics; i++) {
> > +             pch_pic_reset(pch_pic_priv[i]);
> > +             for (j = 0; j < PIC_REG_COUNT; j++) {
> > +                     writel(pch_pic_priv[i]->saved_vec_pol[j],
> > +                                     pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> > +                     writel(pch_pic_priv[i]->saved_vec_edge[j],
> > +                                     pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> > +                     writel(pch_pic_priv[i]->saved_vec_en[j],
> > +                                     pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> > +             }
> > +     }
> > +}
> > +
> > +static struct syscore_ops pch_pic_syscore_ops = {
> > +     .suspend =  pch_pic_suspend,
> > +     .resume =  pch_pic_resume,
> > +};
>
> None of this has anything to do with what is described in the commit
> message. Please move this into its own patch.
OK, this will be split out.

>
> > +
> > +#ifdef CONFIG_OF
> > +
> >  static int pch_pic_of_init(struct device_node *node,
> >                               struct device_node *parent)
> >  {
> > @@ -242,6 +297,9 @@ static int pch_pic_of_init(struct device_node *node,
> >       }
> >
> >       pch_pic_reset(priv);
> > +     pch_pic_priv[0] = priv;
> > +
> > +     register_syscore_ops(&pch_pic_syscore_ops);
> >
> >       return 0;
> >
> > @@ -254,3 +312,63 @@ static int pch_pic_of_init(struct device_node *node,
> >  }
> >
> >  IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init);
> > +
> > +#endif
> > +
> > +#ifdef CONFIG_ACPI
> > +
> > +struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
> > +                                     struct acpi_madt_bio_pic *acpi_pchpic)
> > +{
> > +     int count;
> > +     struct pch_pic *priv;
> > +     struct irq_domain *parent_domain;
> > +
> > +     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > +     if (!priv)
> > +             return NULL;
> > +
> > +     raw_spin_lock_init(&priv->pic_lock);
> > +     priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
> > +     if (!priv->base)
> > +             goto free_priv;
> > +
> > +     priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
> > +     if (!priv->domain_handle) {
> > +             pr_err("Unable to allocate domain handle\n");
> > +             goto iounmap_base;
> > +     }
> > +
> > +     priv->ht_vec_base = acpi_pchpic->gsi_base;
> > +     count = ((readq(priv->base) >> 48) & 0xff) + 1;
> > +     parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> > +     if (!parent_domain) {
> > +             pr_err("Failed to find the parent domain\n");
> > +             goto iounmap_base;
> > +     }
> > +
> > +     priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
> > +                                             count, priv->domain_handle,
> > +                                             &pch_pic_domain_ops, priv);
> > +
> > +     if (!priv->pic_domain) {
> > +             pr_err("Failed to create IRQ domain\n");
> > +             goto iounmap_base;
> > +     }
> > +
> > +     pch_pic_reset(priv);
> > +     pch_pic_priv[nr_pch_pics++] = priv;
> > +
> > +     register_syscore_ops(&pch_pic_syscore_ops);
> > +
> > +     return priv->domain_handle;
> > +
> > +iounmap_base:
> > +     iounmap(priv->base);
> > +free_priv:
> > +     kfree(priv);
> > +
> > +     return NULL;
> > +}
> > +
> > +#endif
>
> A lot of this code is common with its OF counterpart. How about making
> this logic common?
OK, let me think about.

Huacai
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] irqchip/loongson-pch-msi: Add ACPI init support
  2021-07-06 13:12   ` Marc Zyngier
@ 2021-07-07  4:51     ` Huacai Chen
  0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-07-07  4:51 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Tue, Jul 6, 2021 at 9:12 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 06 Jul 2021 04:08:59 +0100,
> Huacai Chen <chenhuacai@loongson.cn> wrote:
> >
> > We are preparing to add new Loongson (based on LoongArch, not MIPS)
> > support. LoongArch use ACPI other than DT as its boot protocol, so
> > add ACPI init support.
> >
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  drivers/irqchip/irq-loongson-pch-msi.c | 69 ++++++++++++++++++++++++--
> >  1 file changed, 64 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
> > index 32562b7e681b..adfa30046f0a 100644
> > --- a/drivers/irqchip/irq-loongson-pch-msi.c
> > +++ b/drivers/irqchip/irq-loongson-pch-msi.c
> > @@ -1,6 +1,8 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> >   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *                   Jianmin Lv <lvjianmin@loongson.cn>
> > + *                   Huacai Chen <chenhuacai@loongson.cn>
>
> Same thing as the previous patch: drop it.
>
> >   *  Loongson PCH MSI support
> >   */
> >
> > @@ -21,6 +23,7 @@ struct pch_msi_data {
> >       u32             irq_first;      /* The vector number that MSIs starts */
> >       u32             num_irqs;       /* The number of vectors for MSIs */
> >       unsigned long   *msi_map;
> > +     struct fwnode_handle *domain_handle;
> >  };
> >
> >  static void pch_msi_mask_msi_irq(struct irq_data *d)
> > @@ -159,7 +162,12 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
> >  {
> >       struct irq_domain *middle_domain, *msi_domain;
> >
> > -     middle_domain = irq_domain_create_linear(of_node_to_fwnode(node),
> > +     if (node)
> > +             priv->domain_handle = of_node_to_fwnode(node);
> > +     else
> > +             priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)priv);
> > +
> > +     middle_domain = irq_domain_create_linear(priv->domain_handle,
> >                                               priv->num_irqs,
> >                                               &pch_msi_middle_domain_ops,
> >                                               priv);
> > @@ -171,7 +179,7 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
> >       middle_domain->parent = parent;
> >       irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
> >
> > -     msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
> > +     msi_domain = pci_msi_create_irq_domain(priv->domain_handle,
> >                                              &pch_msi_domain_info,
> >                                              middle_domain);
> >       if (!msi_domain) {
> > @@ -183,8 +191,9 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
> >       return 0;
> >  }
> >
> > -static int pch_msi_init(struct device_node *node,
> > -                         struct device_node *parent)
> > +#ifdef CONFIG_OF
> > +
> > +int pch_msi_of_init(struct device_node *node, struct device_node *parent)
> >  {
> >       struct pch_msi_data *priv;
> >       struct irq_domain *parent_domain;
> > @@ -247,4 +256,54 @@ static int pch_msi_init(struct device_node *node,
> >       return ret;
> >  }
> >
> > -IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init);
> > +IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init);
> > +
> > +#endif
> > +
> > +#ifdef CONFIG_ACPI
> > +
> > +struct fwnode_handle *pch_msi_acpi_init(struct fwnode_handle *parent,
> > +                                     struct acpi_madt_msi_pic *acpi_pchmsi)
> > +{
> > +     int ret;
> > +     struct pch_msi_data *priv;
> > +     struct irq_domain *parent_domain;
> > +
> > +     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > +     if (!priv)
> > +             return NULL;
> > +
> > +     mutex_init(&priv->msi_map_lock);
> > +
> > +     priv->doorbell = acpi_pchmsi->msg_address;
> > +     priv->irq_first = acpi_pchmsi->start;
> > +     priv->num_irqs = acpi_pchmsi->count;
> > +
> > +     parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> > +     if (!parent_domain) {
> > +             pr_err("Failed to find the parent domain\n");
> > +             return NULL;
> > +     }
> > +
> > +     priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL);
> > +     if (!priv->msi_map)
> > +             goto err_priv;
> > +
> > +     pr_debug("Registering %d MSIs, starting at %d\n",
> > +              priv->num_irqs, priv->irq_first);
> > +
> > +     ret = pch_msi_init_domains(priv, NULL, parent_domain);
> > +     if (ret)
> > +             goto err_map;
> > +
> > +     return priv->domain_handle;
> > +
> > +err_map:
> > +     kfree(priv->msi_map);
> > +err_priv:
> > +     kfree(priv);
> > +
> > +     return NULL;
> > +}
> > +
> > +#endif
>
> Same thing. You are pointlessly duplicating the logic.
OK, I'll rework this.

Huacai
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] irqchip/loongson-htvec: Add ACPI init support
  2021-07-06 13:13   ` Marc Zyngier
@ 2021-07-07  4:52     ` Huacai Chen
  0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-07-07  4:52 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Tue, Jul 6, 2021 at 9:13 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 06 Jul 2021 04:09:00 +0100,
> Huacai Chen <chenhuacai@loongson.cn> wrote:
> >
> > We are preparing to add new Loongson (based on LoongArch, not MIPS)
> > support. LoongArch use ACPI other than DT as its boot protocol, so
> > add ACPI init support.
> >
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  drivers/irqchip/irq-loongson-htvec.c | 102 ++++++++++++++++++++++++++-
> >  1 file changed, 101 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c
> > index 60a335d7e64e..69452d4a33c0 100644
> > --- a/drivers/irqchip/irq-loongson-htvec.c
> > +++ b/drivers/irqchip/irq-loongson-htvec.c
> > @@ -1,6 +1,8 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> >   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *                   Jianmin Lv <lvjianmin@loongson.cn>
> > + *                   Huacai Chen <chenhuacai@loongson.cn>
>
> Drop this, move the suspend/resume code to its own patch, de-duplicate
> the probing code.
>
> Do I sound like a stuck record?
OK, I will rework this.

Huacai
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support
  2021-07-06 13:21   ` Marc Zyngier
@ 2021-07-07  4:57     ` Huacai Chen
  0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-07-07  4:57 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Tue, Jul 6, 2021 at 9:21 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 06 Jul 2021 04:09:02 +0100,
> Huacai Chen <chenhuacai@loongson.cn> wrote:
> >
> > We are preparing to add new Loongson (based on LoongArch, not MIPS)
> > support. This patch add LoongArch CPU interrupt controller support.
> >
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  drivers/irqchip/Kconfig             | 10 ++++
> >  drivers/irqchip/Makefile            |  1 +
> >  drivers/irqchip/irq-loongarch-cpu.c | 87 +++++++++++++++++++++++++++++
> >  3 files changed, 98 insertions(+)
> >  create mode 100644 drivers/irqchip/irq-loongarch-cpu.c
> >
> > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> > index 084bc4c2eebd..443c3a7a0cc1 100644
> > --- a/drivers/irqchip/Kconfig
> > +++ b/drivers/irqchip/Kconfig
> > @@ -528,6 +528,16 @@ config EXYNOS_IRQ_COMBINER
> >         Say yes here to add support for the IRQ combiner devices embedded
> >         in Samsung Exynos chips.
> >
> > +config IRQ_LOONGARCH_CPU
> > +     bool
> > +     select GENERIC_IRQ_CHIP
> > +     select IRQ_DOMAIN
> > +     select GENERIC_IRQ_EFFECTIVE_AFF_MASK
> > +     help
> > +       Support for the LoongArch CPU Interrupt Controller. For details of
> > +       irq chip hierarchy on LoongArch platforms please read the document
> > +       Documentation/loongarch/irq-chip-model.rst.
> > +
> >  config LOONGSON_LIOINTC
> >       bool "Loongson Local I/O Interrupt Controller"
> >       depends on MACH_LOONGSON64
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > index f88cbf36a9d2..4e34eebe180b 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -105,6 +105,7 @@ obj-$(CONFIG_LS1X_IRQ)                    += irq-ls1x.o
> >  obj-$(CONFIG_TI_SCI_INTR_IRQCHIP)    += irq-ti-sci-intr.o
> >  obj-$(CONFIG_TI_SCI_INTA_IRQCHIP)    += irq-ti-sci-inta.o
> >  obj-$(CONFIG_TI_PRUSS_INTC)          += irq-pruss-intc.o
> > +obj-$(CONFIG_IRQ_LOONGARCH_CPU)              += irq-loongarch-cpu.o
> >  obj-$(CONFIG_LOONGSON_LIOINTC)               += irq-loongson-liointc.o
> >  obj-$(CONFIG_LOONGSON_HTPIC)         += irq-loongson-htpic.o
> >  obj-$(CONFIG_LOONGSON_HTVEC)         += irq-loongson-htvec.o
> > diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
> > new file mode 100644
> > index 000000000000..918d61a5a980
> > --- /dev/null
> > +++ b/drivers/irqchip/irq-loongarch-cpu.c
> > @@ -0,0 +1,87 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2020 Loongson Technologies, Inc.
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/kernel.h>
> > +#include <linux/irq.h>
> > +#include <linux/irqchip.h>
> > +#include <linux/irqdomain.h>
> > +
> > +#include <asm/setup.h>
> > +#include <asm/loongarchregs.h>
> > +
> > +static struct irq_domain *irq_domain;
> > +
> > +static inline void unmask_loongarch_irq(struct irq_data *d)
> > +{
> > +     set_csr_ecfg(ECFGF(d->hwirq));
> > +}
> > +
> > +static inline void mask_loongarch_irq(struct irq_data *d)
> > +{
> > +     clear_csr_ecfg(ECFGF(d->hwirq));
> > +}
> > +
> > +#define enable_loongarch_irq  unmask_loongarch_irq
> > +#define disable_loongarch_irq mask_loongarch_irq
> > +
> > +static struct irq_chip loongarch_cpu_irq_controller = {
> > +     .name           = "LoongArch",
> > +     .irq_ack        = mask_loongarch_irq,
> > +     .irq_mask       = mask_loongarch_irq,
> > +     .irq_mask_ack   = mask_loongarch_irq,
> > +     .irq_unmask     = unmask_loongarch_irq,
> > +     .irq_eoi        = unmask_loongarch_irq,
> > +     .irq_enable     = enable_loongarch_irq,
> > +     .irq_disable    = disable_loongarch_irq,
>
> NAK. Clearly, you don't understand what these callbacks do.
>
> > +};
> > +
> > +asmlinkage void __weak plat_irq_dispatch(int irq)
> > +{
> > +     do_IRQ(irq_linear_revmap(irq_domain, irq));
> > +}
>
> NAK. If you are going to add a new architecture to Linux, do not mimic
> the MIPS brain-damage. Have your new architecture to support multiple
> interrupt controllers from day one without the need to add these silly
> weak symbols.
>
> Move the low-level code such as this into the architecture code, and
> use the existing domain abstractions.
Thanks, I will consider to rework the whole thing.

Huacai
>
> > +
> > +static int loongarch_cpu_intc_map(struct irq_domain *d, unsigned int irq,
> > +                          irq_hw_number_t hwirq)
> > +{
> > +     struct irq_chip *chip;
> > +
> > +     chip = &loongarch_cpu_irq_controller;
> > +     set_vi_handler(EXCCODE_INT_START + hwirq, plat_irq_dispatch);
> > +     irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
> > +     .map = loongarch_cpu_intc_map,
> > +     .xlate = irq_domain_xlate_onecell,
>
> Are all interrupts with the same trigger?
>
> > +};
> > +
> > +
> > +int __init loongarch_cpu_irq_init(struct device_node *of_node, struct device_node *parent)
> > +{
> > +     int i;
> > +
> > +     /* Mask interrupts. */
> > +     clear_csr_ecfg(ECFG0_IM);
> > +     clear_csr_estat(ESTATF_IP);
> > +
> > +     irq_alloc_descs(-1, LOONGSON_CPU_IRQ_BASE, EXCCODE_INT_NUM, 0);
> > +
> > +     for (i = LOONGSON_CPU_IRQ_BASE; i <= LOONGSON_CPU_LAST_IRQ; i++)
> > +             irq_set_noprobe(i);
> > +
> > +     irq_domain = irq_domain_add_legacy(of_node, EXCCODE_INT_NUM,
> > +                  LOONGSON_CPU_IRQ_BASE, 0, &loongarch_cpu_intc_irq_domain_ops, NULL);
>
> Oh, the irony of using irq_domain_add_legacy() for a brand new
> architecture...
>
> > +
> > +     if (!irq_domain)
> > +             panic("Failed to add irqdomain for loongarch CPU");
> > +
> > +     return 0;
> > +}
> > +
> > +IRQCHIP_DECLARE(cpu_intc, "loongson,cpu-interrupt-controller", loongarch_cpu_irq_init);
>
> As it stands, this driver has zero chance of being merged. You
> seriously need to move your low-level interrupt handling code into the
> 21st century.
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 8/9] irqchip: Add Loongson Extended I/O interrupt controller support
  2021-07-06  3:09 ` [PATCH 8/9] irqchip: Add Loongson Extended I/O " Huacai Chen
@ 2021-07-08 20:53   ` kernel test robot
  0 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2021-07-08 20:53 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11764 bytes --]

Hi Huacai,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tip/irq/core]
[also build test WARNING on linux/master linus/master v5.13 next-20210708]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 3d2ce675aba7e2425710e23268579a5d76c7e725
config: mips-loongson2k_defconfig (attached as .config)
compiler: mips64el-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/04fd429333496372c9a6edc920872e35ede4c900
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
        git checkout 04fd429333496372c9a6edc920872e35ede4c900
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/irqchip/irq-loongson-eiointc.c: In function 'eiointc_set_irq_route':
   drivers/irqchip/irq-loongson-eiointc.c:65:3: error: implicit declaration of function 'csr_any_send' [-Werror=implicit-function-declaration]
      65 |   csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, node);
         |   ^~~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c: At top level:
>> drivers/irqchip/irq-loongson-eiointc.c:71:5: warning: no previous prototype for 'eiointc_set_irq_affinity' [-Wmissing-prototypes]
      71 | int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
         |     ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c: In function 'eiointc_router_init':
   drivers/irqchip/irq-loongson-eiointc.c:116:3: error: implicit declaration of function 'eiointc_enable' [-Werror=implicit-function-declaration]
     116 |   eiointc_enable();
         |   ^~~~~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c:120:4: error: implicit declaration of function 'iocsr_writel' [-Werror=implicit-function-declaration]
     120 |    iocsr_writel(data, EIOINTC_REG_NODEMAP + i * 4);
         |    ^~~~~~~~~~~~
   In file included from include/linux/bits.h:6,
                    from include/linux/bitops.h:6,
                    from include/linux/kernel.h:12,
                    from include/linux/interrupt.h:6,
                    from drivers/irqchip/irq-loongson-eiointc.c:9:
   drivers/irqchip/irq-loongson-eiointc.c:130:14: error: implicit declaration of function 'cpu_logical_map' [-Werror=implicit-function-declaration]
     130 |    bit = BIT(cpu_logical_map(0));
         |              ^~~~~~~~~~~~~~~
   include/vdso/bits.h:7:30: note: in definition of macro 'BIT'
       7 | #define BIT(nr)   (UL(1) << (nr))
         |                              ^~
   drivers/irqchip/irq-loongson-eiointc.c: In function 'eiointc_irq_dispatch':
   drivers/irqchip/irq-loongson-eiointc.c:156:13: error: implicit declaration of function 'iocsr_readq' [-Werror=implicit-function-declaration]
     156 |   pending = iocsr_readq(EIOINTC_REG_ISR + (i << 3));
         |             ^~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c:157:3: error: implicit declaration of function 'iocsr_writeq' [-Werror=implicit-function-declaration]
     157 |   iocsr_writeq(pending, EIOINTC_REG_ISR + (i << 3));
         |   ^~~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c: At top level:
>> drivers/irqchip/irq-loongson-eiointc.c:262:48: warning: 'struct acpi_madt_eio_pic' declared inside parameter list will not be visible outside of this definition or declaration
     262 | struct fwnode_handle *eiointc_acpi_init(struct acpi_madt_eio_pic *acpi_eiointc)
         |                                                ^~~~~~~~~~~~~~~~~
>> drivers/irqchip/irq-loongson-eiointc.c:262:23: warning: no previous prototype for 'eiointc_acpi_init' [-Wmissing-prototypes]
     262 | struct fwnode_handle *eiointc_acpi_init(struct acpi_madt_eio_pic *acpi_eiointc)
         |                       ^~~~~~~~~~~~~~~~~
   drivers/irqchip/irq-loongson-eiointc.c: In function 'eiointc_acpi_init':
   drivers/irqchip/irq-loongson-eiointc.c:293:15: error: 'LOONGSON_CPU_IRQ_BASE' undeclared (first use in this function); did you mean 'MIPS_CPU_IRQ_BASE'?
     293 |  parent_irq = LOONGSON_CPU_IRQ_BASE + acpi_eiointc->cascade;
         |               ^~~~~~~~~~~~~~~~~~~~~
         |               MIPS_CPU_IRQ_BASE
   drivers/irqchip/irq-loongson-eiointc.c:293:15: note: each undeclared identifier is reported only once for each function it appears in
   drivers/irqchip/irq-loongson-eiointc.c:293:51: error: dereferencing pointer to incomplete type 'struct acpi_madt_eio_pic'
     293 |  parent_irq = LOONGSON_CPU_IRQ_BASE + acpi_eiointc->cascade;
         |                                                   ^~
   cc1: some warnings being treated as errors


vim +/eiointc_set_irq_affinity +71 drivers/irqchip/irq-loongson-eiointc.c

    70	
  > 71	int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
    72				  bool force)
    73	{
    74		unsigned int cpu;
    75		unsigned long flags;
    76		uint32_t vector, pos_off;
    77	
    78		if (!IS_ENABLED(CONFIG_SMP))
    79			return -EPERM;
    80	
    81		spin_lock_irqsave(&affinity_lock, flags);
    82	
    83		if (!cpumask_intersects(affinity, cpu_online_mask)) {
    84			spin_unlock_irqrestore(&affinity_lock, flags);
    85			return -EINVAL;
    86		}
    87		cpu = cpumask_first_and(affinity, cpu_online_mask);
    88	
    89		/*
    90		 * Control interrupt enable or disalbe through cpu 0
    91		 * which is reponsible for dispatching interrupts.
    92		 */
    93		vector = d->hwirq;
    94		pos_off = vector >> 5;
    95	
    96		csr_any_send(EIOINTC_REG_ENABLE + (pos_off << 2),
    97			     eiointc_priv->eiointc_en[pos_off] & (~((1 << (vector & 0x1F)))), 0x0, 0);
    98	
    99		eiointc_set_irq_route(vector, cpu);
   100		csr_any_send(EIOINTC_REG_ENABLE + (pos_off << 2),
   101			     eiointc_priv->eiointc_en[pos_off], 0x0, 0);
   102		irq_data_update_effective_affinity(d, cpumask_of(cpu));
   103	
   104		spin_unlock_irqrestore(&affinity_lock, flags);
   105	
   106		return IRQ_SET_MASK_OK;
   107	}
   108	
   109	static int eiointc_router_init(unsigned int cpu)
   110	{
   111		int i, bit;
   112		uint32_t data;
   113		uint32_t node = cpu_to_node(cpu);
   114	
   115		if (cpu == cpumask_first(cpumask_of_node(node))) {
   116			eiointc_enable();
   117	
   118			for (i = 0; i < VEC_COUNT / 32; i++) {
   119				data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2)));
   120				iocsr_writel(data, EIOINTC_REG_NODEMAP + i * 4);
   121			}
   122	
   123			for (i = 0; i < VEC_COUNT / 32 / 4; i++) {
   124				data = 0x02020202; /* Route to IP3 */
   125				iocsr_writel(data, EIOINTC_REG_IPMAP + i * 4);
   126			}
   127	
   128			for (i = 0; i < VEC_COUNT / 4; i++) {
   129				/* Route to Node-0 Core-0 */
   130				bit = BIT(cpu_logical_map(0));
   131				data = bit | (bit << 8) | (bit << 16) | (bit << 24);
   132				iocsr_writel(data, EIOINTC_REG_ROUTE + i * 4);
   133			}
   134	
   135			for (i = 0; i < VEC_COUNT / 32; i++) {
   136				data = 0xffffffff;
   137				iocsr_writel(data, EIOINTC_REG_ENABLE + i * 4);
   138				iocsr_writel(data, EIOINTC_REG_BOUNCE + i * 4);
   139			}
   140		}
   141	
   142		return 0;
   143	}
   144	
   145	static void eiointc_irq_dispatch(struct irq_desc *desc)
   146	{
   147		int i;
   148		u64 pending;
   149		bool handled = false;
   150		struct irq_chip *chip = irq_desc_get_chip(desc);
   151		struct eiointc_priv *priv = irq_desc_get_handler_data(desc);
   152	
   153		chained_irq_enter(chip, desc);
   154	
   155		for (i = 0; i < VEC_REG_COUNT; i++) {
   156			pending = iocsr_readq(EIOINTC_REG_ISR + (i << 3));
   157			iocsr_writeq(pending, EIOINTC_REG_ISR + (i << 3));
   158			while (pending) {
   159				int bit = __ffs(pending);
   160				int virq = irq_linear_revmap(priv->eiointc_domain, bit + VEC_COUNT_PER_REG * i);
   161	
   162				generic_handle_irq(virq);
   163				pending &= ~BIT(bit);
   164				handled = true;
   165			}
   166		}
   167	
   168		if (!handled)
   169			spurious_interrupt();
   170	
   171		chained_irq_exit(chip, desc);
   172	}
   173	
   174	static void eiointc_ack_irq(struct irq_data *d)
   175	{
   176	}
   177	
   178	static void eiointc_mask_irq(struct irq_data *d)
   179	{
   180	}
   181	
   182	static void eiointc_unmask_irq(struct irq_data *d)
   183	{
   184	}
   185	
   186	static struct irq_chip eiointc_irq_chip = {
   187		.name			= "EIOINTC",
   188		.irq_ack		= eiointc_ack_irq,
   189		.irq_mask		= eiointc_mask_irq,
   190		.irq_unmask		= eiointc_unmask_irq,
   191		.irq_set_affinity	= eiointc_set_irq_affinity,
   192	};
   193	
   194	static int eiointc_domain_alloc(struct irq_domain *domain, unsigned int virq,
   195					unsigned int nr_irqs, void *arg)
   196	{
   197		int ret;
   198		unsigned int i, type;
   199		unsigned long hwirq = 0;
   200		struct eiointc *priv = domain->host_data;
   201	
   202		ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type);
   203		if (ret)
   204			return ret;
   205	
   206		for (i = 0; i < nr_irqs; i++) {
   207			irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip,
   208						priv, handle_edge_irq, NULL, NULL);
   209		}
   210	
   211		return 0;
   212	}
   213	
   214	static void eiointc_domain_free(struct irq_domain *domain, unsigned int virq,
   215					unsigned int nr_irqs)
   216	{
   217		int i;
   218	
   219		for (i = 0; i < nr_irqs; i++) {
   220			struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
   221	
   222			irq_set_handler(virq + i, NULL);
   223			irq_domain_reset_irq_data(d);
   224		}
   225	}
   226	
   227	static const struct irq_domain_ops eiointc_domain_ops = {
   228		.translate	= irq_domain_translate_onecell,
   229		.alloc		= eiointc_domain_alloc,
   230		.free		= eiointc_domain_free,
   231	};
   232	
   233	static int eiointc_suspend(void)
   234	{
   235		return 0;
   236	}
   237	
   238	static void eiointc_resume(void)
   239	{
   240		int i;
   241		struct irq_desc *desc;
   242	
   243		/* init irq en bitmap */
   244		for (i = 0; i < VEC_COUNT / 32; i++)
   245			eiointc_priv->eiointc_en[i] = 0xffffffff;
   246	
   247		eiointc_router_init(0);
   248	
   249		for (i = 0; i < NR_IRQS; i++) {
   250			desc = irq_to_desc(i);
   251			if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq)
   252				eiointc_set_irq_affinity(&desc->irq_data,
   253							 desc->irq_data.common->affinity, 0);
   254		}
   255	}
   256	
   257	static struct syscore_ops eiointc_syscore_ops = {
   258		.suspend = eiointc_suspend,
   259		.resume = eiointc_resume,
   260	};
   261	
 > 262	struct fwnode_handle *eiointc_acpi_init(struct acpi_madt_eio_pic *acpi_eiointc)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31144 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] irqchip: Add Loongson PCH LPC controller support
  2021-07-06  3:09 ` [PATCH 9/9] irqchip: Add Loongson PCH LPC " Huacai Chen
@ 2021-07-08 22:27   ` kernel test robot
  0 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2021-07-08 22:27 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3763 bytes --]

Hi Huacai,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tip/irq/core]
[also build test WARNING on linux/master linus/master v5.13 next-20210708]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 3d2ce675aba7e2425710e23268579a5d76c7e725
config: mips-loongson2k_defconfig (attached as .config)
compiler: mips64el-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/4fbd48146047c7b30465004c71ffe4a711d5c5e8
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
        git checkout 4fbd48146047c7b30465004c71ffe4a711d5c5e8
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross O=build_dir ARCH=mips SHELL=/bin/bash drivers/irqchip/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/irqchip/irq-loongson-pch-lpc.c:148:13: warning: 'struct acpi_madt_lpc_pic' declared inside parameter list will not be visible outside of this definition or declaration
     148 |      struct acpi_madt_lpc_pic *acpi_pchlpc)
         |             ^~~~~~~~~~~~~~~~~
   drivers/irqchip/irq-loongson-pch-lpc.c:147:23: warning: no previous prototype for 'pch_lpc_acpi_init' [-Wmissing-prototypes]
     147 | struct fwnode_handle *pch_lpc_acpi_init(struct fwnode_handle *parent,
         |                       ^~~~~~~~~~~~~~~~~
   In file included from arch/mips/include/asm/mmiowb.h:5,
                    from include/linux/spinlock.h:61,
                    from include/linux/wait.h:9,
                    from include/linux/pid.h:6,
                    from include/linux/sched.h:14,
                    from include/linux/hardirq.h:9,
                    from include/linux/interrupt.h:11,
                    from drivers/irqchip/irq-loongson-pch-lpc.c:9:
   drivers/irqchip/irq-loongson-pch-lpc.c: In function 'pch_lpc_acpi_init':
   drivers/irqchip/irq-loongson-pch-lpc.c:163:34: error: dereferencing pointer to incomplete type 'struct acpi_madt_lpc_pic'
     163 |  priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size);
         |                                  ^~
   arch/mips/include/asm/io.h:180:16: note: in definition of macro 'ioremap'
     180 |  ioremap_prot((offset), (size), _CACHE_UNCACHED)
         |                ^~~~~~
   drivers/irqchip/irq-loongson-pch-lpc.c:187:20: error: 'GSI_MIN_PCH_IRQ' undeclared (first use in this function)
     187 |  fwspec.param[0] = GSI_MIN_PCH_IRQ + acpi_pchlpc->cascade;
         |                    ^~~~~~~~~~~~~~~
   drivers/irqchip/irq-loongson-pch-lpc.c:187:20: note: each undeclared identifier is reported only once for each function it appears in


vim +148 drivers/irqchip/irq-loongson-pch-lpc.c

   146	
   147	struct fwnode_handle *pch_lpc_acpi_init(struct fwnode_handle *parent,
 > 148						struct acpi_madt_lpc_pic *acpi_pchlpc)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31150 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 6/9] irqchip/loongson-liointc: Add ACPI init support
  2021-07-06  3:09 ` [PATCH 6/9] irqchip/loongson-liointc: " Huacai Chen
@ 2021-07-09  0:59   ` kernel test robot
  0 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2021-07-09  0:59 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3192 bytes --]

Hi Huacai,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/irq/core]
[also build test ERROR on linux/master linus/master v5.13 next-20210708]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 3d2ce675aba7e2425710e23268579a5d76c7e725
config: mips-loongson2k_defconfig (attached as .config)
compiler: mips64el-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a2475c3e53e0055e6eb1842fe58dec0f4e453f82
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Huacai-Chen/irqchip-Add-LoongArch-related-irqchip-drivers/20210706-111309
        git checkout a2475c3e53e0055e6eb1842fe58dec0f4e453f82
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-loongson-liointc.c: In function 'liointc_chained_handle_irq':
>> drivers/irqchip/irq-loongson-liointc.c:58:13: error: implicit declaration of function 'cpu_logical_map' [-Werror=implicit-function-declaration]
      58 |  int core = cpu_logical_map(smp_processor_id()) % LIOINTC_NUM_CORES;
         |             ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/cpu_logical_map +58 drivers/irqchip/irq-loongson-liointc.c

    52	
    53	static void liointc_chained_handle_irq(struct irq_desc *desc)
    54	{
    55		struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
    56		struct irq_chip *chip = irq_desc_get_chip(desc);
    57		struct irq_chip_generic *gc = handler->priv->gc;
  > 58		int core = cpu_logical_map(smp_processor_id()) % LIOINTC_NUM_CORES;
    59		u32 pending;
    60	
    61		chained_irq_enter(chip, desc);
    62	
    63		pending = readl(handler->priv->core_isr[core]);
    64	
    65		if (!pending) {
    66			/* Always blame LPC IRQ if we have that bug */
    67			if (handler->priv->has_lpc_irq_errata &&
    68				(handler->parent_int_map & gc->mask_cache &
    69				BIT(LIOINTC_ERRATA_IRQ)))
    70				pending = BIT(LIOINTC_ERRATA_IRQ);
    71			else
    72				spurious_interrupt();
    73		}
    74	
    75		while (pending) {
    76			int bit = __ffs(pending);
    77	
    78			generic_handle_domain_irq(gc->domain, bit);
    79			pending &= ~BIT(bit);
    80		}
    81	
    82		chained_irq_exit(chip, desc);
    83	}
    84	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31142 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support
  2021-07-06 13:06   ` Marc Zyngier
@ 2021-07-09  3:00     ` Huacai Chen
  2021-08-04 14:23       ` Marc Zyngier
  0 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-07-09  3:00 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang, Chen Zhu

Hi, Marc,

On Tue, Jul 6, 2021 at 9:06 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 06 Jul 2021 04:08:57 +0100,
> Huacai Chen <chenhuacai@loongson.cn> wrote:
> >
> > Edge-triggered mode and level-triggered mode need different handlers,
> > and edge-triggered mode need a specific ack operation. So improve it.
> >
>
> Is this a fix? How does it work currently?
Yes, some devices (e.g., RTC) is edge-triggered, they need
handle_edge_irq(). Currently we don't use RTC interrupt in the
upstream kernel on Loongson platform, so it "works".

>
>
> > Signed-off-by: Chen Zhu <zhuchen@loongson.cn>
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  drivers/irqchip/irq-loongson-pch-pic.c | 19 ++++++++++++++++++-
> >  1 file changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> > index f790ca6d78aa..a4eb8a2181c7 100644
> > --- a/drivers/irqchip/irq-loongson-pch-pic.c
> > +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> > @@ -92,18 +92,22 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
> >       case IRQ_TYPE_EDGE_RISING:
> >               pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
> >               pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
> > +             irq_set_handler_locked(d, handle_edge_irq);
> >               break;
> >       case IRQ_TYPE_EDGE_FALLING:
> >               pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
> >               pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
> > +             irq_set_handler_locked(d, handle_edge_irq);
> >               break;
> >       case IRQ_TYPE_LEVEL_HIGH:
> >               pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
> >               pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
> > +             irq_set_handler_locked(d, handle_level_irq);
> >               break;
> >       case IRQ_TYPE_LEVEL_LOW:
> >               pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
> >               pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
> > +             irq_set_handler_locked(d, handle_level_irq);
>
> You are changing the flow for the whole hierarchy. Are all the
> irqchips in the stack supporting this?
Yes, both PCH-PIC and its parent (HTVEC) support both edge and level mode.

Huacai
>
> >               break;
> >       default:
> >               ret = -EINVAL;
> > @@ -113,11 +117,24 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
> >       return ret;
> >  }
> >
> > +static void pch_pic_ack_irq(struct irq_data *d)
> > +{
> > +     unsigned int reg;
> > +     struct pch_pic *priv = irq_data_get_irq_chip_data(d);
> > +
> > +     reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
> > +     if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
> > +             writel(BIT(PIC_REG_BIT(d->hwirq)),
> > +                     priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
> > +     }
> > +     irq_chip_ack_parent(d);
> > +}
> > +
> >  static struct irq_chip pch_pic_irq_chip = {
> >       .name                   = "PCH PIC",
> >       .irq_mask               = pch_pic_mask_irq,
> >       .irq_unmask             = pch_pic_unmask_irq,
> > -     .irq_ack                = irq_chip_ack_parent,
> > +     .irq_ack                = pch_pic_ack_irq,
> >       .irq_set_affinity       = irq_chip_set_affinity_parent,
> >       .irq_set_type           = pch_pic_set_type,
> >  };
>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support
  2021-07-09  3:00     ` Huacai Chen
@ 2021-08-04 14:23       ` Marc Zyngier
  2021-08-05 13:06         ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-08-04 14:23 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang, Chen Zhu

On Fri, 09 Jul 2021 04:00:58 +0100,
Huacai Chen <chenhuacai@gmail.com> wrote:
> 
> Hi, Marc,
> 
> On Tue, Jul 6, 2021 at 9:06 PM Marc Zyngier <maz@kernel.org> wrote:
> >
> > On Tue, 06 Jul 2021 04:08:57 +0100,
> > Huacai Chen <chenhuacai@loongson.cn> wrote:
> > >
> > > Edge-triggered mode and level-triggered mode need different handlers,
> > > and edge-triggered mode need a specific ack operation. So improve it.
> > >
> >
> > Is this a fix? How does it work currently?
> Yes, some devices (e.g., RTC) is edge-triggered, they need
> handle_edge_irq(). Currently we don't use RTC interrupt in the
> upstream kernel on Loongson platform, so it "works".

If you want me to queue this independently of the full LoongArch
series, please resend it with a Fixes: tag.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support
  2021-08-04 14:23       ` Marc Zyngier
@ 2021-08-05 13:06         ` Huacai Chen
  0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-08-05 13:06 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang, Chen Zhu

Hi, Marc,

On Wed, Aug 4, 2021 at 10:23 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Fri, 09 Jul 2021 04:00:58 +0100,
> Huacai Chen <chenhuacai@gmail.com> wrote:
> >
> > Hi, Marc,
> >
> > On Tue, Jul 6, 2021 at 9:06 PM Marc Zyngier <maz@kernel.org> wrote:
> > >
> > > On Tue, 06 Jul 2021 04:08:57 +0100,
> > > Huacai Chen <chenhuacai@loongson.cn> wrote:
> > > >
> > > > Edge-triggered mode and level-triggered mode need different handlers,
> > > > and edge-triggered mode need a specific ack operation. So improve it.
> > > >
> > >
> > > Is this a fix? How does it work currently?
> > Yes, some devices (e.g., RTC) is edge-triggered, they need
> > handle_edge_irq(). Currently we don't use RTC interrupt in the
> > upstream kernel on Loongson platform, so it "works".
>
> If you want me to queue this independently of the full LoongArch
> series, please resend it with a Fixes: tag.
OK, I will send V2.

Huacai
>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-07-07  4:50     ` Huacai Chen
@ 2021-08-12 12:23       ` Huacai Chen
  2021-08-12 13:28         ` Marc Zyngier
  0 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2021-08-12 12:23 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Wed, Jul 7, 2021 at 12:50 PM Huacai Chen <chenhuacai@gmail.com> wrote:
>
> Hi, Marc,
>
> On Tue, Jul 6, 2021 at 9:10 PM Marc Zyngier <maz@kernel.org> wrote:
> >
> > On Tue, 06 Jul 2021 04:08:58 +0100,
> > Huacai Chen <chenhuacai@loongson.cn> wrote:
> > >
> > > We are preparing to add new Loongson (based on LoongArch, not MIPS)
> > > support. LoongArch use ACPI other than DT as its boot protocol, so
> > > add ACPI init support.
> > >
> > > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > > ---
> > >  drivers/irqchip/irq-loongson-pch-pic.c | 120 ++++++++++++++++++++++++-
> > >  1 file changed, 119 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> > > index a4eb8a2181c7..62382611995b 100644
> > > --- a/drivers/irqchip/irq-loongson-pch-pic.c
> > > +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> > > @@ -1,6 +1,8 @@
> > >  // SPDX-License-Identifier: GPL-2.0
> > >  /*
> > >   *  Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
> > > + *                   Jianmin Lv <lvjianmin@loongson.cn>
> > > + *                   Huacai Chen <chenhuacai@loongson.cn>
> >
> > Please drop this change. I'm in a position where I can verify who owns
> > the copyright to this code, and I seriously doubt that 100 lines of
> > boilerplate probing code give you any right over it.
> OK, thanks.
>
> >
> > >   *  Loongson PCH PIC support
> > >   */
> > >
> > > @@ -15,6 +17,7 @@
> > >  #include <linux/of_address.h>
> > >  #include <linux/of_irq.h>
> > >  #include <linux/of_platform.h>
> > > +#include <linux/syscore_ops.h>
> > >
> > >  /* Registers */
> > >  #define PCH_PIC_MASK         0x20
> > > @@ -32,14 +35,23 @@
> > >  #define PIC_COUNT            (PIC_COUNT_PER_REG * PIC_REG_COUNT)
> > >  #define PIC_REG_IDX(irq_id)  ((irq_id) / PIC_COUNT_PER_REG)
> > >  #define PIC_REG_BIT(irq_id)  ((irq_id) % PIC_COUNT_PER_REG)
> > > +#define PCH_PIC_SIZE         0x400
> > > +
> > > +static int nr_pch_pics;
> > >
> > >  struct pch_pic {
> > >       void __iomem            *base;
> > >       struct irq_domain       *pic_domain;
> > > +     struct fwnode_handle    *domain_handle;
> > >       u32                     ht_vec_base;
> > >       raw_spinlock_t          pic_lock;
> > > +     u32                     saved_vec_en[PIC_REG_COUNT];
> > > +     u32                     saved_vec_pol[PIC_REG_COUNT];
> > > +     u32                     saved_vec_edge[PIC_REG_COUNT];
> > >  };
> > >
> > > +struct pch_pic *pch_pic_priv[4];
> > > +
> > >  static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
> > >  {
> > >       u32 reg;
> > > @@ -137,6 +149,7 @@ static struct irq_chip pch_pic_irq_chip = {
> > >       .irq_ack                = pch_pic_ack_irq,
> > >       .irq_set_affinity       = irq_chip_set_affinity_parent,
> > >       .irq_set_type           = pch_pic_set_type,
> > > +     .flags                  = IRQCHIP_SKIP_SET_WAKE,
> > >  };
> > >
> > >  static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
> > > @@ -180,7 +193,7 @@ static void pch_pic_reset(struct pch_pic *priv)
> > >       int i;
> > >
> > >       for (i = 0; i < PIC_COUNT; i++) {
> > > -             /* Write vectored ID */
> > > +             /* Write vector ID */
> > >               writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
> > >               /* Hardcode route to HT0 Lo */
> > >               writeb(1, priv->base + PCH_INT_ROUTE(i));
> > > @@ -198,6 +211,48 @@ static void pch_pic_reset(struct pch_pic *priv)
> > >       }
> > >  }
> > >
> > > +static int pch_pic_suspend(void)
> > > +{
> > > +     int i, j;
> > > +
> > > +     for (i = 0; i < nr_pch_pics; i++) {
> > > +             for (j = 0; j < PIC_REG_COUNT; j++) {
> > > +                     pch_pic_priv[i]->saved_vec_pol[j] =
> > > +                             readl(pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> > > +                     pch_pic_priv[i]->saved_vec_edge[j] =
> > > +                             readl(pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> > > +                     pch_pic_priv[i]->saved_vec_en[j] =
> > > +                             readl(pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> > > +             }
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void pch_pic_resume(void)
> > > +{
> > > +     int i, j;
> > > +
> > > +     for (i = 0; i < nr_pch_pics; i++) {
> > > +             pch_pic_reset(pch_pic_priv[i]);
> > > +             for (j = 0; j < PIC_REG_COUNT; j++) {
> > > +                     writel(pch_pic_priv[i]->saved_vec_pol[j],
> > > +                                     pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j);
> > > +                     writel(pch_pic_priv[i]->saved_vec_edge[j],
> > > +                                     pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j);
> > > +                     writel(pch_pic_priv[i]->saved_vec_en[j],
> > > +                                     pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j);
> > > +             }
> > > +     }
> > > +}
> > > +
> > > +static struct syscore_ops pch_pic_syscore_ops = {
> > > +     .suspend =  pch_pic_suspend,
> > > +     .resume =  pch_pic_resume,
> > > +};
> >
> > None of this has anything to do with what is described in the commit
> > message. Please move this into its own patch.
> OK, this will be split out.
>
> >
> > > +
> > > +#ifdef CONFIG_OF
> > > +
> > >  static int pch_pic_of_init(struct device_node *node,
> > >                               struct device_node *parent)
> > >  {
> > > @@ -242,6 +297,9 @@ static int pch_pic_of_init(struct device_node *node,
> > >       }
> > >
> > >       pch_pic_reset(priv);
> > > +     pch_pic_priv[0] = priv;
> > > +
> > > +     register_syscore_ops(&pch_pic_syscore_ops);
> > >
> > >       return 0;
> > >
> > > @@ -254,3 +312,63 @@ static int pch_pic_of_init(struct device_node *node,
> > >  }
> > >
> > >  IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init);
> > > +
> > > +#endif
> > > +
> > > +#ifdef CONFIG_ACPI
> > > +
> > > +struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
> > > +                                     struct acpi_madt_bio_pic *acpi_pchpic)
> > > +{
> > > +     int count;
> > > +     struct pch_pic *priv;
> > > +     struct irq_domain *parent_domain;
> > > +
> > > +     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > > +     if (!priv)
> > > +             return NULL;
> > > +
> > > +     raw_spin_lock_init(&priv->pic_lock);
> > > +     priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
> > > +     if (!priv->base)
> > > +             goto free_priv;
> > > +
> > > +     priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
> > > +     if (!priv->domain_handle) {
> > > +             pr_err("Unable to allocate domain handle\n");
> > > +             goto iounmap_base;
> > > +     }
> > > +
> > > +     priv->ht_vec_base = acpi_pchpic->gsi_base;
> > > +     count = ((readq(priv->base) >> 48) & 0xff) + 1;
> > > +     parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> > > +     if (!parent_domain) {
> > > +             pr_err("Failed to find the parent domain\n");
> > > +             goto iounmap_base;
> > > +     }
> > > +
> > > +     priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
> > > +                                             count, priv->domain_handle,
> > > +                                             &pch_pic_domain_ops, priv);
> > > +
> > > +     if (!priv->pic_domain) {
> > > +             pr_err("Failed to create IRQ domain\n");
> > > +             goto iounmap_base;
> > > +     }
> > > +
> > > +     pch_pic_reset(priv);
> > > +     pch_pic_priv[nr_pch_pics++] = priv;
> > > +
> > > +     register_syscore_ops(&pch_pic_syscore_ops);
> > > +
> > > +     return priv->domain_handle;
> > > +
> > > +iounmap_base:
> > > +     iounmap(priv->base);
> > > +free_priv:
> > > +     kfree(priv);
> > > +
> > > +     return NULL;
> > > +}
> > > +
> > > +#endif
> >
> > A lot of this code is common with its OF counterpart. How about making
> > this logic common?
> OK, let me think about.
Though pch_pic_acpi_init() is similar to pch_pic_of_init(), but it is
difficult to make a common function, because we cannot prepare
everything before the common function. For example, ioremap() can be
the common part, but pch_pic_acpi_init() should get the vector count
after ioremap(). If we use an argument to distinguish the caller in
the common function, the complexity increases and seems no benefits.

Huacai
>
> Huacai
> >
> >         M.
> >
> > --
> > Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-08-12 12:23       ` Huacai Chen
@ 2021-08-12 13:28         ` Marc Zyngier
  2021-08-16  3:19           ` Huacai Chen
  0 siblings, 1 reply; 28+ messages in thread
From: Marc Zyngier @ 2021-08-12 13:28 UTC (permalink / raw)
  To: Huacai Chen; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

On Thu, 12 Aug 2021 13:23:27 +0100,
Huacai Chen <chenhuacai@gmail.com> wrote:
> 
[...]

> > > > +struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
> > > > +                                     struct acpi_madt_bio_pic *acpi_pchpic)
> > > > +{
> > > > +     int count;
> > > > +     struct pch_pic *priv;
> > > > +     struct irq_domain *parent_domain;
> > > > +
> > > > +     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > > > +     if (!priv)
> > > > +             return NULL;
> > > > +
> > > > +     raw_spin_lock_init(&priv->pic_lock);
> > > > +     priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
> > > > +     if (!priv->base)
> > > > +             goto free_priv;
> > > > +
> > > > +     priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
> > > > +     if (!priv->domain_handle) {
> > > > +             pr_err("Unable to allocate domain handle\n");
> > > > +             goto iounmap_base;
> > > > +     }
> > > > +
> > > > +     priv->ht_vec_base = acpi_pchpic->gsi_base;
> > > > +     count = ((readq(priv->base) >> 48) & 0xff) + 1;
> > > > +     parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> > > > +     if (!parent_domain) {
> > > > +             pr_err("Failed to find the parent domain\n");
> > > > +             goto iounmap_base;
> > > > +     }
> > > > +
> > > > +     priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
> > > > +                                             count, priv->domain_handle,
> > > > +                                             &pch_pic_domain_ops, priv);
> > > > +
> > > > +     if (!priv->pic_domain) {
> > > > +             pr_err("Failed to create IRQ domain\n");
> > > > +             goto iounmap_base;
> > > > +     }
> > > > +
> > > > +     pch_pic_reset(priv);
> > > > +     pch_pic_priv[nr_pch_pics++] = priv;
> > > > +
> > > > +     register_syscore_ops(&pch_pic_syscore_ops);
> > > > +
> > > > +     return priv->domain_handle;
> > > > +
> > > > +iounmap_base:
> > > > +     iounmap(priv->base);
> > > > +free_priv:
> > > > +     kfree(priv);
> > > > +
> > > > +     return NULL;
> > > > +}
> > > > +
> > > > +#endif
> > >
> > > A lot of this code is common with its OF counterpart. How about making
> > > this logic common?
> > OK, let me think about.
> Though pch_pic_acpi_init() is similar to pch_pic_of_init(), but it is
> difficult to make a common function, because we cannot prepare
> everything before the common function. For example, ioremap() can be
> the common part, but pch_pic_acpi_init() should get the vector count
> after ioremap(). If we use an argument to distinguish the caller in
> the common function, the complexity increases and seems no benefits.

All firmware implementations allocate private data structures, irq
domains, map MMIO regions, etc. All that can be common. We even have
APIs that deal with both firmware interfaces.

As for the 'read the vector count from the HW', what does it have to
do with driving the HW using DT or ACPI? The HW doesn't *know*. If you
are conflating HW changes and firmware interfaces, then you have
already lost.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support
  2021-08-12 13:28         ` Marc Zyngier
@ 2021-08-16  3:19           ` Huacai Chen
  0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2021-08-16  3:19 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: Huacai Chen, Thomas Gleixner, LKML, Xuefeng Li, Jiaxun Yang

Hi, Marc,

On Thu, Aug 12, 2021 at 9:28 PM Marc Zyngier <maz@kernel.org> wrote:
>
> On Thu, 12 Aug 2021 13:23:27 +0100,
> Huacai Chen <chenhuacai@gmail.com> wrote:
> >
> [...]
>
> > > > > +struct fwnode_handle *pch_pic_acpi_init(struct fwnode_handle *parent,
> > > > > +                                     struct acpi_madt_bio_pic *acpi_pchpic)
> > > > > +{
> > > > > +     int count;
> > > > > +     struct pch_pic *priv;
> > > > > +     struct irq_domain *parent_domain;
> > > > > +
> > > > > +     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > > > > +     if (!priv)
> > > > > +             return NULL;
> > > > > +
> > > > > +     raw_spin_lock_init(&priv->pic_lock);
> > > > > +     priv->base = ioremap(acpi_pchpic->address, acpi_pchpic->size);
> > > > > +     if (!priv->base)
> > > > > +             goto free_priv;
> > > > > +
> > > > > +     priv->domain_handle = irq_domain_alloc_fwnode(priv->base);
> > > > > +     if (!priv->domain_handle) {
> > > > > +             pr_err("Unable to allocate domain handle\n");
> > > > > +             goto iounmap_base;
> > > > > +     }
> > > > > +
> > > > > +     priv->ht_vec_base = acpi_pchpic->gsi_base;
> > > > > +     count = ((readq(priv->base) >> 48) & 0xff) + 1;
> > > > > +     parent_domain = irq_find_matching_fwnode(parent, DOMAIN_BUS_ANY);
> > > > > +     if (!parent_domain) {
> > > > > +             pr_err("Failed to find the parent domain\n");
> > > > > +             goto iounmap_base;
> > > > > +     }
> > > > > +
> > > > > +     priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
> > > > > +                                             count, priv->domain_handle,
> > > > > +                                             &pch_pic_domain_ops, priv);
> > > > > +
> > > > > +     if (!priv->pic_domain) {
> > > > > +             pr_err("Failed to create IRQ domain\n");
> > > > > +             goto iounmap_base;
> > > > > +     }
> > > > > +
> > > > > +     pch_pic_reset(priv);
> > > > > +     pch_pic_priv[nr_pch_pics++] = priv;
> > > > > +
> > > > > +     register_syscore_ops(&pch_pic_syscore_ops);
> > > > > +
> > > > > +     return priv->domain_handle;
> > > > > +
> > > > > +iounmap_base:
> > > > > +     iounmap(priv->base);
> > > > > +free_priv:
> > > > > +     kfree(priv);
> > > > > +
> > > > > +     return NULL;
> > > > > +}
> > > > > +
> > > > > +#endif
> > > >
> > > > A lot of this code is common with its OF counterpart. How about making
> > > > this logic common?
> > > OK, let me think about.
> > Though pch_pic_acpi_init() is similar to pch_pic_of_init(), but it is
> > difficult to make a common function, because we cannot prepare
> > everything before the common function. For example, ioremap() can be
> > the common part, but pch_pic_acpi_init() should get the vector count
> > after ioremap(). If we use an argument to distinguish the caller in
> > the common function, the complexity increases and seems no benefits.
>
> All firmware implementations allocate private data structures, irq
> domains, map MMIO regions, etc. All that can be common. We even have
> APIs that deal with both firmware interfaces.
>
> As for the 'read the vector count from the HW', what does it have to
> do with driving the HW using DT or ACPI? The HW doesn't *know*. If you
> are conflating HW changes and firmware interfaces, then you have
> already lost.
OK, I know, thanks.

Huacai
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2021-08-16  3:20 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-06  3:08 [PATCH 0/9] irqchip: Add LoongArch-related irqchip drivers Huacai Chen
2021-07-06  3:08 ` [PATCH 1/9] irqchip: Adjust Kconfig for Loongson Huacai Chen
2021-07-06  3:08 ` [PATCH 2/9] irqchip/loongson-pch-pic: Improve edge triggered interrupt support Huacai Chen
2021-07-06 13:06   ` Marc Zyngier
2021-07-09  3:00     ` Huacai Chen
2021-08-04 14:23       ` Marc Zyngier
2021-08-05 13:06         ` Huacai Chen
2021-07-06  3:08 ` [PATCH 3/9] irqchip/loongson-pch-pic: Add ACPI init support Huacai Chen
2021-07-06 13:10   ` Marc Zyngier
2021-07-07  4:50     ` Huacai Chen
2021-08-12 12:23       ` Huacai Chen
2021-08-12 13:28         ` Marc Zyngier
2021-08-16  3:19           ` Huacai Chen
2021-07-06  3:08 ` [PATCH 4/9] irqchip/loongson-pch-msi: " Huacai Chen
2021-07-06 13:12   ` Marc Zyngier
2021-07-07  4:51     ` Huacai Chen
2021-07-06  3:09 ` [PATCH 5/9] irqchip/loongson-htvec: " Huacai Chen
2021-07-06 13:13   ` Marc Zyngier
2021-07-07  4:52     ` Huacai Chen
2021-07-06  3:09 ` [PATCH 6/9] irqchip/loongson-liointc: " Huacai Chen
2021-07-09  0:59   ` kernel test robot
2021-07-06  3:09 ` [PATCH 7/9] irqchip: Add LoongArch CPU interrupt controller support Huacai Chen
2021-07-06 13:21   ` Marc Zyngier
2021-07-07  4:57     ` Huacai Chen
2021-07-06  3:09 ` [PATCH 8/9] irqchip: Add Loongson Extended I/O " Huacai Chen
2021-07-08 20:53   ` kernel test robot
2021-07-06  3:09 ` [PATCH 9/9] irqchip: Add Loongson PCH LPC " Huacai Chen
2021-07-08 22:27   ` kernel test robot

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.