linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3 v2] clocksource/drivers/fttmr010: Be stricter on IRQs
@ 2021-09-22 19:56 Linus Walleij
  2021-09-22 19:56 ` [PATCH 2/3 v2] clocksource/drivers/fttmr010: Clear also overflow bit on AST2600 Linus Walleij
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Linus Walleij @ 2021-09-22 19:56 UTC (permalink / raw)
  To: Daniel Lezcano, Thomas Gleixner
  Cc: linux-kernel, Linus Walleij, Cédric Le Goater, Joel Stanley,
	Guenter Roeck

Make sure we check that the right interrupt occurred before
calling the event handler for timer 1. Report spurious IRQs
as IRQ_NONE.

Cc: Cédric Le Goater <clg@kaod.org>
Cc: Joel Stanley <joel@jms.id.au>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Do not try to detect spurious IRQs on the Aspeed
  2400 and 2500 that miss the IRQ status register.
---
 drivers/clocksource/timer-fttmr010.c | 42 ++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c
index 126fb1f259b2..f47099dda96b 100644
--- a/drivers/clocksource/timer-fttmr010.c
+++ b/drivers/clocksource/timer-fttmr010.c
@@ -253,20 +253,46 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
  */
 static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = dev_id;
+	struct fttmr010 *fttmr010 = dev_id;
+	struct clock_event_device *evt = &fttmr010->clkevt;
+	u32 val;
+
+	if (fttmr010->is_aspeed) {
+		/*
+		 * Aspeed versions do not implement the interrupt
+		 * status register and cannot detect spurious
+		 * interrupts.
+		 */
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
+	}
+
+	val = readl(fttmr010->base + TIMER_INTR_STATE);
+	if (val & (TIMER_1_INT_MATCH1 | TIMER_1_INT_OVERFLOW))
+		evt->event_handler(evt);
+	else
+		/* Spurious IRQ */
+		return IRQ_NONE;
 
-	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t ast2600_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = dev_id;
-	struct fttmr010 *fttmr010 = to_fttmr010(evt);
+	struct fttmr010 *fttmr010 = dev_id;
+	struct clock_event_device *evt = &fttmr010->clkevt;
+	u32 val;
 
-	writel(0x1, fttmr010->base + TIMER_INTR_STATE);
+	val = readl(fttmr010->base + TIMER_INTR_STATE);
+	if (val & (TIMER_1_INT_MATCH1 | TIMER_1_INT_OVERFLOW)) {
+		writel(TIMER_1_INT_MATCH1, fttmr010->base + TIMER_INTR_STATE);
+		evt->event_handler(evt);
+	} else {
+		/* Just clear any spurious IRQs from the block */
+		writel(val, fttmr010->base + TIMER_INTR_STATE);
+		return IRQ_NONE;
+	}
 
-	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
@@ -384,12 +410,12 @@ static int __init fttmr010_common_init(struct device_node *np,
 		fttmr010->timer_shutdown = ast2600_timer_shutdown;
 		ret = request_irq(irq, ast2600_timer_interrupt,
 				  IRQF_TIMER, "FTTMR010-TIMER1",
-				  &fttmr010->clkevt);
+				  fttmr010);
 	} else {
 		fttmr010->timer_shutdown = fttmr010_timer_shutdown;
 		ret = request_irq(irq, fttmr010_timer_interrupt,
 				  IRQF_TIMER, "FTTMR010-TIMER1",
-				  &fttmr010->clkevt);
+				  fttmr010);
 	}
 	if (ret) {
 		pr_err("FTTMR010-TIMER1 no IRQ\n");
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-09-24 13:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-22 19:56 [PATCH 1/3 v2] clocksource/drivers/fttmr010: Be stricter on IRQs Linus Walleij
2021-09-22 19:56 ` [PATCH 2/3 v2] clocksource/drivers/fttmr010: Clear also overflow bit on AST2600 Linus Walleij
2021-09-22 19:56 ` [PATCH 3/3 v2] clocksource/drivers/fttmr010: Just count down Linus Walleij
2021-09-23 20:11 ` [PATCH 1/3 v2] clocksource/drivers/fttmr010: Be stricter on IRQs Cédric Le Goater
2021-09-23 21:05   ` Linus Walleij
2021-09-24 13:56     ` Cédric Le Goater

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).