Devicetree
 help / color / mirror / Atom feed
* [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support
@ 2026-06-05 21:16 Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells Markus Stockhausen
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

The Realtek Otto switch series consists of multiple devices.

- RTL838x: single core (Realtek proprietary IRQ controller)
- RTL839x: multi core (Realtek proprietary IRQ controller)
- RTL930x: multi core (Realtek proprietary IRQ controller)
- RTL931x: multi core (MIPS GIC controller)

The proprietary interrupt controller supports hardware interrupt
routing. To be precise:

- The hardware knows up to 32 different interrupts.
- These can be assigned dynamically to the normal MIPS 
  interrupts (2-6).

For this each of the 32 hardware interrupts has a routing
register. If properly set up, important interrupts (like
timers) can be prioritized.

Until now all interrupts are always routed to the low priority
MIPS interrupt 2. This series extends the driver by registering
multiple domains for the different MIPS interrupts and adding
the possibility for hardware devices to map a desired parent
interrupt.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---



Markus Stockhausen (7):
  dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt
    cells
  irqchip/irq-realtek-rtl: Use helper for parent setup
  irqchip/irq-realtek-rtl: Add interrupt data structure
  irqchip/irq-realtek-rtl: Add mask for interrupt handling
  irqchip/irq-realtek-rtl: Add a select function
  irqchip/irq-realtek-rtl: Allow shuffled interrupt order
  irqchip/irq-realtek-rtl: Activate multiple parents

 .../realtek,rtl-intc.yaml                     |   5 +-
 drivers/irqchip/irq-realtek-rtl.c             | 152 +++++++++++++-----
 2 files changed, 113 insertions(+), 44 deletions(-)

-- 
2.54.0


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

* [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:25   ` sashiko-bot
  2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

The Realtek Otto SoC interrupt controller supports hardware interrupt
routing to multiple parent CPU interrupt lines. To utilize this
multi-domain support, peripheral devices need a way to explicitly
specify their desired parent interrupt line in the device tree.

Update the "#interrupt-cells" property to accept either 1 or 2 cells.
- 1 cell: Specifies the hardware interrupt index, implicitly routing it
  to the first available parent (maintaining backward compatibility).
- 2 cells: The first cell specifies the hardware interrupt index and
  the second cell specifies the targeted parent interrupt index.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 .../bindings/interrupt-controller/realtek,rtl-intc.yaml      | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
index 833a01cdd1b1..5c52e57c6647 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
@@ -32,8 +32,9 @@ properties:
 
   "#interrupt-cells":
     description:
-      SoC interrupt line index.
-    const: 1
+      First cell is the SoC interrupt line index. Optional second cell
+      specifies the parent interrupt index to route to.
+    enum: [1, 2]
 
   reg:
     minItems: 1
-- 
2.54.0


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

* [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure Markus Stockhausen
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

With the upcoming commits the parent interrupt setup will be extended.
Relocate it into a separate helper. Although it still works only
for a single interrupt prepare the coding so it can be easily
extended with a loop for multi parent support. For this reduce the
line lengths so that the upcoming indentation still leaves the
width below 100 characters.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 60 +++++++++++++++++--------------
 1 file changed, 33 insertions(+), 27 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 2ae3be7fa633..3b4508ec7198 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -147,48 +147,35 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
-static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
+static int __init realtek_setup_parents(struct device_node *node)
 {
+	int parent_irq, num_parents = of_irq_count(node);
 	struct of_phandle_args oirq;
 	struct irq_domain *domain;
-	int cpu, parent_irq;
 
-	for_each_present_cpu(cpu) {
-		realtek_ictl_base[cpu] = of_iomap(node, cpu);
-		if (!realtek_ictl_base[cpu])
-			return -ENXIO;
-
-		/* Disable all cascaded interrupts and clear routing */
-		for (unsigned int hw_irq = 0; hw_irq < RTL_ICTL_NUM_INPUTS; hw_irq++) {
-			disable_gimr(cpu, hw_irq);
-			write_irr(cpu, hw_irq, 0);
-		}
-	}
-
-	if (WARN_ON(!of_irq_count(node))) {
+	if (WARN_ON(!num_parents)) {
 		/*
-		 * If DT contains no parent interrupts, assume MIPS CPU IRQ 2
-		 * (HW0) is connected to the first output. This is the case for
-		 * all known hardware anyway. "interrupt-map" is deprecated, so
-		 * don't bother trying to parse that.
+		 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
+		 * connected to the first output. This is the case for all known hardware.
 		 */
-		oirq.np = of_find_compatible_node(NULL, NULL, "mti,cpu-interrupt-controller");
+		oirq.np = of_find_compatible_node(NULL, NULL,
+						  "mti,cpu-interrupt-controller");
+		if (!oirq.np)
+			return -EINVAL;
+
 		oirq.args_count = 1;
 		oirq.args[0] = 2;
-
 		parent_irq = irq_create_of_mapping(&oirq);
-
 		of_node_put(oirq.np);
 	} else {
 		parent_irq = of_irq_get(node, 0);
 	}
 
-	if (parent_irq < 0)
-		return parent_irq;
-	else if (!parent_irq)
-		return -ENODEV;
+	if (parent_irq <= 0)
+		return parent_irq ? parent_irq : -ENODEV;
 
-	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS, &irq_domain_ops, NULL);
+	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
+					  &irq_domain_ops, NULL);
 	if (!domain)
 		return -ENOMEM;
 
@@ -197,4 +184,23 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
 	return 0;
 }
 
+static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
+{
+	unsigned int cpu;
+
+	for_each_present_cpu(cpu) {
+		realtek_ictl_base[cpu] = of_iomap(node, cpu);
+		if (!realtek_ictl_base[cpu])
+			return -ENXIO;
+
+		/* Disable all cascaded interrupts and clear routing */
+		for (unsigned int hw_irq = 0; hw_irq < RTL_ICTL_NUM_INPUTS; hw_irq++) {
+			disable_gimr(cpu, hw_irq);
+			write_irr(cpu, hw_irq, 0);
+		}
+	}
+
+	return realtek_setup_parents(node);
+}
+
 IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init);
-- 
2.54.0


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

* [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

To prepare for multiple parent interrupt domains add an intermediate
data structure. For now this will only host the link to the domain.
Additionally adapt a deviating variable name to driver standard "hw_irq".

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 48 ++++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 3b4508ec7198..9629b4bed635 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -25,6 +25,10 @@
 
 #define REG(cpu, x)		(realtek_ictl_base[cpu] + x)
 
+struct realtek_ictl_output {
+	struct irq_domain *domain;
+};
+
 static DEFINE_RAW_SPINLOCK(irq_lock);
 static void __iomem *realtek_ictl_base[NR_CPUS];
 
@@ -125,11 +129,11 @@ static const struct irq_domain_ops irq_domain_ops = {
 
 static void realtek_irq_dispatch(struct irq_desc *desc)
 {
+	struct realtek_ictl_output *output = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cpu = smp_processor_id();
-	struct irq_domain *domain;
 	unsigned long pending;
-	unsigned int soc_int;
+	unsigned int hw_irq;
 
 	chained_irq_enter(chip, desc);
 	pending = readl(REG(cpu, RTL_ICTL_GIMR)) & readl(REG(cpu, RTL_ICTL_GISR));
@@ -139,9 +143,8 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 		goto out;
 	}
 
-	domain = irq_desc_get_handler_data(desc);
-	for_each_set_bit(soc_int, &pending, RTL_ICTL_NUM_INPUTS)
-		generic_handle_domain_irq(domain, soc_int);
+	for_each_set_bit(hw_irq, &pending, RTL_ICTL_NUM_INPUTS)
+		generic_handle_domain_irq(output->domain, hw_irq);
 
 out:
 	chained_irq_exit(chip, desc);
@@ -149,10 +152,15 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 
 static int __init realtek_setup_parents(struct device_node *node)
 {
-	int parent_irq, num_parents = of_irq_count(node);
+	int err, parent_irq, num_parents = of_irq_count(node);
+	struct realtek_ictl_output *output;
 	struct of_phandle_args oirq;
 	struct irq_domain *domain;
 
+	output = kcalloc(1, sizeof(*output), GFP_KERNEL);
+	if (!output)
+		return -ENOMEM;
+
 	if (WARN_ON(!num_parents)) {
 		/*
 		 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
@@ -160,8 +168,10 @@ static int __init realtek_setup_parents(struct device_node *node)
 		 */
 		oirq.np = of_find_compatible_node(NULL, NULL,
 						  "mti,cpu-interrupt-controller");
-		if (!oirq.np)
-			return -EINVAL;
+		if (!oirq.np) {
+			err = -EINVAL;
+			goto err_out;
+		}
 
 		oirq.args_count = 1;
 		oirq.args[0] = 2;
@@ -171,17 +181,27 @@ static int __init realtek_setup_parents(struct device_node *node)
 		parent_irq = of_irq_get(node, 0);
 	}
 
-	if (parent_irq <= 0)
-		return parent_irq ? parent_irq : -ENODEV;
+	if (parent_irq <= 0) {
+		err = parent_irq ? parent_irq : -ENODEV;
+		goto err_out;
+	}
 
 	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
-					  &irq_domain_ops, NULL);
-	if (!domain)
-		return -ENOMEM;
+					  &irq_domain_ops, output);
+	if (!domain) {
+		err = -ENOMEM;
+		goto err_out;
+	}
 
-	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, domain);
+	output->domain = domain;
+	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, output);
 
 	return 0;
+
+err_out:
+	kfree(output);
+
+	return err;
 }
 
 static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
-- 
2.54.0


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

* [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
                   ` (2 preceding siblings ...)
  2026-06-05 21:16 ` [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function Markus Stockhausen
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

When using multiple domains for the Interrupt controller, each one
must know which hardware interrupts it serves. Add a mask that is
filled during setup and apply it during interrupt handling.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 9629b4bed635..508c2dae7ec1 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -27,6 +27,7 @@
 
 struct realtek_ictl_output {
 	struct irq_domain *domain;
+	u32 mask;
 };
 
 static DEFINE_RAW_SPINLOCK(irq_lock);
@@ -109,15 +110,17 @@ static struct irq_chip realtek_ictl_irq = {
 	.irq_set_affinity	= realtek_ictl_irq_affinity,
 };
 
-static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw_irq)
 {
+	struct realtek_ictl_output *output = d->host_data;
 	unsigned int cpu;
 
 	irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
 
 	guard(raw_spinlock_irqsave)(&irq_lock);
+	output->mask |= BIT(hw_irq);
 	for_each_present_cpu(cpu)
-		write_irr(cpu, hw, 1);
+		write_irr(cpu, hw_irq, 1);
 
 	return 0;
 }
@@ -136,7 +139,7 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 	unsigned int hw_irq;
 
 	chained_irq_enter(chip, desc);
-	pending = readl(REG(cpu, RTL_ICTL_GIMR)) & readl(REG(cpu, RTL_ICTL_GISR));
+	pending = readl(REG(cpu, RTL_ICTL_GIMR)) & readl(REG(cpu, RTL_ICTL_GISR)) & output->mask;
 
 	if (unlikely(!pending)) {
 		spurious_interrupt();
-- 
2.54.0


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

* [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
                   ` (3 preceding siblings ...)
  2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

When working with multiple domains, the interrupt registration
must know to which domain it attaches. Add a select function that
takes care of the lookup. Logic is as follows.

If a device needs explicit parent routing it can request it by
giving an index as a second argument in the device tree. E.g.

intc: interrupt-controller@3000 {
  ...
  interrupts = <2>, <3>, <4>, <5>, <6>, <7>;
};

uart1: uart@2100 {
  ...
  interrupt-parent = <&intc>;
  interrupts = <31 1>;
}

This way the serial console with hardware interrupt 31 will be
routed via SoC interrupt 3. If the second argument is not given,
the first parent interrupt of the controller is selected.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 508c2dae7ec1..546d294bad35 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -26,7 +26,9 @@
 #define REG(cpu, x)		(realtek_ictl_base[cpu] + x)
 
 struct realtek_ictl_output {
+	struct fwnode_handle *fwnode;
 	struct irq_domain *domain;
+	unsigned int index;
 	u32 mask;
 };
 
@@ -125,9 +127,25 @@ static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw_i
 	return 0;
 }
 
+static int intc_select(struct irq_domain *d, struct irq_fwspec *fwspec,
+		       enum irq_domain_bus_token bus_token)
+{
+	struct realtek_ictl_output *output = d->host_data;
+	unsigned int index = 0;
+
+	if (fwspec->fwnode != output->fwnode)
+		return false;
+
+	if (fwspec->param_count == 2)
+		index = fwspec->param[1];
+
+	return index == output->index;
+}
+
 static const struct irq_domain_ops irq_domain_ops = {
-	.map = intc_map,
-	.xlate = irq_domain_xlate_onecell,
+	.map	= intc_map,
+	.select	= intc_select,
+	.xlate	= irq_domain_xlate_onecell,
 };
 
 static void realtek_irq_dispatch(struct irq_desc *desc)
@@ -197,6 +215,8 @@ static int __init realtek_setup_parents(struct device_node *node)
 	}
 
 	output->domain = domain;
+	output->fwnode = of_fwnode_handle(node);
+	output->index = 0;
 	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, output);
 
 	return 0;
-- 
2.54.0


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

* [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
                   ` (4 preceding siblings ...)
  2026-06-05 21:16 ` [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

The driver silently assumes that the first given interrupt in
the device tree is nailed to "2". Any deviation from this will
break the driver. Fix this by storing the given interrupt
in the domain data structure and writing the proper value
to the routing register.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 546d294bad35..5c5097edbc98 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -28,6 +28,8 @@
 struct realtek_ictl_output {
 	struct fwnode_handle *fwnode;
 	struct irq_domain *domain;
+	unsigned int parent_irq;
+	unsigned int parent_hwirq;
 	unsigned int index;
 	u32 mask;
 };
@@ -122,7 +124,7 @@ static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw_i
 	guard(raw_spinlock_irqsave)(&irq_lock);
 	output->mask |= BIT(hw_irq);
 	for_each_present_cpu(cpu)
-		write_irr(cpu, hw_irq, 1);
+		write_irr(cpu, hw_irq, output->parent_hwirq - 1);
 
 	return 0;
 }
@@ -175,6 +177,7 @@ static int __init realtek_setup_parents(struct device_node *node)
 {
 	int err, parent_irq, num_parents = of_irq_count(node);
 	struct realtek_ictl_output *output;
+	struct irq_data *parent_data;
 	struct of_phandle_args oirq;
 	struct irq_domain *domain;
 
@@ -207,6 +210,12 @@ static int __init realtek_setup_parents(struct device_node *node)
 		goto err_out;
 	}
 
+	parent_data = irq_get_irq_data(parent_irq);
+	if (!parent_data) {
+		err = -EINVAL;
+		goto err_out;
+	}
+
 	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
 					  &irq_domain_ops, output);
 	if (!domain) {
@@ -217,6 +226,8 @@ static int __init realtek_setup_parents(struct device_node *node)
 	output->domain = domain;
 	output->fwnode = of_fwnode_handle(node);
 	output->index = 0;
+	output->parent_irq = parent_irq;
+	output->parent_hwirq = irqd_to_hwirq(parent_data);
 	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, output);
 
 	return 0;
-- 
2.54.0


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

* [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents
  2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
                   ` (5 preceding siblings ...)
  2026-06-05 21:16 ` [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order Markus Stockhausen
@ 2026-06-05 21:16 ` Markus Stockhausen
  6 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-05 21:16 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, mail, bert, john, devicetree, tglx,
	linux-kernel
  Cc: Markus Stockhausen

Until now the driver exactly registers a single parent interrupt.
Relax this to make use of all defined interrupts in the device tree.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 88 +++++++++++++++++--------------
 1 file changed, 48 insertions(+), 40 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 5c5097edbc98..4b59e0cd86bf 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -175,64 +175,72 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 
 static int __init realtek_setup_parents(struct device_node *node)
 {
-	int err, parent_irq, num_parents = of_irq_count(node);
+	int p, cnt, err, parent_irq, num_parents = of_irq_count(node);
 	struct realtek_ictl_output *output;
 	struct irq_data *parent_data;
 	struct of_phandle_args oirq;
 	struct irq_domain *domain;
 
-	output = kcalloc(1, sizeof(*output), GFP_KERNEL);
+	cnt = max(1, num_parents);
+	output = kcalloc(cnt, sizeof(*output), GFP_KERNEL);
 	if (!output)
 		return -ENOMEM;
 
-	if (WARN_ON(!num_parents)) {
-		/*
-		 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
-		 * connected to the first output. This is the case for all known hardware.
-		 */
-		oirq.np = of_find_compatible_node(NULL, NULL,
-						  "mti,cpu-interrupt-controller");
-		if (!oirq.np) {
-			err = -EINVAL;
-			goto err_out;
+	for (p = 0; p < cnt; p++) {
+		if (WARN_ON(!num_parents)) {
+			/*
+			 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
+			 * connected to the first output. This is the case for all known hardware.
+			 */
+			oirq.np = of_find_compatible_node(NULL, NULL,
+							  "mti,cpu-interrupt-controller");
+			if (!oirq.np) {
+				err = -EINVAL;
+				goto err_out;
+			}
+
+			oirq.args_count = 1;
+			oirq.args[0] = 2;
+			parent_irq = irq_create_of_mapping(&oirq);
+			of_node_put(oirq.np);
+		} else {
+			parent_irq = of_irq_get(node, p);
 		}
 
-		oirq.args_count = 1;
-		oirq.args[0] = 2;
-		parent_irq = irq_create_of_mapping(&oirq);
-		of_node_put(oirq.np);
-	} else {
-		parent_irq = of_irq_get(node, 0);
-	}
+		if (parent_irq <= 0) {
+			err = parent_irq ? parent_irq : -ENODEV;
+			goto err_out;
+		}
 
-	if (parent_irq <= 0) {
-		err = parent_irq ? parent_irq : -ENODEV;
-		goto err_out;
-	}
+		parent_data = irq_get_irq_data(parent_irq);
+		if (!parent_data) {
+			err = -EINVAL;
+			goto err_out;
+		}
 
-	parent_data = irq_get_irq_data(parent_irq);
-	if (!parent_data) {
-		err = -EINVAL;
-		goto err_out;
-	}
+		domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
+						  &irq_domain_ops, &output[p]);
+		if (!domain) {
+			err = -ENOMEM;
+			goto err_out;
+		}
 
-	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
-					  &irq_domain_ops, output);
-	if (!domain) {
-		err = -ENOMEM;
-		goto err_out;
+		output[p].domain = domain;
+		output[p].fwnode = of_fwnode_handle(node);
+		output[p].index = p;
+		output[p].parent_irq = parent_irq;
+		output[p].parent_hwirq = irqd_to_hwirq(parent_data);
+		irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, &output[p]);
 	}
 
-	output->domain = domain;
-	output->fwnode = of_fwnode_handle(node);
-	output->index = 0;
-	output->parent_irq = parent_irq;
-	output->parent_hwirq = irqd_to_hwirq(parent_data);
-	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, output);
-
 	return 0;
 
 err_out:
+	while (p--) {
+		irq_set_chained_handler_and_data(output[p].parent_irq, NULL, NULL);
+		irq_domain_remove(output[p].domain);
+	}
+
 	kfree(output);
 
 	return err;
-- 
2.54.0


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

* Re: [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
  2026-06-05 21:16 ` [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells Markus Stockhausen
@ 2026-06-05 21:25   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-06-05 21:25 UTC (permalink / raw)
  To: Markus Stockhausen; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The cell-count property `#interrupt-cells` uses an `enum` constraint instead of a `const` constraint, violating dt-bindings subsystem rules.
--

commit 11a7c1b034a74e6212dca3ea81cd1ec7e513c49c
Author: Markus Stockhausen <markus.stockhausen@gmx.de>

dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells

This commit updates the #interrupt-cells property to accept either 1 or 2
cells to support explicit hardware interrupt routing to multiple parent CPU
interrupt lines.

> diff --git a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> --- a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> +++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> @@ -32,8 +32,9 @@ properties:
>  
>    "#interrupt-cells":
>      description:
> -      SoC interrupt line index.
> -    const: 1
> +      First cell is the SoC interrupt line index. Optional second cell
> +      specifies the parent interrupt index to route to.
> +    enum: [1, 2]

[Severity: Medium]
Does this change violate the subsystem requirements for cell-count properties?

The device tree binding subsystem rules require that each cell-count property
must have a const constraint matching the hardware (for example, const: 2).
Changing this constraint to use an enum instead of a const can lead to
incomplete or unreliable schema validation during dt_binding_check, as
downstream node references rely on a fixed cell count constraint to validate
interrupt specifiers properly.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260605211646.2101652-1-markus.stockhausen@gmx.de?part=1

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

end of thread, other threads:[~2026-06-05 21:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 21:16 [PATCH 0/7] irqchip/irq-realtek-rtl: Add multi parent support Markus Stockhausen
2026-06-05 21:16 ` [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells Markus Stockhausen
2026-06-05 21:25   ` sashiko-bot
2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
2026-06-05 21:16 ` [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure Markus Stockhausen
2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
2026-06-05 21:16 ` [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function Markus Stockhausen
2026-06-05 21:16 ` [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order Markus Stockhausen
2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox