summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBiju Das <biju.das.jz@bp.renesas.com>2026-01-27 17:48:15 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-01-30 10:32:28 +0100
commit9966c8cc987e307ecd439266db8b4fd4feaad482 (patch)
tree3235d02d8dd0fbc88dfa91d4ec82ac02eabccc31
parent79966baabcfe9aea00f2f16f8750aa659ea4b62b (diff)
downloadlinux-9966c8cc987e307ecd439266db8b4fd4feaad482.tar.gz
linux-9966c8cc987e307ecd439266db8b4fd4feaad482.tar.bz2
linux-9966c8cc987e307ecd439266db8b4fd4feaad482.zip
irqchip/renesas-rzv2h: Prevent TINT spurious interrupt during resume
[ Upstream commit cd4a3ced4d1cdb14ffe905657b98a91e9d239dfb ] A glitch in the edge detection circuit can cause a spurious interrupt. The hardware manual recommends clearing the status flag after setting the ICU_TSSRk register as a countermeasure. Currently, a spurious interrupt is generated on the resume path of s2idle for the PMIC RTC TINT interrupt due to a glitch related to unnecessary enabling/disabling of the TINT enable bit. Fix this issue by not setting TSSR(TINT Source) and TITSR(TINT Detection Method Selection) registers if the values are the same as those set in these registers. Fixes: 0d7605e75ac2 ("irqchip: Add RZ/V2H(P) Interrupt Control Unit (ICU) driver") Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260113125315.359967-2-biju.das.jz@bp.renesas.com [tm: Added field_get() to avoid build error] Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/irqchip/irq-renesas-rzv2h.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
index 899a423b5da8..3dab62ededec 100644
--- a/drivers/irqchip/irq-renesas-rzv2h.c
+++ b/drivers/irqchip/irq-renesas-rzv2h.c
@@ -89,6 +89,8 @@
#define ICU_RZG3E_TSSEL_MAX_VAL 0x8c
#define ICU_RZV2H_TSSEL_MAX_VAL 0x55
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
/**
* struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
* @tssel_lut: TINT lookup table
@@ -328,6 +330,7 @@ static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
u32 titsr, titsr_k, titsel_n, tien;
struct rzv2h_icu_priv *priv;
u32 tssr, tssr_k, tssel_n;
+ u32 titsr_cur, tssr_cur;
unsigned int hwirq;
u32 tint, sense;
int tint_nr;
@@ -376,12 +379,18 @@ static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
guard(raw_spinlock)(&priv->lock);
tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
+ titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
+
+ tssr_cur = field_get(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width), tssr);
+ titsr_cur = field_get(ICU_TITSR_TITSEL_MASK(titsel_n), titsr);
+ if (tssr_cur == tint && titsr_cur == sense)
+ return 0;
+
tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width) | tien);
tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n, priv->info->field_width);
writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
- titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n);
titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);