Skip to content

Commit 1648051

Browse files
tmlinddlezcano
authored andcommitted
clocksource/drivers/timer-ti-dm: Do reset before enable
Commit 6cfcd55 ("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: 6cfcd55 ("clocksource/drivers/timer-ti-dm: Fix suspend and resume for am3 and am4") Reported-by: H. Nikolaus Schaller" <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Signed-off-by: Daniel Lezcano <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 400d033 commit 1648051

File tree

1 file changed

+23
-21
lines changed

1 file changed

+23
-21
lines changed

drivers/clocksource/timer-ti-dm-systimer.c

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,33 @@ static bool dmtimer_systimer_revision1(struct dmtimer_systimer *t)
6969
return !(tidr >> 16);
7070
}
7171

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+
7292
static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
7393
{
7494
void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
7595
int ret;
7696
u32 l;
7797

98+
dmtimer_systimer_enable(t);
7899
writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
79100
ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
80101
DMTIMER_RESET_WAIT);
@@ -88,6 +109,7 @@ static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
88109
void __iomem *sysc = t->base + t->sysc;
89110
u32 l;
90111

112+
dmtimer_systimer_enable(t);
91113
l = readl_relaxed(sysc);
92114
l |= BIT(0);
93115
writel_relaxed(l, sysc);
@@ -336,26 +358,6 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
336358
return 0;
337359
}
338360

339-
static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
340-
{
341-
u32 val;
342-
343-
if (dmtimer_systimer_revision1(t))
344-
val = DMTIMER_TYPE1_ENABLE;
345-
else
346-
val = DMTIMER_TYPE2_ENABLE;
347-
348-
writel_relaxed(val, t->base + t->sysc);
349-
}
350-
351-
static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
352-
{
353-
if (!dmtimer_systimer_revision1(t))
354-
return;
355-
356-
writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
357-
}
358-
359361
static int __init dmtimer_systimer_setup(struct device_node *np,
360362
struct dmtimer_systimer *t)
361363
{
@@ -409,8 +411,8 @@ static int __init dmtimer_systimer_setup(struct device_node *np,
409411
t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
410412
t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
411413

412-
dmtimer_systimer_enable(t);
413414
dmtimer_systimer_reset(t);
415+
dmtimer_systimer_enable(t);
414416
pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
415417
readl_relaxed(t->base + t->sysc));
416418

0 commit comments

Comments
 (0)