[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <176873057590.510.936652578580136768.tip-bot2@tip-bot2>
Date: Sun, 18 Jan 2026 10:02:55 -0000
From: "tip-bot2 for Biju Das" <tip-bot2@...utronix.de>
To: linux-tip-commits@...r.kernel.org
Cc: Biju Das <biju.das.jz@...renesas.com>, Thomas Gleixner <tglx@...nel.org>,
x86@...nel.org, linux-kernel@...r.kernel.org
Subject: [tip: irq/drivers] irqchip/renesas-rzv2h: Add suspend/resume support
The following commit has been merged into the irq/drivers branch of tip:
Commit-ID: fba6ab8010bb3e77f7a590deae9ab23b49cb051d
Gitweb: https://git.kernel.org/tip/fba6ab8010bb3e77f7a590deae9ab23b49cb051d
Author: Biju Das <biju.das.jz@...renesas.com>
AuthorDate: Tue, 13 Jan 2026 12:53:12
Committer: Thomas Gleixner <tglx@...nel.org>
CommitterDate: Sun, 18 Jan 2026 11:00:29 +01:00
irqchip/renesas-rzv2h: Add suspend/resume support
On RZ/G3E using PSCI, s2ram powers down the SoC. Add suspend/resume
callbacks to restore IRQ type for NMI, TINT and external IRQ interrupts.
Signed-off-by: Biju Das <biju.das.jz@...renesas.com>
Signed-off-by: Thomas Gleixner <tglx@...nel.org>
Link: https://patch.msgid.link/20260113125315.359967-3-biju.das.jz@bp.renesas.com
---
drivers/irqchip/irq-renesas-rzv2h.c | 60 ++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
index 0c44b61..69980a8 100644
--- a/drivers/irqchip/irq-renesas-rzv2h.c
+++ b/drivers/irqchip/irq-renesas-rzv2h.c
@@ -20,6 +20,7 @@
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
/* DT "interrupts" indexes */
#define ICU_IRQ_START 1
@@ -90,6 +91,18 @@
#define ICU_RZV2H_TSSEL_MAX_VAL 0x55
/**
+ * struct rzv2h_irqc_reg_cache - registers cache (necessary for suspend/resume)
+ * @nitsr: ICU_NITSR register
+ * @iitsr: ICU_IITSR register
+ * @titsr: ICU_TITSR registers
+ */
+struct rzv2h_irqc_reg_cache {
+ u32 nitsr;
+ u32 iitsr;
+ u32 titsr[2];
+};
+
+/**
* struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
* @tssel_lut: TINT lookup table
* @t_offs: TINT offset
@@ -118,13 +131,15 @@ struct rzv2h_hw_info {
* @fwspec: IRQ firmware specific data
* @lock: Lock to serialize access to hardware registers
* @info: Pointer to struct rzv2h_hw_info
+ * @cache: Registers cache for suspend/resume
*/
-struct rzv2h_icu_priv {
+static struct rzv2h_icu_priv {
void __iomem *base;
struct irq_fwspec fwspec[ICU_NUM_IRQ];
raw_spinlock_t lock;
const struct rzv2h_hw_info *info;
-};
+ struct rzv2h_irqc_reg_cache cache;
+} *rzv2h_icu_data;
void rzv2h_icu_register_dma_req(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel,
u16 req_no)
@@ -412,6 +427,44 @@ static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type)
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
}
+static int rzv2h_irqc_irq_suspend(void *data)
+{
+ struct rzv2h_irqc_reg_cache *cache = &rzv2h_icu_data->cache;
+ void __iomem *base = rzv2h_icu_data->base;
+
+ cache->nitsr = readl_relaxed(base + ICU_NITSR);
+ cache->iitsr = readl_relaxed(base + ICU_IITSR);
+ for (unsigned int i = 0; i < 2; i++)
+ cache->titsr[i] = readl_relaxed(base + rzv2h_icu_data->info->t_offs + ICU_TITSR(i));
+
+ return 0;
+}
+
+static void rzv2h_irqc_irq_resume(void *data)
+{
+ struct rzv2h_irqc_reg_cache *cache = &rzv2h_icu_data->cache;
+ void __iomem *base = rzv2h_icu_data->base;
+
+ /*
+ * Restore only interrupt type. TSSRx will be restored at the
+ * request of pin controller to avoid spurious interrupts due
+ * to invalid PIN states.
+ */
+ for (unsigned int i = 0; i < 2; i++)
+ writel_relaxed(cache->titsr[i], base + rzv2h_icu_data->info->t_offs + ICU_TITSR(i));
+ writel_relaxed(cache->iitsr, base + ICU_IITSR);
+ writel_relaxed(cache->nitsr, base + ICU_NITSR);
+}
+
+static const struct syscore_ops rzv2h_irqc_syscore_ops = {
+ .suspend = rzv2h_irqc_irq_suspend,
+ .resume = rzv2h_irqc_irq_resume,
+};
+
+static struct syscore rzv2h_irqc_syscore = {
+ .ops = &rzv2h_irqc_syscore_ops,
+};
+
static const struct irq_chip rzv2h_icu_chip = {
.name = "rzv2h-icu",
.irq_eoi = rzv2h_icu_eoi,
@@ -495,7 +548,6 @@ static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_no
{
struct irq_domain *irq_domain, *parent_domain;
struct device_node *node = pdev->dev.of_node;
- struct rzv2h_icu_priv *rzv2h_icu_data;
struct reset_control *resetn;
int ret;
@@ -553,6 +605,8 @@ static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_no
rzv2h_icu_data->info = hw_info;
+ register_syscore(&rzv2h_irqc_syscore);
+
/*
* coccicheck complains about a missing put_device call before returning, but it's a false
* positive. We still need &pdev->dev after successfully returning from this function.
Powered by blists - more mailing lists