mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02: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@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
This commit is contained in:
parent
a384f2ed88
commit
3a74e73b86
|
|
@ -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
|
||||
|
|
@ -89,6 +90,18 @@
|
|||
#define ICU_RZG3E_TSSEL_MAX_VAL 0x8c
|
||||
#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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user