Skip to content

Commit 3a74e73

Browse files
bijudasThomas Gleixner
authored andcommitted
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@bp.renesas.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Link: https://patch.msgid.link/20260113125315.359967-3-biju.das.jz@bp.renesas.com
1 parent a384f2e commit 3a74e73

1 file changed

Lines changed: 57 additions & 3 deletions

File tree

drivers/irqchip/irq-renesas-rzv2h.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/pm_runtime.h>
2121
#include <linux/reset.h>
2222
#include <linux/spinlock.h>
23+
#include <linux/syscore_ops.h>
2324

2425
/* DT "interrupts" indexes */
2526
#define ICU_IRQ_START 1
@@ -89,6 +90,18 @@
8990
#define ICU_RZG3E_TSSEL_MAX_VAL 0x8c
9091
#define ICU_RZV2H_TSSEL_MAX_VAL 0x55
9192

93+
/**
94+
* struct rzv2h_irqc_reg_cache - registers cache (necessary for suspend/resume)
95+
* @nitsr: ICU_NITSR register
96+
* @iitsr: ICU_IITSR register
97+
* @titsr: ICU_TITSR registers
98+
*/
99+
struct rzv2h_irqc_reg_cache {
100+
u32 nitsr;
101+
u32 iitsr;
102+
u32 titsr[2];
103+
};
104+
92105
/**
93106
* struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
94107
* @tssel_lut: TINT lookup table
@@ -118,13 +131,15 @@ struct rzv2h_hw_info {
118131
* @fwspec: IRQ firmware specific data
119132
* @lock: Lock to serialize access to hardware registers
120133
* @info: Pointer to struct rzv2h_hw_info
134+
* @cache: Registers cache for suspend/resume
121135
*/
122-
struct rzv2h_icu_priv {
136+
static struct rzv2h_icu_priv {
123137
void __iomem *base;
124138
struct irq_fwspec fwspec[ICU_NUM_IRQ];
125139
raw_spinlock_t lock;
126140
const struct rzv2h_hw_info *info;
127-
};
141+
struct rzv2h_irqc_reg_cache cache;
142+
} *rzv2h_icu_data;
128143

129144
void rzv2h_icu_register_dma_req(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel,
130145
u16 req_no)
@@ -412,6 +427,44 @@ static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type)
412427
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
413428
}
414429

430+
static int rzv2h_irqc_irq_suspend(void *data)
431+
{
432+
struct rzv2h_irqc_reg_cache *cache = &rzv2h_icu_data->cache;
433+
void __iomem *base = rzv2h_icu_data->base;
434+
435+
cache->nitsr = readl_relaxed(base + ICU_NITSR);
436+
cache->iitsr = readl_relaxed(base + ICU_IITSR);
437+
for (unsigned int i = 0; i < 2; i++)
438+
cache->titsr[i] = readl_relaxed(base + rzv2h_icu_data->info->t_offs + ICU_TITSR(i));
439+
440+
return 0;
441+
}
442+
443+
static void rzv2h_irqc_irq_resume(void *data)
444+
{
445+
struct rzv2h_irqc_reg_cache *cache = &rzv2h_icu_data->cache;
446+
void __iomem *base = rzv2h_icu_data->base;
447+
448+
/*
449+
* Restore only interrupt type. TSSRx will be restored at the
450+
* request of pin controller to avoid spurious interrupts due
451+
* to invalid PIN states.
452+
*/
453+
for (unsigned int i = 0; i < 2; i++)
454+
writel_relaxed(cache->titsr[i], base + rzv2h_icu_data->info->t_offs + ICU_TITSR(i));
455+
writel_relaxed(cache->iitsr, base + ICU_IITSR);
456+
writel_relaxed(cache->nitsr, base + ICU_NITSR);
457+
}
458+
459+
static const struct syscore_ops rzv2h_irqc_syscore_ops = {
460+
.suspend = rzv2h_irqc_irq_suspend,
461+
.resume = rzv2h_irqc_irq_resume,
462+
};
463+
464+
static struct syscore rzv2h_irqc_syscore = {
465+
.ops = &rzv2h_irqc_syscore_ops,
466+
};
467+
415468
static const struct irq_chip rzv2h_icu_chip = {
416469
.name = "rzv2h-icu",
417470
.irq_eoi = rzv2h_icu_eoi,
@@ -495,7 +548,6 @@ static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_no
495548
{
496549
struct irq_domain *irq_domain, *parent_domain;
497550
struct device_node *node = pdev->dev.of_node;
498-
struct rzv2h_icu_priv *rzv2h_icu_data;
499551
struct reset_control *resetn;
500552
int ret;
501553

@@ -553,6 +605,8 @@ static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_no
553605

554606
rzv2h_icu_data->info = hw_info;
555607

608+
register_syscore(&rzv2h_irqc_syscore);
609+
556610
/*
557611
* coccicheck complains about a missing put_device call before returning, but it's a false
558612
* positive. We still need &pdev->dev after successfully returning from this function.

0 commit comments

Comments
 (0)