Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Tony Lindgren and committed by
Daniel Lezcano
16480515 400d033f

+23 -21
+23 -21
drivers/clocksource/timer-ti-dm-systimer.c
··· 69 69 return !(tidr >> 16); 70 70 } 71 71 72 + static void dmtimer_systimer_enable(struct dmtimer_systimer *t) 73 + { 74 + u32 val; 75 + 76 + if (dmtimer_systimer_revision1(t)) 77 + val = DMTIMER_TYPE1_ENABLE; 78 + else 79 + val = DMTIMER_TYPE2_ENABLE; 80 + 81 + writel_relaxed(val, t->base + t->sysc); 82 + } 83 + 84 + static void dmtimer_systimer_disable(struct dmtimer_systimer *t) 85 + { 86 + if (!dmtimer_systimer_revision1(t)) 87 + return; 88 + 89 + writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc); 90 + } 91 + 72 92 static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t) 73 93 { 74 94 void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET; 75 95 int ret; 76 96 u32 l; 77 97 98 + dmtimer_systimer_enable(t); 78 99 writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl); 79 100 ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100, 80 101 DMTIMER_RESET_WAIT); ··· 109 88 void __iomem *sysc = t->base + t->sysc; 110 89 u32 l; 111 90 91 + dmtimer_systimer_enable(t); 112 92 l = readl_relaxed(sysc); 113 93 l |= BIT(0); 114 94 writel_relaxed(l, sysc); ··· 358 336 return 0; 359 337 } 360 338 361 - static void dmtimer_systimer_enable(struct dmtimer_systimer *t) 362 - { 363 - u32 val; 364 - 365 - if (dmtimer_systimer_revision1(t)) 366 - val = DMTIMER_TYPE1_ENABLE; 367 - else 368 - val = DMTIMER_TYPE2_ENABLE; 369 - 370 - writel_relaxed(val, t->base + t->sysc); 371 - } 372 - 373 - static void dmtimer_systimer_disable(struct dmtimer_systimer *t) 374 - { 375 - if (!dmtimer_systimer_revision1(t)) 376 - return; 377 - 378 - writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc); 379 - } 380 - 381 339 static int __init dmtimer_systimer_setup(struct device_node *np, 382 340 struct dmtimer_systimer *t) 383 341 { ··· 411 409 t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET; 412 410 t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET; 413 411 414 - dmtimer_systimer_enable(t); 415 412 dmtimer_systimer_reset(t); 413 + dmtimer_systimer_enable(t); 416 414 pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base), 417 415 readl_relaxed(t->base + t->sysc)); 418 416