summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBiju Das <biju.das.jz@bp.renesas.com>2024-03-05 18:39:18 +0000
committerThomas Gleixner <tglx@linutronix.de>2024-03-18 12:20:01 +0100
commit9eec61df55c51415409c7cc47e9a1c8de94a0522 (patch)
treed9e5bde64e72de3c15d64133f0b3df60105e7b2e
parentca5b0b717b75d0f86f7f5dfe18369781bec742ad (diff)
downloadlinux-stable-9eec61df55c51415409c7cc47e9a1c8de94a0522.tar.gz
linux-stable-9eec61df55c51415409c7cc47e9a1c8de94a0522.tar.bz2
linux-stable-9eec61df55c51415409c7cc47e9a1c8de94a0522.zip
irqchip/renesas-rzg2l: Flush posted write in irq_eoi()
The irq_eoi() callback of the RZ/G2L interrupt chip clears the relevant interrupt cause bit in the TSCR register by writing to it. This write is not sufficient because the write is posted and therefore not guaranteed to immediately clear the bit. Due to that delay the CPU can raise the just handled interrupt again. Prevent this by reading the register back which causes the posted write to be flushed to the hardware before the read completes. Fixes: 3fed09559cd8 ("irqchip: Add RZ/G2L IA55 Interrupt Controller driver") Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/irqchip/irq-renesas-rzg2l.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 9494fc26259c..5285bc817dd0 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -99,8 +99,14 @@ static void rzg2l_irq_eoi(struct irq_data *d)
* ISCR can only be cleared if the type is falling-edge, rising-edge or
* falling/rising-edge.
*/
- if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq)))
+ if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq))) {
writel_relaxed(iscr & ~bit, priv->base + ISCR);
+ /*
+ * Enforce that the posted write is flushed to prevent that the
+ * just handled interrupt is raised again.
+ */
+ readl_relaxed(priv->base + ISCR);
+ }
}
static void rzg2l_tint_eoi(struct irq_data *d)
@@ -111,8 +117,14 @@ static void rzg2l_tint_eoi(struct irq_data *d)
u32 reg;
reg = readl_relaxed(priv->base + TSCR);
- if (reg & bit)
+ if (reg & bit) {
writel_relaxed(reg & ~bit, priv->base + TSCR);
+ /*
+ * Enforce that the posted write is flushed to prevent that the
+ * just handled interrupt is raised again.
+ */
+ readl_relaxed(priv->base + TSCR);
+ }
}
static void rzg2l_irqc_eoi(struct irq_data *d)