mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] irqchip/renesas-rzt2h: support error and software-triggered interrupts
@ 2026-05-20 20:31 Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Cosmin Tanislav @ 2026-05-20 20:31 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Cosmin Tanislav, linux-kernel

The Renesas RZ/T2H ICU is able to report errors for CA55, GIC, and
various IPs. It also supports software-triggerable interrupts.

Add support for these two features, and, while at it, also fix a runtime
PM issue in the probe error path.

Both the error interrupts and software-triggered interrupts are handled
similarly to the RZ/V2H implementation.

Cosmin Tanislav (3):
  irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path
  irqchip/renesas-rzt2h: add software-triggered interrupts support
  irqchip/renesas-rzt2h: add error interrupts support

 drivers/irqchip/irq-renesas-rzt2h.c | 279 +++++++++++++++++++++++++++-
 1 file changed, 275 insertions(+), 4 deletions(-)

-- 
2.54.0


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

* [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path
  2026-05-20 20:31 [PATCH 0/3] irqchip/renesas-rzt2h: support error and software-triggered interrupts Cosmin Tanislav
@ 2026-05-20 20:31 ` Cosmin Tanislav
  2026-05-21  9:50   ` [tip: irq/urgent] irqchip/renesas-rzt2h: Use " tip-bot2 for Cosmin Tanislav
  2026-05-21 18:17   ` tip-bot2 for Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 2/3] irqchip/renesas-rzt2h: add software-triggered interrupts support Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 3/3] irqchip/renesas-rzt2h: add error " Cosmin Tanislav
  2 siblings, 2 replies; 8+ messages in thread
From: Cosmin Tanislav @ 2026-05-20 20:31 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Cosmin Tanislav, linux-kernel

pm_runtime_put() may trigger the idle check after pm_runtime_disable()
is run as part of devm_pm_runtime_enable()'s cleanup action, leaving
runtime PM active.

Use pm_runtime_put_sync() to ensure the idle check runs synchronously.

Fixes: 13e7b3305b64 ("irqchip: Add RZ/{T2H,N2H} Interrupt Controller (ICU) driver")
Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
---
 drivers/irqchip/irq-renesas-rzt2h.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index 53cf80e1155a..ecb69da55508 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -265,7 +265,7 @@ static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *pare
 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, RZT2H_ICU_NUM_IRQ,
 						 dev_fwnode(dev), &rzt2h_icu_domain_ops, priv);
 	if (!irq_domain) {
-		pm_runtime_put(dev);
+		pm_runtime_put_sync(dev);
 		return -ENOMEM;
 	}
 
-- 
2.54.0


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

* [PATCH 2/3] irqchip/renesas-rzt2h: add software-triggered interrupts support
  2026-05-20 20:31 [PATCH 0/3] irqchip/renesas-rzt2h: support error and software-triggered interrupts Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
@ 2026-05-20 20:31 ` Cosmin Tanislav
  2026-06-03 16:29   ` [tip: irq/drivers] irqchip/renesas-rzt2h: Add " tip-bot2 for Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 3/3] irqchip/renesas-rzt2h: add error " Cosmin Tanislav
  2 siblings, 1 reply; 8+ messages in thread
From: Cosmin Tanislav @ 2026-05-20 20:31 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Cosmin Tanislav, linux-kernel

The Renesas RZ/T2H ICU supports software-triggerable interrupts.

Add a dedicated rzt2h_icu_intcpu_chip irq_chip which implements
rzt2h_icu_intcpu_set_irqchip_state() to allow injecting these
interrupts.

Request the INTCPU IRQs when IRQ injection is enabled to report them
when they occur.

Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
---
 drivers/irqchip/irq-renesas-rzt2h.c | 133 +++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index ecb69da55508..3fd0381efa32 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -2,6 +2,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/err.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/irq-renesas-rzt2h.h>
@@ -40,6 +41,9 @@
 	((n) >= RZT2H_ICU_##type##_START &&					\
 	 (n) <  RZT2H_ICU_##type##_START + RZT2H_ICU_##type##_COUNT)
 
+#define RZT2H_ICU_SWINT				0x0
+#define RZT2H_ICU_SWINT_IC_MASK(i)		BIT(i)
+
 #define RZT2H_ICU_PORTNF_MD			0xc
 #define RZT2H_ICU_PORTNF_MDi_MASK(i)		(GENMASK(1, 0) << ((i) * 2))
 #define RZT2H_ICU_PORTNF_MDi_PREP(i, val)	(FIELD_PREP(GENMASK(1, 0), val) << ((i) * 2))
@@ -99,6 +103,12 @@ static inline int rzt2h_icu_irq_to_offset(struct irq_data *d, void __iomem **bas
 	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, IRQ_S) || RZT2H_ICU_IRQ_IN_RANGE(hwirq, SEI)) {
 		*offset = hwirq - RZT2H_ICU_IRQ_S_START;
 		*base = priv->base_s;
+	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_NS)) {
+		*offset = hwirq - RZT2H_ICU_INTCPU_NS_START;
+		*base = priv->base_ns;
+	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_S)) {
+		*offset = hwirq - RZT2H_ICU_INTCPU_S_START;
+		*base = priv->base_s;
 	} else {
 		return -EINVAL;
 	}
@@ -164,6 +174,28 @@ static int rzt2h_icu_set_type(struct irq_data *d, unsigned int type)
 	return irq_chip_set_type_parent(d, IRQ_TYPE_EDGE_RISING);
 }
 
+static int rzt2h_icu_intcpu_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which,
+					      bool state)
+{
+	unsigned int offset;
+	void __iomem *base;
+	int ret;
+
+	if (which != IRQCHIP_STATE_PENDING)
+		return irq_chip_set_parent_state(d, which, state);
+
+	if (!state)
+		return 0;
+
+	ret = rzt2h_icu_irq_to_offset(d, &base, &offset);
+	if (ret)
+		return ret;
+
+	writel_relaxed(RZT2H_ICU_SWINT_IC_MASK(offset), base + RZT2H_ICU_SWINT);
+
+	return 0;
+}
+
 static const struct irq_chip rzt2h_icu_chip = {
 	.name			= "rzt2h-icu",
 	.irq_mask		= irq_chip_mask_parent,
@@ -180,10 +212,27 @@ static const struct irq_chip rzt2h_icu_chip = {
 				  IRQCHIP_SKIP_SET_WAKE,
 };
 
+static const struct irq_chip rzt2h_icu_intcpu_chip = {
+	.name			= "rzt2h-icu",
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_type		= irq_chip_set_type_parent,
+	.irq_set_wake		= irq_chip_set_wake_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_get_irqchip_state	= irq_chip_get_parent_state,
+	.irq_set_irqchip_state	= rzt2h_icu_intcpu_set_irqchip_state,
+	.flags			= IRQCHIP_MASK_ON_SUSPEND |
+				  IRQCHIP_SET_TYPE_MASKED |
+				  IRQCHIP_SKIP_SET_WAKE,
+};
+
 static int rzt2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
 			   void *arg)
 {
 	struct rzt2h_icu_priv *priv = domain->host_data;
+	const struct irq_chip *chip;
 	irq_hw_number_t hwirq;
 	unsigned int type;
 	int ret;
@@ -192,7 +241,13 @@ static int rzt2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigne
 	if (ret)
 		return ret;
 
-	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &rzt2h_icu_chip, NULL);
+	if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_NS) ||
+	    RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_S))
+		chip = &rzt2h_icu_intcpu_chip;
+	else
+		chip = &rzt2h_icu_chip;
+
+	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, NULL);
 	if (ret)
 		return ret;
 
@@ -222,6 +277,68 @@ static int rzt2h_icu_parse_interrupts(struct rzt2h_icu_priv *priv, struct device
 	return 0;
 }
 
+static irqreturn_t rzt2h_icu_intcpu_irq(int irq, void *data)
+{
+	unsigned int intcpu = (uintptr_t)data;
+
+	pr_info("INTCPU%u software interrupt\n", intcpu);
+
+	return IRQ_HANDLED;
+}
+
+static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domain *irq_domain,
+				  unsigned int start, unsigned int count, irq_handler_t handler,
+				  void *data)
+{
+	struct device *dev = &pdev->dev;
+	unsigned int offset, virq;
+	struct irq_fwspec fwspec;
+	int ret;
+
+	for (offset = start; offset < start + count; offset++) {
+		fwspec.fwnode = irq_domain->fwnode;
+		fwspec.param_count = 2;
+		fwspec.param[0] = offset;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+
+		virq = irq_create_fwspec_mapping(&fwspec);
+		if (!virq) {
+			return dev_err_probe(dev, -EINVAL,
+					     "Failed to create IRQ %u mapping\n", offset);
+		}
+
+		ret = devm_request_irq(dev, virq, handler, 0, dev_name(dev),
+				       data ?: (void *)(uintptr_t)offset);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to request IRQ %u\n", offset);
+	}
+
+	return 0;
+}
+
+static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain *irq_domain)
+{
+	int ret;
+
+	if (IS_ENABLED(CONFIG_GENERIC_IRQ_INJECTION)) {
+		ret = rzt2h_icu_request_irqs(pdev, irq_domain,
+					     RZT2H_ICU_INTCPU_NS_START,
+					     RZT2H_ICU_INTCPU_NS_COUNT,
+					     rzt2h_icu_intcpu_irq, NULL);
+		if (ret)
+			return ret;
+
+		ret = rzt2h_icu_request_irqs(pdev, irq_domain,
+					     RZT2H_ICU_INTCPU_S_START,
+					     RZT2H_ICU_INTCPU_S_COUNT,
+					     rzt2h_icu_intcpu_irq, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *parent)
 {
 	struct irq_domain *irq_domain, *parent_domain;
@@ -265,11 +382,21 @@ static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *pare
 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, RZT2H_ICU_NUM_IRQ,
 						 dev_fwnode(dev), &rzt2h_icu_domain_ops, priv);
 	if (!irq_domain) {
-		pm_runtime_put_sync(dev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_pm_put;
 	}
 
+	ret = rzt2h_icu_setup_irqs(pdev, irq_domain);
+	if (ret)
+		goto err_irq_domain_free;
+
 	return 0;
+
+err_irq_domain_free:
+	irq_domain_remove(irq_domain);
+err_pm_put:
+	pm_runtime_put_sync(dev);
+	return ret;
 }
 
 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzt2h_icu)
-- 
2.54.0


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

* [PATCH 3/3] irqchip/renesas-rzt2h: add error interrupts support
  2026-05-20 20:31 [PATCH 0/3] irqchip/renesas-rzt2h: support error and software-triggered interrupts Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
  2026-05-20 20:31 ` [PATCH 2/3] irqchip/renesas-rzt2h: add software-triggered interrupts support Cosmin Tanislav
@ 2026-05-20 20:31 ` Cosmin Tanislav
  2026-06-03 16:29   ` [tip: irq/drivers] irqchip/renesas-rzt2h: Add " tip-bot2 for Cosmin Tanislav
  2 siblings, 1 reply; 8+ messages in thread
From: Cosmin Tanislav @ 2026-05-20 20:31 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Cosmin Tanislav, linux-kernel

The Renesas RZ/T2H ICU is able to report errors for CA55, GIC, and
various IPs. Unmask these errors, request the IRQs and report them when
they occur.

Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
---
 drivers/irqchip/irq-renesas-rzt2h.c | 146 +++++++++++++++++++++++++++-
 1 file changed, 145 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index 3fd0381efa32..b04ea7a00b2c 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -31,11 +31,36 @@
 						 RZT2H_ICU_IRQ_S_COUNT)
 #define RZT2H_ICU_SEI_COUNT			1
 
+#define RZT2H_ICU_CA55_ERR_START		(RZT2H_ICU_SEI_START +		\
+						 RZT2H_ICU_SEI_COUNT)
+#define RZT2H_ICU_CA55_ERR_COUNT		2
+
+#define RZT2H_ICU_CR52_ERR_START		(RZT2H_ICU_CA55_ERR_START +	\
+						 RZT2H_ICU_CA55_ERR_COUNT)
+#define RZT2H_ICU_CR52_ERR_COUNT		4
+
+#define RZT2H_ICU_PERI_ERR_START		(RZT2H_ICU_CR52_ERR_START +	\
+						 RZT2H_ICU_CR52_ERR_COUNT)
+#define RZT2H_ICU_PERI_ERR_COUNT		2
+
+#define RZT2H_ICU_DSMIF_ERR_START		(RZT2H_ICU_PERI_ERR_START +	\
+						 RZT2H_ICU_PERI_ERR_COUNT)
+#define RZT2H_ICU_DSMIF_ERR_COUNT		2
+
+#define RZT2H_ICU_ENCIF_ERR_START		(RZT2H_ICU_DSMIF_ERR_START +	\
+						 RZT2H_ICU_DSMIF_ERR_COUNT)
+#define RZT2H_ICU_ENCIF_ERR_COUNT		2
+
 #define RZT2H_ICU_NUM_IRQ			(RZT2H_ICU_INTCPU_NS_COUNT +	\
 						 RZT2H_ICU_INTCPU_S_COUNT +	\
 						 RZT2H_ICU_IRQ_NS_COUNT +	\
 						 RZT2H_ICU_IRQ_S_COUNT +	\
-						 RZT2H_ICU_SEI_COUNT)
+						 RZT2H_ICU_SEI_COUNT +		\
+						 RZT2H_ICU_CA55_ERR_COUNT +	\
+						 RZT2H_ICU_CR52_ERR_COUNT +	\
+						 RZT2H_ICU_PERI_ERR_COUNT +	\
+						 RZT2H_ICU_DSMIF_ERR_COUNT +	\
+						 RZT2H_ICU_ENCIF_ERR_COUNT)
 
 #define RZT2H_ICU_IRQ_IN_RANGE(n, type)						\
 	((n) >= RZT2H_ICU_##type##_START &&					\
@@ -53,6 +78,29 @@
 #define RZT2H_ICU_MD_RISING_EDGE		0b10
 #define RZT2H_ICU_MD_BOTH_EDGES			0b11
 
+#define RZT2H_ICU_CA55ERR_E0MSK			0x50
+#define RZT2H_ICU_CA55ERR_CLR			0x60
+#define RZT2H_ICU_CA55ERR_STAT			0x64
+#define RZT2H_ICU_CA55ERR_MASK			GENMASK(12, 0)
+
+#define RZT2H_ICU_PERIERR_E0MSKn(n)		(0x98 + 0x4 * (n))
+#define RZT2H_ICU_PERIERR_CLRn(n)		(0xc8 + 0x4 * (n))
+#define RZT2H_ICU_PERIERR_STAT			0xd4
+#define RZT2H_ICU_PERIERR_NUM			3
+#define RZT2H_ICU_PERIERR_MASK			GENMASK(31, 0)
+
+#define RZT2H_ICU_DSMIFERR_E0MSKn(n)		(0xe0 + 0x4 * (n))
+#define RZT2H_ICU_DSMIFERR_CLRn(n)		(0x1a0 + 0x4 * (n))
+#define RZT2H_ICU_DSMIFERR_STAT			0x1d0
+#define RZT2H_ICU_DSMIFERR_NUM			12
+#define RZT2H_ICU_DSMIFERR_MASK			GENMASK(31, 0)
+
+#define RZT2H_ICU_ENCIFERR_E0MSKn(n)		(0x200 + 0x4 * (n))
+#define RZT2H_ICU_ENCIFERR_CLRn(n)		(0x250 + 0x4 * (n))
+#define RZT2H_ICU_ENCIFERR_STAT			0x264
+#define RZT2H_ICU_ENCIFERR_NUM			5
+#define RZT2H_ICU_ENCIFERR_MASK			GENMASK(31, 0)
+
 #define RZT2H_ICU_DMACn_RSSELi(n, i)		(0x7d0 + 0x18 * (n) + 0x4 * (i))
 #define RZT2H_ICU_DMAC_REQ_SELx_MASK(x)		(GENMASK(9, 0) << ((x) * 10))
 #define RZT2H_ICU_DMAC_REQ_SELx_PREP(x, val)	(FIELD_PREP(GENMASK(9, 0), val) << ((x) * 10))
@@ -286,6 +334,52 @@ static irqreturn_t rzt2h_icu_intcpu_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t rzt2h_icu_err_irq(struct rzt2h_icu_priv *priv, const char *name,
+				     unsigned int num, u32 stat_base, u32 clr_base)
+{
+	bool handled = false;
+
+	for (unsigned int n = 0; n < num; n++) {
+		u32 stat = readl(priv->base_ns + stat_base + n * 0x4);
+
+		if (!stat)
+			continue;
+
+		handled = true;
+
+		pr_err("rzt2h-icu: %s error n=%u status=0x%08x\n",
+		       name, n, stat);
+
+		writel_relaxed(stat, priv->base_ns + clr_base + n * 0x4);
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static irqreturn_t rzt2h_icu_ca55_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "CA55", 1,
+				 RZT2H_ICU_CA55ERR_STAT, RZT2H_ICU_CA55ERR_CLR);
+}
+
+static irqreturn_t rzt2h_icu_peri_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "peripheral", RZT2H_ICU_PERIERR_NUM,
+				 RZT2H_ICU_PERIERR_STAT, RZT2H_ICU_PERIERR_CLRn(0));
+}
+
+static irqreturn_t rzt2h_icu_dsmif_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "DSMIF", RZT2H_ICU_DSMIFERR_NUM,
+				 RZT2H_ICU_DSMIFERR_STAT, RZT2H_ICU_DSMIFERR_CLRn(0));
+}
+
+static irqreturn_t rzt2h_icu_encif_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "ENCIF", RZT2H_ICU_ENCIFERR_NUM,
+				 RZT2H_ICU_ENCIFERR_STAT, RZT2H_ICU_ENCIFERR_CLRn(0));
+}
+
 static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domain *irq_domain,
 				  unsigned int start, unsigned int count, irq_handler_t handler,
 				  void *data)
@@ -318,6 +412,8 @@ static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domai
 
 static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain *irq_domain)
 {
+	struct rzt2h_icu_priv *priv = platform_get_drvdata(pdev);
+	unsigned int n;
 	int ret;
 
 	if (IS_ENABLED(CONFIG_GENERIC_IRQ_INJECTION)) {
@@ -336,6 +432,54 @@ static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain
 			return ret;
 	}
 
+	/*
+	 * There are two error interrupts and two error masks that can be used
+	 * separately for each error type. It would not be very useful to
+	 * receive two interrupts for the same error, so use only the first one.
+	 */
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_CA55_ERR_START, 1,
+				     rzt2h_icu_ca55_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_PERI_ERR_START, 1,
+				     rzt2h_icu_peri_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_DSMIF_ERR_START, 1,
+				     rzt2h_icu_dsmif_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_ENCIF_ERR_START, 1,
+				     rzt2h_icu_encif_err_irq, priv);
+	if (ret)
+		return ret;
+
+	/* Clear and unmask CA55 error events */
+	writel_relaxed(RZT2H_ICU_CA55ERR_MASK, priv->base_ns + RZT2H_ICU_CA55ERR_CLR);
+	writel_relaxed(0, priv->base_ns + RZT2H_ICU_CA55ERR_E0MSK);
+
+	/* Clear and unmask peripheral error events */
+	for (n = 0; n < RZT2H_ICU_PERIERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_PERIERR_MASK, priv->base_ns + RZT2H_ICU_PERIERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_PERIERR_E0MSKn(n));
+	}
+
+	/* Clear and unmask DSMIF error events */
+	for (n = 0; n < RZT2H_ICU_DSMIFERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_DSMIFERR_MASK, priv->base_ns + RZT2H_ICU_DSMIFERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_DSMIFERR_E0MSKn(n));
+	}
+
+	/* Clear and unmask ENCIF error events */
+	for (n = 0; n < RZT2H_ICU_ENCIFERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_ENCIFERR_MASK, priv->base_ns + RZT2H_ICU_ENCIFERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_ENCIFERR_E0MSKn(n));
+	}
+
 	return 0;
 }
 
-- 
2.54.0


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

* [tip: irq/urgent] irqchip/renesas-rzt2h: Use pm_runtime_put_sync() in probe error path
  2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
@ 2026-05-21  9:50   ` tip-bot2 for Cosmin Tanislav
  2026-05-21 18:17   ` tip-bot2 for Cosmin Tanislav
  1 sibling, 0 replies; 8+ messages in thread
From: tip-bot2 for Cosmin Tanislav @ 2026-05-21  9:50 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Cosmin Tanislav, Thomas Gleixner, x86, linux-kernel, maz

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

Commit-ID:     b3b8fce2173a6e9c07a67e69b032e72564c3ccff
Gitweb:        https://git.kernel.org/tip/b3b8fce2173a6e9c07a67e69b032e72564c3ccff
Author:        Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
AuthorDate:    Wed, 20 May 2026 23:31:15 +03:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Thu, 21 May 2026 11:48:30 +02:00

irqchip/renesas-rzt2h: Use pm_runtime_put_sync() in probe error path

pm_runtime_put() may trigger the idle check after pm_runtime_disable()
is run as part of devm_pm_runtime_enable()'s cleanup action, leaving
runtime PM active.

Use pm_runtime_put_sync() to ensure the idle check runs synchronously.

Fixes: 13e7b3305b64 ("irqchip: Add RZ/{T2H,N2H} Interrupt Controller (ICU) driver")
Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260520203117.1516442-2-cosmin-gabriel.tanislav.xa@renesas.com
---
 drivers/irqchip/irq-renesas-rzt2h.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index 53cf80e..ecb69da 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -265,7 +265,7 @@ static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *pare
 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, RZT2H_ICU_NUM_IRQ,
 						 dev_fwnode(dev), &rzt2h_icu_domain_ops, priv);
 	if (!irq_domain) {
-		pm_runtime_put(dev);
+		pm_runtime_put_sync(dev);
 		return -ENOMEM;
 	}
 

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

* [tip: irq/urgent] irqchip/renesas-rzt2h: Use pm_runtime_put_sync() in probe error path
  2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
  2026-05-21  9:50   ` [tip: irq/urgent] irqchip/renesas-rzt2h: Use " tip-bot2 for Cosmin Tanislav
@ 2026-05-21 18:17   ` tip-bot2 for Cosmin Tanislav
  1 sibling, 0 replies; 8+ messages in thread
From: tip-bot2 for Cosmin Tanislav @ 2026-05-21 18:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Cosmin Tanislav, Thomas Gleixner, x86, linux-kernel, maz

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

Commit-ID:     c9b7598eb013c6dbf2526dc050364bd8dc24f0d3
Gitweb:        https://git.kernel.org/tip/c9b7598eb013c6dbf2526dc050364bd8dc24f0d3
Author:        Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
AuthorDate:    Wed, 20 May 2026 23:31:15 +03:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Thu, 21 May 2026 20:11:29 +02:00

irqchip/renesas-rzt2h: Use pm_runtime_put_sync() in probe error path

pm_runtime_put() may trigger the idle check after pm_runtime_disable()
is run as part of devm_pm_runtime_enable()'s cleanup action, leaving
runtime PM active.

Use pm_runtime_put_sync() to ensure the idle check runs synchronously.

Fixes: 13e7b3305b64 ("irqchip: Add RZ/{T2H,N2H} Interrupt Controller (ICU) driver")
Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260520203117.1516442-2-cosmin-gabriel.tanislav.xa@renesas.com
---
 drivers/irqchip/irq-renesas-rzt2h.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index 53cf80e..ecb69da 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -265,7 +265,7 @@ static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *pare
 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, RZT2H_ICU_NUM_IRQ,
 						 dev_fwnode(dev), &rzt2h_icu_domain_ops, priv);
 	if (!irq_domain) {
-		pm_runtime_put(dev);
+		pm_runtime_put_sync(dev);
 		return -ENOMEM;
 	}
 

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

* [tip: irq/drivers] irqchip/renesas-rzt2h: Add error interrupts support
  2026-05-20 20:31 ` [PATCH 3/3] irqchip/renesas-rzt2h: add error " Cosmin Tanislav
@ 2026-06-03 16:29   ` tip-bot2 for Cosmin Tanislav
  0 siblings, 0 replies; 8+ messages in thread
From: tip-bot2 for Cosmin Tanislav @ 2026-06-03 16:29 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Cosmin Tanislav, Thomas Gleixner, x86, linux-kernel

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

Commit-ID:     8d721c08dd67af96664ce381f6b2790d15de7213
Gitweb:        https://git.kernel.org/tip/8d721c08dd67af96664ce381f6b2790d15de7213
Author:        Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
AuthorDate:    Wed, 20 May 2026 23:31:17 +03:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Wed, 03 Jun 2026 18:27:05 +02:00

irqchip/renesas-rzt2h: Add error interrupts support

The Renesas RZ/T2H ICU is able to report errors for CA55, GIC, and
various IPs. Unmask these errors, request the IRQs and report them when
they occur.

Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260520203117.1516442-4-cosmin-gabriel.tanislav.xa@renesas.com
---
 drivers/irqchip/irq-renesas-rzt2h.c | 151 ++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index f7813d3..e06264a 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -31,11 +31,36 @@
 						 RZT2H_ICU_IRQ_S_COUNT)
 #define RZT2H_ICU_SEI_COUNT			1
 
+#define RZT2H_ICU_CA55_ERR_START		(RZT2H_ICU_SEI_START +		\
+						 RZT2H_ICU_SEI_COUNT)
+#define RZT2H_ICU_CA55_ERR_COUNT		2
+
+#define RZT2H_ICU_CR52_ERR_START		(RZT2H_ICU_CA55_ERR_START +	\
+						 RZT2H_ICU_CA55_ERR_COUNT)
+#define RZT2H_ICU_CR52_ERR_COUNT		4
+
+#define RZT2H_ICU_PERI_ERR_START		(RZT2H_ICU_CR52_ERR_START +	\
+						 RZT2H_ICU_CR52_ERR_COUNT)
+#define RZT2H_ICU_PERI_ERR_COUNT		2
+
+#define RZT2H_ICU_DSMIF_ERR_START		(RZT2H_ICU_PERI_ERR_START +	\
+						 RZT2H_ICU_PERI_ERR_COUNT)
+#define RZT2H_ICU_DSMIF_ERR_COUNT		2
+
+#define RZT2H_ICU_ENCIF_ERR_START		(RZT2H_ICU_DSMIF_ERR_START +	\
+						 RZT2H_ICU_DSMIF_ERR_COUNT)
+#define RZT2H_ICU_ENCIF_ERR_COUNT		2
+
 #define RZT2H_ICU_NUM_IRQ			(RZT2H_ICU_INTCPU_NS_COUNT +	\
 						 RZT2H_ICU_INTCPU_S_COUNT +	\
 						 RZT2H_ICU_IRQ_NS_COUNT +	\
 						 RZT2H_ICU_IRQ_S_COUNT +	\
-						 RZT2H_ICU_SEI_COUNT)
+						 RZT2H_ICU_SEI_COUNT +		\
+						 RZT2H_ICU_CA55_ERR_COUNT +	\
+						 RZT2H_ICU_CR52_ERR_COUNT +	\
+						 RZT2H_ICU_PERI_ERR_COUNT +	\
+						 RZT2H_ICU_DSMIF_ERR_COUNT +	\
+						 RZT2H_ICU_ENCIF_ERR_COUNT)
 
 #define RZT2H_ICU_IRQ_IN_RANGE(n, type)						\
 	((n) >= RZT2H_ICU_##type##_START &&					\
@@ -53,6 +78,29 @@
 #define RZT2H_ICU_MD_RISING_EDGE		0b10
 #define RZT2H_ICU_MD_BOTH_EDGES			0b11
 
+#define RZT2H_ICU_CA55ERR_E0MSK			0x50
+#define RZT2H_ICU_CA55ERR_CLR			0x60
+#define RZT2H_ICU_CA55ERR_STAT			0x64
+#define RZT2H_ICU_CA55ERR_MASK			GENMASK(12, 0)
+
+#define RZT2H_ICU_PERIERR_E0MSKn(n)		(0x98 + 0x4 * (n))
+#define RZT2H_ICU_PERIERR_CLRn(n)		(0xc8 + 0x4 * (n))
+#define RZT2H_ICU_PERIERR_STAT			0xd4
+#define RZT2H_ICU_PERIERR_NUM			3
+#define RZT2H_ICU_PERIERR_MASK			GENMASK(31, 0)
+
+#define RZT2H_ICU_DSMIFERR_E0MSKn(n)		(0xe0 + 0x4 * (n))
+#define RZT2H_ICU_DSMIFERR_CLRn(n)		(0x1a0 + 0x4 * (n))
+#define RZT2H_ICU_DSMIFERR_STAT			0x1d0
+#define RZT2H_ICU_DSMIFERR_NUM			12
+#define RZT2H_ICU_DSMIFERR_MASK			GENMASK(31, 0)
+
+#define RZT2H_ICU_ENCIFERR_E0MSKn(n)		(0x200 + 0x4 * (n))
+#define RZT2H_ICU_ENCIFERR_CLRn(n)		(0x250 + 0x4 * (n))
+#define RZT2H_ICU_ENCIFERR_STAT			0x264
+#define RZT2H_ICU_ENCIFERR_NUM			5
+#define RZT2H_ICU_ENCIFERR_MASK			GENMASK(31, 0)
+
 #define RZT2H_ICU_DMACn_RSSELi(n, i)		(0x7d0 + 0x18 * (n) + 0x4 * (i))
 #define RZT2H_ICU_DMAC_REQ_SELx_MASK(x)		(GENMASK(9, 0) << ((x) * 10))
 #define RZT2H_ICU_DMAC_REQ_SELx_PREP(x, val)	(FIELD_PREP(GENMASK(9, 0), val) << ((x) * 10))
@@ -284,6 +332,50 @@ static irqreturn_t rzt2h_icu_intcpu_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t rzt2h_icu_err_irq(struct rzt2h_icu_priv *priv, const char *name,
+				     unsigned int num, u32 stat_base, u32 clr_base)
+{
+	bool handled = false;
+
+	for (unsigned int n = 0; n < num; n++) {
+		u32 stat = readl(priv->base_ns + stat_base + n * 0x4);
+
+		if (!stat)
+			continue;
+
+		handled = true;
+
+		pr_err("rzt2h-icu: %s error n=%u status=0x%08x\n", name, n, stat);
+
+		writel_relaxed(stat, priv->base_ns + clr_base + n * 0x4);
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static irqreturn_t rzt2h_icu_ca55_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "CA55", 1, RZT2H_ICU_CA55ERR_STAT, RZT2H_ICU_CA55ERR_CLR);
+}
+
+static irqreturn_t rzt2h_icu_peri_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "peripheral", RZT2H_ICU_PERIERR_NUM, RZT2H_ICU_PERIERR_STAT,
+				 RZT2H_ICU_PERIERR_CLRn(0));
+}
+
+static irqreturn_t rzt2h_icu_dsmif_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "DSMIF", RZT2H_ICU_DSMIFERR_NUM, RZT2H_ICU_DSMIFERR_STAT,
+				 RZT2H_ICU_DSMIFERR_CLRn(0));
+}
+
+static irqreturn_t rzt2h_icu_encif_err_irq(int irq, void *data)
+{
+	return rzt2h_icu_err_irq(data, "ENCIF", RZT2H_ICU_ENCIFERR_NUM, RZT2H_ICU_ENCIFERR_STAT,
+				 RZT2H_ICU_ENCIFERR_CLRn(0));
+}
+
 static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domain *irq_domain,
 				  unsigned int start, unsigned int count, irq_handler_t handler,
 				  void *data)
@@ -314,10 +406,13 @@ static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domai
 
 static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain *irq_domain)
 {
+	struct rzt2h_icu_priv *priv = platform_get_drvdata(pdev);
+	unsigned int n;
+	int ret;
+
 	if (IS_ENABLED(CONFIG_GENERIC_IRQ_INJECTION)) {
-		int ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_INTCPU_NS_START,
-						 RZT2H_ICU_INTCPU_NS_COUNT, rzt2h_icu_intcpu_irq,
-						 NULL);
+		ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_INTCPU_NS_START,
+					     RZT2H_ICU_INTCPU_NS_COUNT, rzt2h_icu_intcpu_irq, NULL);
 		if (ret)
 			return ret;
 
@@ -327,6 +422,54 @@ static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain 
 			return ret;
 	}
 
+	/*
+	 * There are two error interrupts and two error masks that can be used
+	 * separately for each error type. It would not be very useful to
+	 * receive two interrupts for the same error, so use only the first one.
+	 */
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_CA55_ERR_START, 1,
+				     rzt2h_icu_ca55_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_PERI_ERR_START, 1,
+				     rzt2h_icu_peri_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_DSMIF_ERR_START, 1,
+				     rzt2h_icu_dsmif_err_irq, priv);
+	if (ret)
+		return ret;
+
+	ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_ENCIF_ERR_START, 1,
+				     rzt2h_icu_encif_err_irq, priv);
+	if (ret)
+		return ret;
+
+	/* Clear and unmask CA55 error events */
+	writel_relaxed(RZT2H_ICU_CA55ERR_MASK, priv->base_ns + RZT2H_ICU_CA55ERR_CLR);
+	writel_relaxed(0, priv->base_ns + RZT2H_ICU_CA55ERR_E0MSK);
+
+	/* Clear and unmask peripheral error events */
+	for (n = 0; n < RZT2H_ICU_PERIERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_PERIERR_MASK, priv->base_ns + RZT2H_ICU_PERIERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_PERIERR_E0MSKn(n));
+	}
+
+	/* Clear and unmask DSMIF error events */
+	for (n = 0; n < RZT2H_ICU_DSMIFERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_DSMIFERR_MASK, priv->base_ns + RZT2H_ICU_DSMIFERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_DSMIFERR_E0MSKn(n));
+	}
+
+	/* Clear and unmask ENCIF error events */
+	for (n = 0; n < RZT2H_ICU_ENCIFERR_NUM; n++) {
+		writel_relaxed(RZT2H_ICU_ENCIFERR_MASK, priv->base_ns + RZT2H_ICU_ENCIFERR_CLRn(n));
+		writel_relaxed(0, priv->base_ns + RZT2H_ICU_ENCIFERR_E0MSKn(n));
+	}
+
 	return 0;
 }
 

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

* [tip: irq/drivers] irqchip/renesas-rzt2h: Add software-triggered interrupts support
  2026-05-20 20:31 ` [PATCH 2/3] irqchip/renesas-rzt2h: add software-triggered interrupts support Cosmin Tanislav
@ 2026-06-03 16:29   ` tip-bot2 for Cosmin Tanislav
  0 siblings, 0 replies; 8+ messages in thread
From: tip-bot2 for Cosmin Tanislav @ 2026-06-03 16:29 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Cosmin Tanislav, Thomas Gleixner, x86, linux-kernel

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

Commit-ID:     a964dabc28a18fe62ff79e734cf54167ed322134
Gitweb:        https://git.kernel.org/tip/a964dabc28a18fe62ff79e734cf54167ed322134
Author:        Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
AuthorDate:    Wed, 20 May 2026 23:31:16 +03:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Wed, 03 Jun 2026 18:27:05 +02:00

irqchip/renesas-rzt2h: Add software-triggered interrupts support

The Renesas RZ/T2H ICU supports software-triggerable interrupts.

Add a dedicated rzt2h_icu_intcpu_chip irq_chip which implements
rzt2h_icu_intcpu_set_irqchip_state() to allow injecting these
interrupts.

Request the INTCPU IRQs when IRQ injection is enabled to report them
when they occur.

Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260520203117.1516442-3-cosmin-gabriel.tanislav.xa@renesas.com
---
 drivers/irqchip/irq-renesas-rzt2h.c | 123 ++++++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzt2h.c b/drivers/irqchip/irq-renesas-rzt2h.c
index ecb69da..f7813d3 100644
--- a/drivers/irqchip/irq-renesas-rzt2h.c
+++ b/drivers/irqchip/irq-renesas-rzt2h.c
@@ -2,6 +2,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/err.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/irq-renesas-rzt2h.h>
@@ -40,6 +41,9 @@
 	((n) >= RZT2H_ICU_##type##_START &&					\
 	 (n) <  RZT2H_ICU_##type##_START + RZT2H_ICU_##type##_COUNT)
 
+#define RZT2H_ICU_SWINT				0x0
+#define RZT2H_ICU_SWINT_IC_MASK(i)		BIT(i)
+
 #define RZT2H_ICU_PORTNF_MD			0xc
 #define RZT2H_ICU_PORTNF_MDi_MASK(i)		(GENMASK(1, 0) << ((i) * 2))
 #define RZT2H_ICU_PORTNF_MDi_PREP(i, val)	(FIELD_PREP(GENMASK(1, 0), val) << ((i) * 2))
@@ -99,6 +103,12 @@ static inline int rzt2h_icu_irq_to_offset(struct irq_data *d, void __iomem **bas
 	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, IRQ_S) || RZT2H_ICU_IRQ_IN_RANGE(hwirq, SEI)) {
 		*offset = hwirq - RZT2H_ICU_IRQ_S_START;
 		*base = priv->base_s;
+	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_NS)) {
+		*offset = hwirq - RZT2H_ICU_INTCPU_NS_START;
+		*base = priv->base_ns;
+	} else if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_S)) {
+		*offset = hwirq - RZT2H_ICU_INTCPU_S_START;
+		*base = priv->base_s;
 	} else {
 		return -EINVAL;
 	}
@@ -164,6 +174,28 @@ static int rzt2h_icu_set_type(struct irq_data *d, unsigned int type)
 	return irq_chip_set_type_parent(d, IRQ_TYPE_EDGE_RISING);
 }
 
+static int rzt2h_icu_intcpu_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which,
+					      bool state)
+{
+	unsigned int offset;
+	void __iomem *base;
+	int ret;
+
+	if (which != IRQCHIP_STATE_PENDING)
+		return irq_chip_set_parent_state(d, which, state);
+
+	if (!state)
+		return 0;
+
+	ret = rzt2h_icu_irq_to_offset(d, &base, &offset);
+	if (ret)
+		return ret;
+
+	writel_relaxed(RZT2H_ICU_SWINT_IC_MASK(offset), base + RZT2H_ICU_SWINT);
+
+	return 0;
+}
+
 static const struct irq_chip rzt2h_icu_chip = {
 	.name			= "rzt2h-icu",
 	.irq_mask		= irq_chip_mask_parent,
@@ -180,10 +212,27 @@ static const struct irq_chip rzt2h_icu_chip = {
 				  IRQCHIP_SKIP_SET_WAKE,
 };
 
+static const struct irq_chip rzt2h_icu_intcpu_chip = {
+	.name			= "rzt2h-icu",
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_type		= irq_chip_set_type_parent,
+	.irq_set_wake		= irq_chip_set_wake_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_get_irqchip_state	= irq_chip_get_parent_state,
+	.irq_set_irqchip_state	= rzt2h_icu_intcpu_set_irqchip_state,
+	.flags			= IRQCHIP_MASK_ON_SUSPEND |
+				  IRQCHIP_SET_TYPE_MASKED |
+				  IRQCHIP_SKIP_SET_WAKE,
+};
+
 static int rzt2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
 			   void *arg)
 {
 	struct rzt2h_icu_priv *priv = domain->host_data;
+	const struct irq_chip *chip;
 	irq_hw_number_t hwirq;
 	unsigned int type;
 	int ret;
@@ -192,7 +241,12 @@ static int rzt2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigne
 	if (ret)
 		return ret;
 
-	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &rzt2h_icu_chip, NULL);
+	if (RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_NS) || RZT2H_ICU_IRQ_IN_RANGE(hwirq, INTCPU_S))
+		chip = &rzt2h_icu_intcpu_chip;
+	else
+		chip = &rzt2h_icu_chip;
+
+	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, NULL);
 	if (ret)
 		return ret;
 
@@ -222,6 +276,60 @@ static int rzt2h_icu_parse_interrupts(struct rzt2h_icu_priv *priv, struct device
 	return 0;
 }
 
+static irqreturn_t rzt2h_icu_intcpu_irq(int irq, void *data)
+{
+	unsigned int intcpu = (uintptr_t)data;
+
+	pr_info("INTCPU%u software interrupt\n", intcpu);
+	return IRQ_HANDLED;
+}
+
+static int rzt2h_icu_request_irqs(struct platform_device *pdev, struct irq_domain *irq_domain,
+				  unsigned int start, unsigned int count, irq_handler_t handler,
+				  void *data)
+{
+	struct device *dev = &pdev->dev;
+	unsigned int offset, virq;
+	struct irq_fwspec fwspec;
+	int ret;
+
+	for (offset = start; offset < start + count; offset++) {
+		fwspec.fwnode = irq_domain->fwnode;
+		fwspec.param_count = 2;
+		fwspec.param[0] = offset;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+
+		virq = irq_create_fwspec_mapping(&fwspec);
+		if (!virq)
+			return dev_err_probe(dev, -EINVAL, "Failed to create IRQ %u mapping\n", offset);
+
+		ret = devm_request_irq(dev, virq, handler, 0, dev_name(dev),
+				       data ?: (void *)(uintptr_t)offset);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to request IRQ %u\n", offset);
+	}
+
+	return 0;
+}
+
+static int rzt2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain *irq_domain)
+{
+	if (IS_ENABLED(CONFIG_GENERIC_IRQ_INJECTION)) {
+		int ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_INTCPU_NS_START,
+						 RZT2H_ICU_INTCPU_NS_COUNT, rzt2h_icu_intcpu_irq,
+						 NULL);
+		if (ret)
+			return ret;
+
+		ret = rzt2h_icu_request_irqs(pdev, irq_domain, RZT2H_ICU_INTCPU_S_START,
+					     RZT2H_ICU_INTCPU_S_COUNT, rzt2h_icu_intcpu_irq, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *parent)
 {
 	struct irq_domain *irq_domain, *parent_domain;
@@ -265,11 +373,20 @@ static int rzt2h_icu_init(struct platform_device *pdev, struct device_node *pare
 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, RZT2H_ICU_NUM_IRQ,
 						 dev_fwnode(dev), &rzt2h_icu_domain_ops, priv);
 	if (!irq_domain) {
-		pm_runtime_put_sync(dev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_pm_put;
 	}
 
+	ret = rzt2h_icu_setup_irqs(pdev, irq_domain);
+	if (ret)
+		goto err_irq_domain_free;
 	return 0;
+
+err_irq_domain_free:
+	irq_domain_remove(irq_domain);
+err_pm_put:
+	pm_runtime_put_sync(dev);
+	return ret;
 }
 
 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzt2h_icu)

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

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

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-20 20:31 [PATCH 0/3] irqchip/renesas-rzt2h: support error and software-triggered interrupts Cosmin Tanislav
2026-05-20 20:31 ` [PATCH 1/3] irqchip/renesas-rzt2h: use pm_runtime_put_sync() in probe error path Cosmin Tanislav
2026-05-21  9:50   ` [tip: irq/urgent] irqchip/renesas-rzt2h: Use " tip-bot2 for Cosmin Tanislav
2026-05-21 18:17   ` tip-bot2 for Cosmin Tanislav
2026-05-20 20:31 ` [PATCH 2/3] irqchip/renesas-rzt2h: add software-triggered interrupts support Cosmin Tanislav
2026-06-03 16:29   ` [tip: irq/drivers] irqchip/renesas-rzt2h: Add " tip-bot2 for Cosmin Tanislav
2026-05-20 20:31 ` [PATCH 3/3] irqchip/renesas-rzt2h: add error " Cosmin Tanislav
2026-06-03 16:29   ` [tip: irq/drivers] irqchip/renesas-rzt2h: Add " tip-bot2 for Cosmin Tanislav

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

all inboxes | Powered by JetHome®