[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git-commits-head
Subject:    clocksource/drivers/timer-ti-dm: Do reset before enable
From:       Linux Kernel Mailing List <linux-kernel () vger ! kernel ! org>
Date:       2020-09-27 19:34:06
Message-ID: git-mailbomb-linux-master-164805157f3c6834670afbaff563353c773131f1 () kernel ! org
[Download RAW message or body]

Commit:     164805157f3c6834670afbaff563353c773131f1
Parent:     400d033f5a599120089b5f0c54d14d198499af5a
Refname:    refs/heads/master
Web:        https://git.kernel.org/torvalds/c/164805157f3c6834670afbaff563353c773131f1
Author:     Tony Lindgren <tony@atomide.com>
AuthorDate: Mon Aug 17 12:24:28 2020 +0300
Committer:  Daniel Lezcano <daniel.lezcano@linaro.org>
CommitDate: Mon Aug 24 13:01:39 2020 +0200

    clocksource/drivers/timer-ti-dm: Do reset before enable
    
    Commit 6cfcd5563b4f ("clocksource/drivers/timer-ti-dm: Fix suspend and
    resume for am3 and am4") exposed a new issue for type2 dual mode timers
    on at least omap5 where the clockevent will stop when the SoC starts
    entering idle states during the boot.
    
    Turns out we are wrongly first enabling the system timer and then
    resetting it, while we must also re-enable it after reset. The current
    sequence leaves the timer module in a partially initialized state. This
    issue went unnoticed earlier with ti-sysc driver reconfiguring the timer
    module until we fixed the issue of ti-sysc reconfiguring system timers.
    
    Let's fix the issue by calling dmtimer_systimer_enable() from reset for
    both type1 and type2 timers, and switch the order of reset and enable in
    dmtimer_systimer_setup(). Let's also move dmtimer_systimer_enable() and
    dmtimer_systimer_disable() to do this without adding forward declarations.
    
    Fixes: 6cfcd5563b4f ("clocksource/drivers/timer-ti-dm: Fix suspend and resume for am3 and am4")
    Reported-by: H. Nikolaus Schaller" <hns@goldelico.com>
    Signed-off-by: Tony Lindgren <tony@atomide.com>
    Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
    Link: https://lore.kernel.org/r/20200817092428.6176-1-tony@atomide.com
---
 drivers/clocksource/timer-ti-dm-systimer.c | 44 ++++++++++++++++--------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
index f6fd1c1cc527..33b3e8aa2cc5 100644
--- a/drivers/clocksource/timer-ti-dm-systimer.c
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
@@ -69,12 +69,33 @@ static bool dmtimer_systimer_revision1(struct dmtimer_systimer *t)
 	return !(tidr >> 16);
 }
 
+static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
+{
+	u32 val;
+
+	if (dmtimer_systimer_revision1(t))
+		val = DMTIMER_TYPE1_ENABLE;
+	else
+		val = DMTIMER_TYPE2_ENABLE;
+
+	writel_relaxed(val, t->base + t->sysc);
+}
+
+static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
+{
+	if (!dmtimer_systimer_revision1(t))
+		return;
+
+	writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
+}
+
 static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
 {
 	void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
 	int ret;
 	u32 l;
 
+	dmtimer_systimer_enable(t);
 	writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
 	ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
 					DMTIMER_RESET_WAIT);
@@ -88,6 +109,7 @@ static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
 	void __iomem *sysc = t->base + t->sysc;
 	u32 l;
 
+	dmtimer_systimer_enable(t);
 	l = readl_relaxed(sysc);
 	l |= BIT(0);
 	writel_relaxed(l, sysc);
@@ -336,26 +358,6 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
 	return 0;
 }
 
-static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
-{
-	u32 val;
-
-	if (dmtimer_systimer_revision1(t))
-		val = DMTIMER_TYPE1_ENABLE;
-	else
-		val = DMTIMER_TYPE2_ENABLE;
-
-	writel_relaxed(val, t->base + t->sysc);
-}
-
-static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
-{
-	if (!dmtimer_systimer_revision1(t))
-		return;
-
-	writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
-}
-
 static int __init dmtimer_systimer_setup(struct device_node *np,
 					 struct dmtimer_systimer *t)
 {
@@ -409,8 +411,8 @@ static int __init dmtimer_systimer_setup(struct device_node *np,
 	t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
 	t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
 
-	dmtimer_systimer_enable(t);
 	dmtimer_systimer_reset(t);
+	dmtimer_systimer_enable(t);
 	pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
 		 readl_relaxed(t->base + t->sysc));
 
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic