The Linux Kernel Mailing List
 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; 18+ 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] 18+ 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-10 19:59   ` Rob Herring (Arm)
  2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 18+ 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] 18+ 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-29 15:19   ` [tip: irq/drivers] irqchip/irq-realtek-rtl: Split out parent setup code tip-bot2 for 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, 1 reply; 18+ 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] 18+ 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-29 15:19   ` [tip: irq/drivers] " tip-bot2 for 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, 1 reply; 18+ 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] 18+ 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-29 15:12   ` Thomas Gleixner
  2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for 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, 2 replies; 18+ 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] 18+ 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-29 15:19   ` [tip: irq/drivers] " tip-bot2 for 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, 1 reply; 18+ 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] 18+ 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-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
  2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen
  6 siblings, 1 reply; 18+ 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] 18+ 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
  2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
  6 siblings, 1 reply; 18+ 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] 18+ 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-10 19:59   ` Rob Herring (Arm)
  2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
  1 sibling, 0 replies; 18+ messages in thread
From: Rob Herring (Arm) @ 2026-06-10 19:59 UTC (permalink / raw)
  To: Markus Stockhausen
  Cc: devicetree, mail, krzk+dt, conor+dt, john, tglx, bert,
	linux-kernel


On Fri, 05 Jun 2026 23:16:40 +0200, Markus Stockhausen wrote:
> 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(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling
  2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
@ 2026-06-29 15:12   ` Thomas Gleixner
  2026-06-29 15:43     ` AW: " Markus Stockhausen
  2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
  1 sibling, 1 reply; 18+ messages in thread
From: Thomas Gleixner @ 2026-06-29 15:12 UTC (permalink / raw)
  To: Markus Stockhausen, robh, krzk+dt, conor+dt, mail, bert, john,
	devicetree, linux-kernel
  Cc: Markus Stockhausen

On Fri, Jun 05 2026 at 23:16, Markus Stockhausen wrote:
>  struct realtek_ictl_output {
>  	struct irq_domain *domain;
> +	u32 mask;

Data structures want to be declared in tabular form. See documentation.

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Activate multiple parents
  2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     4940e7daf4daa105c311f66b5774af1a98fc6b53
Gitweb:        https://git.kernel.org/tip/4940e7daf4daa105c311f66b5774af1a98fc6b53
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:46 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Activate multiple parents

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-8-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 96aae20..c8becb4 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -175,64 +175,72 @@ out:
 
 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;

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Allow shuffled interrupt order
  2026-06-05 21:16 ` [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order Markus Stockhausen
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     291e30ea93db78726c5d512afb620f9834c629d7
Gitweb:        https://git.kernel.org/tip/291e30ea93db78726c5d512afb620f9834c629d7
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:45 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Allow shuffled interrupt order

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-7-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 b256f98..96aae20 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;

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Add a select function
  2026-06-05 21:16 ` [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function Markus Stockhausen
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     86ddc446fd7936fdc1ad5a79a8fe1fd9f30ca3f6
Gitweb:        https://git.kernel.org/tip/86ddc446fd7936fdc1ad5a79a8fe1fd9f30ca3f6
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:44 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Add a select function

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-6-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 9f792d4..b256f98 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;

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Add mask for interrupt handling
  2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
  2026-06-29 15:12   ` Thomas Gleixner
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     2a3fa7f31f43580edcba5ee9f97473801aa3deec
Gitweb:        https://git.kernel.org/tip/2a3fa7f31f43580edcba5ee9f97473801aa3deec
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:43 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Add mask for interrupt handling

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-5-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 547f21d..9f792d4 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();

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Add interrupt data structure
  2026-06-05 21:16 ` [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure Markus Stockhausen
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     2568f6926c667e0b4ecf523cb4015acefc40409a
Gitweb:        https://git.kernel.org/tip/2568f6926c667e0b4ecf523cb4015acefc40409a
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:42 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Add interrupt data structure

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-4-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 3b4508e..547f21d 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 @@ out:
 
 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)

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

* [tip: irq/drivers] irqchip/irq-realtek-rtl: Split out parent setup code
  2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Markus Stockhausen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     d36c1d1657113fcf442c50e074593d7b712bada1
Gitweb:        https://git.kernel.org/tip/d36c1d1657113fcf442c50e074593d7b712bada1
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:41 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:06 +02:00

irqchip/irq-realtek-rtl: Split out parent setup code

The parent interrupt setup will be extended to support multiple parents.

To prepare for that, relocate the code 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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-3-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 2ae3be7..3b4508e 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -147,48 +147,35 @@ out:
 	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);

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

* [tip: irq/drivers] 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-10 19:59   ` Rob Herring (Arm)
@ 2026-06-29 15:19   ` tip-bot2 for Markus Stockhausen
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot2 for Markus Stockhausen @ 2026-06-29 15:19 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Markus Stockhausen, Thomas Gleixner, Rob Herring (Arm), x86,
	linux-kernel

The following commit has been merged into the irq/drivers branch of tip:

Commit-ID:     9d9faab6f562b8a447b4f7aae2862d071ba1ae0d
Gitweb:        https://git.kernel.org/tip/9d9faab6f562b8a447b4f7aae2862d071ba1ae0d
Author:        Markus Stockhausen <markus.stockhausen@gmx.de>
AuthorDate:    Fri, 05 Jun 2026 23:16:40 +02:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Mon, 29 Jun 2026 17:19:05 +02:00

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

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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Link: https://patch.msgid.link/20260605211646.2101652-2-markus.stockhausen@gmx.de
---
 Documentation/devicetree/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 833a01c..5c52e57 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

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

* AW: [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling
  2026-06-29 15:12   ` Thomas Gleixner
@ 2026-06-29 15:43     ` Markus Stockhausen
  0 siblings, 0 replies; 18+ messages in thread
From: Markus Stockhausen @ 2026-06-29 15:43 UTC (permalink / raw)
  To: 'Thomas Gleixner'; +Cc: linux-kernel

> Von: Thomas Gleixner <tglx@kernel.org> 
> Gesendet: Montag, 29. Juni 2026 17:12
>  Betreff: Re: [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt
handling
>
> On Fri, Jun 05 2026 at 23:16, Markus Stockhausen wrote:
> >  struct realtek_ictl_output {
> >  	struct irq_domain *domain;
> > +	u32 mask;
>
> Data structures want to be declared in tabular form. See documentation.

Thanks for the info and merging.

Markus


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

end of thread, other threads:[~2026-06-29 15:43 UTC | newest]

Thread overview: 18+ 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-10 19:59   ` Rob Herring (Arm)
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 2/7] irqchip/irq-realtek-rtl: Use helper for parent setup Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] irqchip/irq-realtek-rtl: Split out parent setup code tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 3/7] irqchip/irq-realtek-rtl: Add interrupt data structure Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 4/7] irqchip/irq-realtek-rtl: Add mask for interrupt handling Markus Stockhausen
2026-06-29 15:12   ` Thomas Gleixner
2026-06-29 15:43     ` AW: " Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 5/7] irqchip/irq-realtek-rtl: Add a select function Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 6/7] irqchip/irq-realtek-rtl: Allow shuffled interrupt order Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen
2026-06-05 21:16 ` [PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents Markus Stockhausen
2026-06-29 15:19   ` [tip: irq/drivers] " tip-bot2 for Markus Stockhausen

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