- * [PATCH v6 1/8] of/irq: Introduce for_each_of_imap_item
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 2/8] of: unittest: Add a test case for for_each_of_imap_item iterator Herve Codina (Schneider Electric)
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
for_each_of_imap_item is an iterator designed to help a driver to parse
an interrupt-map property.
Indeed some drivers need to know details about the interrupt mapping
described in the device-tree in order to set internal registers
accordingly.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 drivers/of/irq.c       | 70 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_irq.h | 41 ++++++++++++++++++++++++-
 2 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 65c3c23255b7..ca7d51d07047 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -157,6 +157,76 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph
 	return imap;
 }
 
+int of_imap_parser_init(struct of_imap_parser *parser, struct device_node *node,
+			struct of_imap_item *item)
+{
+	int imaplen;
+	u32 tmp;
+	int ret;
+
+	/*
+	 * parent_offset is the offset where the parent part is starting.
+	 * In other words, the offset where the parent interrupt controller
+	 * phandle is present.
+	 *
+	 * Compute this offset (child #interrupt-cells + child #address-cells)
+	 */
+	parser->parent_offset = of_bus_n_addr_cells(node);
+
+	ret = of_property_read_u32(node, "#interrupt-cells", &tmp);
+	if (ret)
+		return ret;
+
+	parser->parent_offset += tmp;
+
+	if (WARN(parser->parent_offset > ARRAY_SIZE(item->child_imap),
+		 "child part size = %u, cannot fit in array of %zu items",
+		 parser->parent_offset, ARRAY_SIZE(item->child_imap)))
+		return -EINVAL;
+
+	parser->imap = of_get_property(node, "interrupt-map", &imaplen);
+	if (!parser->imap)
+		return -ENOENT;
+
+	imaplen /= sizeof(*parser->imap);
+	parser->imap_end = parser->imap + imaplen;
+
+	memset(item, 0, sizeof(*item));
+	item->child_imap_count = parser->parent_offset;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_imap_parser_init);
+
+struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
+					struct of_imap_item *item)
+{
+	const __be32 *imap_parent, *imap_next;
+	int i;
+
+	/* Release previously get parent node */
+	of_node_put(item->parent_args.np);
+
+	if (parser->imap + parser->parent_offset + 1 >= parser->imap_end)
+		return NULL;
+
+	imap_parent = parser->imap + parser->parent_offset;
+
+	imap_next = of_irq_parse_imap_parent(imap_parent,
+					     parser->imap_end - imap_parent,
+					     &item->parent_args);
+	if (!imap_next)
+		return NULL;
+
+	for (i = 0; i < parser->parent_offset; i++)
+		item->child_imap[i] = be32_to_cpu(*(parser->imap + i));
+
+	parser->imap = imap_next;
+
+	return item;
+}
+EXPORT_SYMBOL_GPL(of_imap_parser_one);
+
 /**
  * of_irq_parse_raw - Low level interrupt tree parsing
  * @addr:	address specifier (start of "reg" property of the device) in be32 format
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 1db8543dfc8a..7edb64edb0d6 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -11,6 +11,30 @@
 
 typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
 
+struct of_imap_parser {
+	struct device_node *node;
+	const __be32 *imap;
+	const __be32 *imap_end;
+	u32 parent_offset;
+};
+
+struct of_imap_item {
+	struct of_phandle_args parent_args;
+	u32 child_imap_count;
+	u32 child_imap[16]; /* Arbitrary size.
+			     * Should be #address-cells + #interrupt-cells but
+			     * avoid using allocation and so, expect that 16
+			     * should be enough
+			     */
+};
+
+/*
+ * If the iterator is exited prematurely (break, goto, return) of_node_put() has
+ * to be called on item.parent_args.np
+ */
+#define for_each_of_imap_item(parser, item) \
+	for (; of_imap_parser_one(parser, item);)
+
 /*
  * Workarounds only applied to 32bit powermac machines
  */
@@ -47,6 +71,11 @@ extern int of_irq_get_byname(struct device_node *dev, const char *name);
 extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
+extern int of_imap_parser_init(struct of_imap_parser *parser,
+			       struct device_node *node,
+			       struct of_imap_item *item);
+extern struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
+					       struct of_imap_item *item);
 extern struct irq_domain *of_msi_get_domain(struct device *dev,
 					    const struct device_node *np,
 					    enum irq_domain_bus_token token);
@@ -85,7 +114,17 @@ static inline void *of_irq_find_parent(struct device_node *child)
 {
 	return NULL;
 }
-
+static inline int of_imap_parser_init(struct of_imap_parser *parser,
+				      struct device_node *node,
+				      struct of_imap_item *item)
+{
+	return -ENOSYS;
+}
+static inline struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
+						      struct of_imap_item *item)
+{
+	return NULL;
+}
 static inline struct irq_domain *of_msi_get_domain(struct device *dev,
 						   struct device_node *np,
 						   enum irq_domain_bus_token token)
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 2/8] of: unittest: Add a test case for for_each_of_imap_item iterator
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 1/8] of/irq: Introduce for_each_of_imap_item Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 3/8] irqchip/ls-extirq: Use " Herve Codina (Schneider Electric)
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
Recently for_each_of_imap_item iterator has been introduce to help
drivers in parsing the interrupt-map property.
Add a test case for this iterator.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../of/unittest-data/tests-interrupts.dtsi    |   9 ++
 drivers/of/unittest.c                         | 116 ++++++++++++++++++
 2 files changed, 125 insertions(+)
diff --git a/drivers/of/unittest-data/tests-interrupts.dtsi b/drivers/of/unittest-data/tests-interrupts.dtsi
index 4ccb54f91c30..974f888c9b15 100644
--- a/drivers/of/unittest-data/tests-interrupts.dtsi
+++ b/drivers/of/unittest-data/tests-interrupts.dtsi
@@ -50,6 +50,15 @@ test_intmap1: intmap1 {
 				interrupt-map = <0x5000 1 2 &test_intc0 15>;
 			};
 
+			intmap2 {
+				#interrupt-cells = <2>;
+				#address-cells = <0>;
+				interrupt-map = <1 11 &test_intc0 100>,
+						<2 22 &test_intc1 200 201 202>,
+						<3 33 &test_intc2 300 301>,
+						<4 44 &test_intc2 400 401>;
+			};
+
 			test_intc_intmap0: intc-intmap0 {
 				#interrupt-cells = <1>;
 				#address-cells = <1>;
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 388e9ec2cccf..d88a12f23ad5 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1654,6 +1654,121 @@ static void __init of_unittest_parse_interrupts_extended(void)
 	of_node_put(np);
 }
 
+struct of_unittest_expected_imap_item {
+	u32 child_imap_count;
+	u32 child_imap[2];
+	const char *parent_path;
+	int parent_args_count;
+	u32 parent_args[3];
+};
+
+static const struct of_unittest_expected_imap_item of_unittest_expected_imap_items[] = {
+	{
+		.child_imap_count = 2,
+		.child_imap = {1, 11},
+		.parent_path = "/testcase-data/interrupts/intc0",
+		.parent_args_count = 1,
+		.parent_args = {100},
+	}, {
+		.child_imap_count = 2,
+		.child_imap = {2, 22},
+		.parent_path = "/testcase-data/interrupts/intc1",
+		.parent_args_count = 3,
+		.parent_args = {200, 201, 202},
+	}, {
+		.child_imap_count = 2,
+		.child_imap = {3, 33},
+		.parent_path = "/testcase-data/interrupts/intc2",
+		.parent_args_count = 2,
+		.parent_args = {300, 301},
+	}, {
+		.child_imap_count = 2,
+		.child_imap = {4, 44},
+		.parent_path = "/testcase-data/interrupts/intc2",
+		.parent_args_count = 2,
+		.parent_args = {400, 401},
+	}
+};
+
+static void __init of_unittest_parse_interrupt_map(void)
+{
+	const struct of_unittest_expected_imap_item *expected_item;
+	struct device_node *imap_np, *expected_parent_np;
+	struct of_imap_parser imap_parser;
+	struct of_imap_item imap_item;
+	int count, ret, i;
+
+	if (of_irq_workarounds & (OF_IMAP_NO_PHANDLE | OF_IMAP_OLDWORLD_MAC))
+		return;
+
+	imap_np = of_find_node_by_path("/testcase-data/interrupts/intmap2");
+	if (!imap_np) {
+		pr_err("missing testcase data\n");
+		return;
+	}
+
+	ret = of_imap_parser_init(&imap_parser, imap_np, &imap_item);
+	if (unittest(!ret, "of_imap_parser_init(%pOF) returned error %d\n",
+		     imap_np, ret))
+		goto end;
+
+	expected_item = of_unittest_expected_imap_items;
+	count = 0;
+
+	for_each_of_imap_item(&imap_parser, &imap_item) {
+		if (unittest(count < ARRAY_SIZE(of_unittest_expected_imap_items),
+			     "imap item number %d not expected. Max number %zu\n",
+			     count, ARRAY_SIZE(of_unittest_expected_imap_items) - 1)) {
+			of_node_put(imap_item.parent_args.np);
+			goto end;
+		}
+
+		expected_parent_np = of_find_node_by_path(expected_item->parent_path);
+		if (unittest(expected_parent_np,
+			     "missing dependent testcase data (%s)\n",
+			     expected_item->parent_path)) {
+			of_node_put(imap_item.parent_args.np);
+			goto end;
+		}
+
+		unittest(imap_item.child_imap_count == expected_item->child_imap_count,
+			 "imap[%d] child_imap_count = %u, expected %u\n",
+			 count, imap_item.child_imap_count,
+			 expected_item->child_imap_count);
+
+		for (i = 0; i < expected_item->child_imap_count; i++)
+			unittest(imap_item.child_imap[i] == expected_item->child_imap[i],
+				 "imap[%d] child_imap[%d] = %u, expected %u\n",
+				 count, i, imap_item.child_imap[i],
+				 expected_item->child_imap[i]);
+
+		unittest(imap_item.parent_args.np == expected_parent_np,
+			 "imap[%d] parent np = %pOF, expected %pOF\n",
+			 count, imap_item.parent_args.np, expected_parent_np);
+
+		unittest(imap_item.parent_args.args_count == expected_item->parent_args_count,
+			 "imap[%d] parent param_count = %d, expected %d\n",
+			 count, imap_item.parent_args.args_count,
+			 expected_item->parent_args_count);
+
+		for (i = 0; i < expected_item->parent_args_count; i++)
+			unittest(imap_item.parent_args.args[i] == expected_item->parent_args[i],
+				 "imap[%d] parent param[%d] = %u, expected %u\n",
+				 count, i, imap_item.parent_args.args[i],
+				 expected_item->parent_args[i]);
+
+		of_node_put(expected_parent_np);
+		count++;
+		expected_item++;
+	}
+
+	unittest(count == ARRAY_SIZE(of_unittest_expected_imap_items),
+		 "Missing items. %d parsed, expected %zu\n",
+		 count, ARRAY_SIZE(of_unittest_expected_imap_items));
+end:
+	of_node_put(imap_np);
+}
+
 #if IS_ENABLED(CONFIG_OF_DYNAMIC)
 static void __init of_unittest_irq_refcount(void)
 {
@@ -4395,6 +4510,7 @@ static int __init of_unittest(void)
 	of_unittest_changeset_prop();
 	of_unittest_parse_interrupts();
 	of_unittest_parse_interrupts_extended();
+	of_unittest_parse_interrupt_map();
 	of_unittest_irq_refcount();
 	of_unittest_dma_get_max_cpu_address();
 	of_unittest_parse_dma_ranges();
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 3/8] irqchip/ls-extirq: Use for_each_of_imap_item iterator
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 1/8] of/irq: Introduce for_each_of_imap_item Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 2/8] of: unittest: Add a test case for for_each_of_imap_item iterator Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 4/8] irqchip/renesas-rza1: " Herve Codina (Schneider Electric)
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
The ls-extirq driver parses the interrupt-map property. It does it using
open code.
Recently for_each_of_imap_item iterator has been introduce to help
drivers in this parsing.
Convert the ls-extirq driver to use the for_each_of_imap_item
iterator instead of open code.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
---
 drivers/irqchip/irq-ls-extirq.c | 47 ++++++++++++---------------------
 1 file changed, 17 insertions(+), 30 deletions(-)
diff --git a/drivers/irqchip/irq-ls-extirq.c b/drivers/irqchip/irq-ls-extirq.c
index 50a7b38381b9..ed8755777349 100644
--- a/drivers/irqchip/irq-ls-extirq.c
+++ b/drivers/irqchip/irq-ls-extirq.c
@@ -125,45 +125,32 @@ static const struct irq_domain_ops extirq_domain_ops = {
 static int
 ls_extirq_parse_map(struct ls_extirq_data *priv, struct device_node *node)
 {
-	const __be32 *map;
-	u32 mapsize;
+	struct of_imap_parser imap_parser;
+	struct of_imap_item imap_item;
 	int ret;
 
-	map = of_get_property(node, "interrupt-map", &mapsize);
-	if (!map)
-		return -ENOENT;
-	if (mapsize % sizeof(*map))
-		return -EINVAL;
-	mapsize /= sizeof(*map);
+	ret = of_imap_parser_init(&imap_parser, node, &imap_item);
+	if (ret)
+		return ret;
 
-	while (mapsize) {
+	for_each_of_imap_item(&imap_parser, &imap_item) {
 		struct device_node *ipar;
-		u32 hwirq, intsize, j;
+		u32 hwirq;
+		int i;
 
-		if (mapsize < 3)
-			return -EINVAL;
-		hwirq = be32_to_cpup(map);
-		if (hwirq >= MAXIRQ)
+		hwirq = imap_item.child_imap[0];
+		if (hwirq >= MAXIRQ) {
+			of_node_put(imap_item.parent_args.np);
 			return -EINVAL;
+		}
 		priv->nirq = max(priv->nirq, hwirq + 1);
 
-		ipar = of_find_node_by_phandle(be32_to_cpup(map + 2));
-		map += 3;
-		mapsize -= 3;
-		if (!ipar)
-			return -EINVAL;
-		priv->map[hwirq].fwnode = &ipar->fwnode;
-		ret = of_property_read_u32(ipar, "#interrupt-cells", &intsize);
-		if (ret)
-			return ret;
-
-		if (intsize > mapsize)
-			return -EINVAL;
+		ipar = of_node_get(imap_item.parent_args.np);
+		priv->map[hwirq].fwnode = of_fwnode_handle(ipar);
 
-		priv->map[hwirq].param_count = intsize;
-		for (j = 0; j < intsize; ++j)
-			priv->map[hwirq].param[j] = be32_to_cpup(map++);
-		mapsize -= intsize;
+		priv->map[hwirq].param_count = imap_item.parent_args.args_count;
+		for (i = 0; i < priv->map[hwirq].param_count; i++)
+			priv->map[hwirq].param[i] = imap_item.parent_args.args[i];
 	}
 	return 0;
 }
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 4/8] irqchip/renesas-rza1: Use for_each_of_imap_item iterator
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (2 preceding siblings ...)
  2025-10-27 12:35 ` [PATCH v6 3/8] irqchip/ls-extirq: Use " Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 5/8] ARM: dts: r9a06g032: Add GPIO controllers Herve Codina (Schneider Electric)
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
The renesas-rza1 driver parses the interrupt-map property. It does it
using open code.
Recently for_each_of_imap_item iterator has been introduce to help
drivers in this parsing.
Convert the renesas-rza1 driver to use the for_each_of_imap_item
iterator instead of open code.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 drivers/irqchip/irq-renesas-rza1.c | 43 +++++++++++-------------------
 1 file changed, 16 insertions(+), 27 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rza1.c b/drivers/irqchip/irq-renesas-rza1.c
index 6047a524ac77..370d968b2398 100644
--- a/drivers/irqchip/irq-renesas-rza1.c
+++ b/drivers/irqchip/irq-renesas-rza1.c
@@ -142,47 +142,36 @@ static const struct irq_domain_ops rza1_irqc_domain_ops = {
 static int rza1_irqc_parse_map(struct rza1_irqc_priv *priv,
 			       struct device_node *gic_node)
 {
+	struct of_imap_parser imap_parser;
 	struct device *dev = priv->dev;
-	unsigned int imaplen, i, j;
+	struct of_imap_item imap_item;
 	struct device_node *ipar;
-	const __be32 *imap;
-	u32 intsize;
+	unsigned int j;
+	u32 i = 0;
 	int ret;
 
-	imap = of_get_property(dev->of_node, "interrupt-map", &imaplen);
-	if (!imap)
-		return -EINVAL;
-
-	for (i = 0; i < IRQC_NUM_IRQ; i++) {
-		if (imaplen < 3)
-			return -EINVAL;
+	ret = of_imap_parser_init(&imap_parser, dev->of_node, &imap_item);
+	if (ret)
+		return ret;
 
+	for_each_of_imap_item(&imap_parser, &imap_item) {
 		/* Check interrupt number, ignore sense */
-		if (be32_to_cpup(imap) != i)
+		if (imap_item.child_imap[0] != i) {
+			of_node_put(imap_item.parent_args.np);
 			return -EINVAL;
+		}
 
-		ipar = of_find_node_by_phandle(be32_to_cpup(imap + 2));
+		ipar  = imap_item.parent_args.np;
 		if (ipar != gic_node) {
 			of_node_put(ipar);
 			return -EINVAL;
 		}
 
-		imap += 3;
-		imaplen -= 3;
-
-		ret = of_property_read_u32(ipar, "#interrupt-cells", &intsize);
-		of_node_put(ipar);
-		if (ret)
-			return ret;
-
-		if (imaplen < intsize)
-			return -EINVAL;
-
-		priv->map[i].args_count = intsize;
-		for (j = 0; j < intsize; j++)
-			priv->map[i].args[j] = be32_to_cpup(imap++);
+		priv->map[i].args_count = imap_item.parent_args.args_count;
+		for (j = 0; j < priv->map[i].args_count; j++)
+			priv->map[i].args[j] = imap_item.parent_args.args[j];
 
-		imaplen -= intsize;
+		i++;
 	}
 
 	return 0;
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 5/8] ARM: dts: r9a06g032: Add GPIO controllers
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (3 preceding siblings ...)
  2025-10-27 12:35 ` [PATCH v6 4/8] irqchip/renesas-rza1: " Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 6/8] dt-bindings: soc: renesas: Add the Renesas RZ/N1 GPIO Interrupt Multiplexer Herve Codina (Schneider Electric)
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni, Bartosz Golaszewski
Add GPIO controllers (Synosys DesignWare IPs) available in the
r9a06g032 (RZ/N1D) SoC.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 arch/arm/boot/dts/renesas/r9a06g032.dtsi | 121 +++++++++++++++++++++++
 1 file changed, 121 insertions(+)
diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
index 13a60656b044..da977cdd8487 100644
--- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
@@ -499,6 +499,127 @@ gic: interrupt-controller@44101000 {
 				<GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
+		/*
+		 * The GPIO mapping to the corresponding pins is not obvious.
+		 * See the hardware documentation for details.
+		 */
+		gpio0: gpio@5000b000 {
+			compatible = "snps,dw-apb-gpio";
+			reg = <0x5000b000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&sysctrl R9A06G032_HCLK_GPIO0>;
+			clock-names = "bus";
+			status = "disabled";
+
+			/* GPIO0a[0]      connected to pin  GPIO0      */
+			/* GPIO0a[1..2]   connected to pins GPIO3..4   */
+			/* GPIO0a[3..4]   connected to pins GPIO9..10  */
+			/* GPIO0a[5]      connected to pin  GPIO12     */
+			/* GPIO0a[6..7]   connected to pins GPIO15..16 */
+			/* GPIO0a[8..9]   connected to pins GPIO21..22 */
+			/* GPIO0a[10]     connected to pin  GPIO24     */
+			/* GPIO0a[11..12] connected to pins GPIO27..28 */
+			/* GPIO0a[13..14] connected to pins GPIO33..34 */
+			/* GPIO0a[15]     connected to pin  GPIO36     */
+			/* GPIO0a[16..17] connected to pins GPIO39..40 */
+			/* GPIO0a[18..19] connected to pins GPIO45..46 */
+			/* GPIO0a[20]     connected to pin  GPIO48     */
+			/* GPIO0a[21..22] connected to pins GPIO51..52 */
+			/* GPIO0a[23..24] connected to pins GPIO57..58 */
+			/* GPIO0a[25..31] connected to pins GPIO62..68 */
+			gpio0a: gpio-port@0 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <32>;
+				reg = <0>;
+			};
+
+			/* GPIO0b[0..1]   connected to pins GPIO1..2   */
+			/* GPIO0b[2..5]   connected to pins GPIO5..8   */
+			/* GPIO0b[6]      connected to pin  GPIO11     */
+			/* GPIO0b[7..8]   connected to pins GPIO13..14 */
+			/* GPIO0b[9..12]  connected to pins GPIO17..20 */
+			/* GPIO0b[13]     connected to pin  GPIO23     */
+			/* GPIO0b[14..15] connected to pins GPIO25..26 */
+			/* GPIO0b[16..19] connected to pins GPIO29..32 */
+			/* GPIO0b[20]     connected to pin  GPIO35     */
+			/* GPIO0b[21..22] connected to pins GPIO37..38 */
+			/* GPIO0b[23..26] connected to pins GPIO41..44 */
+			/* GPIO0b[27]     connected to pin  GPIO47     */
+			/* GPIO0b[28..29] connected to pins GPIO49..50 */
+			/* GPIO0b[30..31] connected to pins GPIO53..54 */
+			gpio0b: gpio-port@1 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <32>;
+				reg = <1>;
+			};
+		};
+
+		gpio1: gpio@5000c000 {
+			compatible = "snps,dw-apb-gpio";
+			reg = <0x5000c000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&sysctrl R9A06G032_HCLK_GPIO1>;
+			clock-names = "bus";
+			status = "disabled";
+
+			/* GPIO1a[0..4]  connected to pins GPIO69..73 */
+			/* GPIO1a[5..31] connected to pins GPIO95..121 */
+			gpio1a: gpio-port@0 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <32>;
+				reg = <0>;
+			};
+
+			/* GPIO1b[0..1]   connected to pins GPIO55..56 */
+			/* GPIO1b[2..4]   connected to pins GPIO59..61 */
+			/* GPIO1b[5..25]  connected to pins GPIO74..94 */
+			/* GPIO1b[26..31] connected to pins GPIO150..155 */
+			gpio1b: gpio-port@1 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <32>;
+				reg = <1>;
+			};
+		};
+
+		gpio2: gpio@5000d000 {
+			compatible = "snps,dw-apb-gpio";
+			reg = <0x5000d000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
+			clock-names = "bus";
+			status = "disabled";
+
+			/* GPIO2a[0..27]  connected to pins GPIO122..149 */
+			/* GPIO2a[28..31] connected to pins GPIO156..159 */
+			gpio2a: gpio-port@0 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <32>;
+				reg = <0>;
+			};
+
+			/* GPIO2b[0..9] connected to pins GPIO160..169 */
+			gpio2b: gpio-port@1 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				snps,nr-gpios = <10>;
+				reg = <1>;
+			};
+		};
+
 		can0: can@52104000 {
 			compatible = "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000";
 			reg = <0x52104000 0x800>;
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 6/8] dt-bindings: soc: renesas: Add the Renesas RZ/N1 GPIO Interrupt Multiplexer
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (4 preceding siblings ...)
  2025-10-27 12:35 ` [PATCH v6 5/8] ARM: dts: r9a06g032: Add GPIO controllers Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-27 12:35 ` [PATCH v6 7/8] soc: renesas: Add support for " Herve Codina (Schneider Electric)
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
On the Renesas RZ/N1 SoC, GPIOs can generate interruptions. Those
interruption lines are multiplexed by the GPIO Interrupt Multiplexer in
order to map 32 * 3 GPIO interrupt lines to 8 GIC interrupt lines.
The GPIO interrupt multiplexer IP does nothing but select 8 GPIO
IRQ lines out of the 96 available to wire them to the GIC input lines.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../soc/renesas/renesas,rzn1-gpioirqmux.yaml  | 87 +++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/renesas/renesas,rzn1-gpioirqmux.yaml
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas,rzn1-gpioirqmux.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas,rzn1-gpioirqmux.yaml
new file mode 100644
index 000000000000..1a31c11bc3b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas,rzn1-gpioirqmux.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/renesas/renesas,rzn1-gpioirqmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/N1 SoCs GPIO Interrupt Multiplexer
+
+description: |
+   The Renesas RZ/N1 GPIO Interrupt Multiplexer multiplexes GPIO interrupt
+   lines to the interrupt controller available in the SoC.
+
+   It selects up to 8 of the 96 GPIO interrupt lines available and connect them
+   to 8 output interrupt lines.
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - renesas,r9a06g032-gpioirqmux
+      - const: renesas,rzn1-gpioirqmux
+
+  reg:
+    maxItems: 1
+
+  "#address-cells":
+    const: 0
+
+  "#interrupt-cells":
+    const: 1
+
+  interrupt-map-mask:
+    items:
+      - const: 0x7f
+
+  interrupt-map:
+    description: |
+      Specifies the mapping from external GPIO interrupt lines to the output
+      interrupts. The array has up to 8 items defining the mapping related to
+      the output line 0 (GIC 103) up to the output line 7 (GIC 110).
+
+      The child interrupt number set in arrays items is computed using the
+      following formula:
+          gpio_bank * 32 + gpio_number
+      with:
+        - gpio_bank: The GPIO bank number
+            - 0 for GPIO0A,
+            - 1 for GPIO1A,
+            - 2 for GPIO2A
+        - gpio_number: Number of the gpio in the bank (0..31)
+    minItems: 1
+    maxItems: 8
+
+required:
+  - compatible
+  - reg
+  - "#address-cells"
+  - "#interrupt-cells"
+  - interrupt-map-mask
+  - interrupt-map
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    gic: interrupt-controller {
+        interrupt-controller;
+        #address-cells = <0>;
+        #interrupt-cells = <3>;
+    };
+
+    interrupt-controller@51000480 {
+        compatible = "renesas,r9a06g032-gpioirqmux", "renesas,rzn1-gpioirqmux";
+        reg = <0x51000480 0x20>;
+        #address-cells = <0>;
+        #interrupt-cells = <1>;
+        interrupt-map-mask = <0x7f>;
+        interrupt-map =
+            <32 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* line 0, GPIO1A.0 */
+            <89 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, /* line 1, GPIO2A.25 */
+            <9 &gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; /* line 3, GPIO0A.9 */
+    };
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * [PATCH v6 7/8] soc: renesas: Add support for Renesas RZ/N1 GPIO Interrupt Multiplexer
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (5 preceding siblings ...)
  2025-10-27 12:35 ` [PATCH v6 6/8] dt-bindings: soc: renesas: Add the Renesas RZ/N1 GPIO Interrupt Multiplexer Herve Codina (Schneider Electric)
@ 2025-10-27 12:35 ` Herve Codina (Schneider Electric)
  2025-10-28  8:52   ` Wolfram Sang
  2025-10-27 12:36 ` [PATCH v6 8/8] ARM: dts: r9a06g032: Add support for GPIO interrupts Herve Codina (Schneider Electric)
  2025-10-29 14:14 ` [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Linus Walleij
  8 siblings, 1 reply; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:35 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
On the Renesas RZ/N1 SoC, GPIOs can generate interruptions. Those
interruption lines are multiplexed by the GPIO Interrupt Multiplexer in
order to map 32 * 3 GPIO interrupt lines to 8 GIC interrupt lines.
The GPIO interrupt multiplexer IP does nothing but select 8 GPIO
IRQ lines out of the 96 available to wire them to the GIC input lines.
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
---
 drivers/soc/renesas/Kconfig       |   4 +
 drivers/soc/renesas/Makefile      |   1 +
 drivers/soc/renesas/rzn1_irqmux.c | 133 ++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 drivers/soc/renesas/rzn1_irqmux.c
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 340a1ff7e92b..71865778b058 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -62,6 +62,7 @@ config ARCH_RZN1
 	select PM
 	select PM_GENERIC_DOMAINS
 	select ARM_AMBA
+	select RZN1_IRQMUX
 
 if ARM && ARCH_RENESAS
 
@@ -459,6 +460,9 @@ config PWC_RZV2M
 config RST_RCAR
 	bool "Reset Controller support for R-Car" if COMPILE_TEST
 
+config RZN1_IRQMUX
+	bool "Renesas RZ/N1 GPIO IRQ multiplexer support" if COMPILE_TEST
+
 config SYSC_RZ
 	bool "System controller for RZ SoCs" if COMPILE_TEST
 	select MFD_SYSCON
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 3bdcc6a395d5..33d44d964d61 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -14,4 +14,5 @@ obj-$(CONFIG_SYS_R9A09G057)	+= r9a09g057-sys.o
 # Family
 obj-$(CONFIG_PWC_RZV2M)		+= pwc-rzv2m.o
 obj-$(CONFIG_RST_RCAR)		+= rcar-rst.o
+obj-$(CONFIG_RZN1_IRQMUX)	+= rzn1_irqmux.o
 obj-$(CONFIG_SYSC_RZ)		+= rz-sysc.o
diff --git a/drivers/soc/renesas/rzn1_irqmux.c b/drivers/soc/renesas/rzn1_irqmux.c
new file mode 100644
index 000000000000..b4b43aa3e496
--- /dev/null
+++ b/drivers/soc/renesas/rzn1_irqmux.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RZ/N1 GPIO Interrupt Multiplexer
+ *
+ * Copyright 2025 Schneider Electric
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/*
+ * Up to 8 output lines are connected to GIC SPI interrupt controller
+ * starting at IRQ 103.
+ */
+#define RZN1_IRQMUX_GIC_SPI_BASE	103
+#define RZN1_IRQMUX_NUM_OUTPUTS		8
+
+static int rzn1_irqmux_parent_args_to_line_index(struct device *dev,
+						 const struct of_phandle_args *parent_args)
+{
+	/*
+	 * The parent interrupt should be one of the GIC controller.
+	 * Three arguments must be provided.
+	 *  - args[0]: GIC_SPI
+	 *  - args[1]: The GIC interrupt number
+	 *  - args[2]: The interrupt flags
+	 *
+	 * We retrieve the line index based on the GIC interrupt number
+	 * provided.
+	 */
+
+	if (parent_args->args_count != 3 ||
+	    parent_args->args[0] != GIC_SPI) {
+		dev_err(dev, "Invalid interrupt-map item\n");
+		return -EINVAL;
+	}
+
+	if (parent_args->args[1] < RZN1_IRQMUX_GIC_SPI_BASE ||
+	    parent_args->args[1] >= RZN1_IRQMUX_GIC_SPI_BASE + RZN1_IRQMUX_NUM_OUTPUTS) {
+		dev_err(dev, "Invalid GIC interrupt %u\n", parent_args->args[1]);
+		return -EINVAL;
+	}
+
+	return parent_args->args[1] - RZN1_IRQMUX_GIC_SPI_BASE;
+}
+
+static int rzn1_irqmux_setup(struct device *dev, struct device_node *np, u32 __iomem *regs)
+{
+	DECLARE_BITMAP(index_done, RZN1_IRQMUX_NUM_OUTPUTS) = {};
+	struct of_imap_parser imap_parser;
+	struct of_imap_item imap_item;
+	int index;
+	int ret;
+	u32 tmp;
+
+	/* We support only #interrupt-cells = <1> and #address-cells = <0> */
+	ret = of_property_read_u32(np, "#interrupt-cells", &tmp);
+	if (ret)
+		return ret;
+	if (tmp != 1)
+		return -EINVAL;
+
+	ret = of_property_read_u32(np, "#address-cells", &tmp);
+	if (ret)
+		return ret;
+	if (tmp != 0)
+		return -EINVAL;
+
+	ret = of_imap_parser_init(&imap_parser, np, &imap_item);
+	if (ret)
+		return ret;
+
+	for_each_of_imap_item(&imap_parser, &imap_item) {
+		index = rzn1_irqmux_parent_args_to_line_index(dev, &imap_item.parent_args);
+		if (index < 0) {
+			of_node_put(imap_item.parent_args.np);
+			return index;
+		}
+
+		if (test_and_set_bit(index, index_done)) {
+			of_node_put(imap_item.parent_args.np);
+			dev_err(dev, "Mux output line already defined\n");
+			return -EINVAL;
+		}
+
+		/*
+		 * The child #address-cells is 0 (already checked). The first
+		 * value in imap item is the src hwirq.
+		 */
+		writel(imap_item.child_imap[0], regs + index);
+	}
+
+	return 0;
+}
+
+static int rzn1_irqmux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	u32 __iomem *regs;
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	return rzn1_irqmux_setup(dev, np, regs);
+}
+
+static const struct of_device_id rzn1_irqmux_of_match[] = {
+	{ .compatible = "renesas,rzn1-gpioirqmux", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzn1_irqmux_of_match);
+
+static struct platform_driver rzn1_irqmux_driver = {
+	.probe = rzn1_irqmux_probe,
+	.driver = {
+		.name = "rzn1_irqmux",
+		.of_match_table = rzn1_irqmux_of_match,
+	},
+};
+module_platform_driver(rzn1_irqmux_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("Renesas RZ/N1 GPIO IRQ Multiplexer Driver");
+MODULE_LICENSE("GPL");
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * Re: [PATCH v6 7/8] soc: renesas: Add support for Renesas RZ/N1 GPIO Interrupt Multiplexer
  2025-10-27 12:35 ` [PATCH v6 7/8] soc: renesas: Add support for " Herve Codina (Schneider Electric)
@ 2025-10-28  8:52   ` Wolfram Sang
  0 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2025-10-28  8:52 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Thomas Gleixner, Hoan Tran, Linus Walleij, Bartosz Golaszewski,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Saravana Kannan, Serge Semin,
	Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
[-- Attachment #1: Type: text/plain, Size: 1766 bytes --]
Hi Herve,
On Mon, Oct 27, 2025 at 01:35:59PM +0100, Herve Codina (Schneider Electric) wrote:
> On the Renesas RZ/N1 SoC, GPIOs can generate interruptions. Those
> interruption lines are multiplexed by the GPIO Interrupt Multiplexer in
> order to map 32 * 3 GPIO interrupt lines to 8 GIC interrupt lines.
> 
> The GPIO interrupt multiplexer IP does nothing but select 8 GPIO
> IRQ lines out of the 96 available to wire them to the GIC input lines.
> 
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Good news first:
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
I can access GPIO LEDs on my board and PHY interrupts also work.
> +	if (parent_args->args[1] < RZN1_IRQMUX_GIC_SPI_BASE ||
> +	    parent_args->args[1] >= RZN1_IRQMUX_GIC_SPI_BASE + RZN1_IRQMUX_NUM_OUTPUTS) {
> +		dev_err(dev, "Invalid GIC interrupt %u\n", parent_args->args[1]);
> +		return -EINVAL;
> +	}
I really like this solution. I think I suggested it before but can't
recall the details. And it is not worth digging it up again. Looks good,
works, perfect.
...
> +static int rzn1_irqmux_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	u32 __iomem *regs;
> +
> +	regs = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	return rzn1_irqmux_setup(dev, np, regs);
The only super minor thing is that we could fold rzn1_irqmux_setup()
into probe() according to my taste. But I am also fine as is. Looking
really forward to see this series finally going upstream.
Thanks again for your work on this!
   Wolfram
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply	[flat|nested] 12+ messages in thread
 
- * [PATCH v6 8/8] ARM: dts: r9a06g032: Add support for GPIO interrupts
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (6 preceding siblings ...)
  2025-10-27 12:35 ` [PATCH v6 7/8] soc: renesas: Add support for " Herve Codina (Schneider Electric)
@ 2025-10-27 12:36 ` Herve Codina (Schneider Electric)
  2025-10-28  9:07   ` Wolfram Sang
  2025-10-29 14:14 ` [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Linus Walleij
  8 siblings, 1 reply; 12+ messages in thread
From: Herve Codina (Schneider Electric) @ 2025-10-27 12:36 UTC (permalink / raw)
  To: Thomas Gleixner, Wolfram Sang, Hoan Tran, Linus Walleij,
	Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Saravana Kannan,
	Serge Semin, Herve Codina
  Cc: Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni, Bartosz Golaszewski
In the RZ/N1 SoC, the GPIO interrupts are multiplexed using the GPIO
Interrupt Multiplexer.
Add the multiplexer node and connect GPIO interrupt lines to the
multiplexer.
The interrupt-map available in the multiplexer node has to be updated in
dts files depending on the GPIO usage. Indeed, the usage of an interrupt
for a GPIO is board dependent.
Up to 8 GPIOs can be used as an interrupt line (one per multiplexer
output interrupt).
Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 arch/arm/boot/dts/renesas/r9a06g032.dtsi | 41 ++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
index da977cdd8487..c7196e720c6c 100644
--- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
@@ -534,6 +534,14 @@ gpio0a: gpio-port@0 {
 				#gpio-cells = <2>;
 				snps,nr-gpios = <32>;
 				reg = <0>;
+
+				interrupt-controller;
+				interrupt-parent = <&gpioirqmux>;
+				interrupts = < 0  1  2  3  4  5  6  7
+					       8  9 10 11 12 13 14 15
+					      16 17 18 19 20 21 22 23
+					      24 25 26 27 28 29 30 31 >;
+				#interrupt-cells = <2>;
 			};
 
 			/* GPIO0b[0..1]   connected to pins GPIO1..2   */
@@ -576,6 +584,14 @@ gpio1a: gpio-port@0 {
 				#gpio-cells = <2>;
 				snps,nr-gpios = <32>;
 				reg = <0>;
+
+				interrupt-controller;
+				interrupt-parent = <&gpioirqmux>;
+				interrupts = < 32 33 34 35 36 37 38 39
+					       40 41 42 43 44 45 46 47
+					       48 49 50 51 52 53 54 55
+					       56 57 58 59 60 61 62 63 >;
+				#interrupt-cells = <2>;
 			};
 
 			/* GPIO1b[0..1]   connected to pins GPIO55..56 */
@@ -608,6 +624,14 @@ gpio2a: gpio-port@0 {
 				#gpio-cells = <2>;
 				snps,nr-gpios = <32>;
 				reg = <0>;
+
+				interrupt-controller;
+				interrupt-parent = <&gpioirqmux>;
+				interrupts = < 64 65 66 67 68 69 70 71
+					       72 73 74 75 76 77 78 79
+					       80 81 82 83 84 85 86 87
+					       88 89 90 91 92 93 94 95 >;
+				#interrupt-cells = <2>;
 			};
 
 			/* GPIO2b[0..9] connected to pins GPIO160..169 */
@@ -620,6 +644,23 @@ gpio2b: gpio-port@1 {
 			};
 		};
 
+		gpioirqmux: interrupt-controller@51000480 {
+			compatible = "renesas,r9a06g032-gpioirqmux", "renesas,rzn1-gpioirqmux";
+			reg = <0x51000480 0x20>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			interrupt-map-mask = <0x7f>;
+
+			/*
+			 * Example mapping entry. Board DTs need to overwrite
+			 * 'interrupt-map' with their specific mapping. Check
+			 * the irqmux binding documentation for details.
+			 */
+			interrupt-map = <0 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+
+			status = "disabled";
+		};
+
 		can0: can@52104000 {
 			compatible = "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000";
 			reg = <0x52104000 0x800>;
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 12+ messages in thread
- * Re: [PATCH v6 8/8] ARM: dts: r9a06g032: Add support for GPIO interrupts
  2025-10-27 12:36 ` [PATCH v6 8/8] ARM: dts: r9a06g032: Add support for GPIO interrupts Herve Codina (Schneider Electric)
@ 2025-10-28  9:07   ` Wolfram Sang
  0 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2025-10-28  9:07 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Thomas Gleixner, Hoan Tran, Linus Walleij, Bartosz Golaszewski,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Saravana Kannan, Serge Semin,
	Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni, Bartosz Golaszewski
[-- Attachment #1: Type: text/plain, Size: 775 bytes --]
On Mon, Oct 27, 2025 at 01:36:00PM +0100, Herve Codina (Schneider Electric) wrote:
> In the RZ/N1 SoC, the GPIO interrupts are multiplexed using the GPIO
> Interrupt Multiplexer.
> 
> Add the multiplexer node and connect GPIO interrupt lines to the
> multiplexer.
> 
> The interrupt-map available in the multiplexer node has to be updated in
> dts files depending on the GPIO usage. Indeed, the usage of an interrupt
> for a GPIO is board dependent.
> 
> Up to 8 GPIOs can be used as an interrupt line (one per multiplexer
> output interrupt).
> 
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply	[flat|nested] 12+ messages in thread 
 
- * Re: [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC
  2025-10-27 12:35 [PATCH v6 0/8] gpio: renesas: Add support for GPIO and related interrupts in RZ/N1 SoC Herve Codina (Schneider Electric)
                   ` (7 preceding siblings ...)
  2025-10-27 12:36 ` [PATCH v6 8/8] ARM: dts: r9a06g032: Add support for GPIO interrupts Herve Codina (Schneider Electric)
@ 2025-10-29 14:14 ` Linus Walleij
  8 siblings, 0 replies; 12+ messages in thread
From: Linus Walleij @ 2025-10-29 14:14 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Thomas Gleixner, Wolfram Sang, Hoan Tran, Bartosz Golaszewski,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Saravana Kannan, Serge Semin,
	Phil Edworthy, linux-gpio, devicetree, linux-kernel,
	linux-renesas-soc, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
On Mon, Oct 27, 2025 at 1:36 PM Herve Codina (Schneider Electric)
<herve.codina@bootlin.com> wrote:
> This series adds support for GPIO and GPIO IRQ mux available in the
> RZ/N1 SoCs.
I think I sent some review tag at some point?
Anyways, here is another one:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
^ permalink raw reply	[flat|nested] 12+ messages in thread