* [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®