irqchip/renesas-rzg2l: Flush posted write in irq_eoi()

[ Upstream commit 9eec61df55 ]

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: 3fed09559c ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Biju Das 2024-03-05 18:39:18 +00:00 committed by Greg Kroah-Hartman
parent bb4abe840e
commit c73da6b9eb
1 changed files with 14 additions and 2 deletions

View File

@ -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)