| From 4172db172b4409067180bc7ea07e68eafd65dbec Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 4 Mar 2021 09:21:33 +0200 |
| Subject: clocksource/drivers/timer-ti-dm: Fix posted mode status check order |
| |
| From: Tony Lindgren <tony@atomide.com> |
| |
| [ Upstream commit 212709926c5493a566ca4086ad4f4b0d4e66b553 ] |
| |
| When the timer is configured in posted mode, we need to check the write- |
| posted status register (TWPS) before writing to the register. |
| |
| We now check TWPS after the write starting with commit 52762fbd1c47 |
| ("clocksource/drivers/timer-ti-dm: Add clockevent and clocksource |
| support"). |
| |
| For example, in the TRM for am571x the following is documented in chapter |
| "22.2.4.13.1.1 Write Posting Synchronization Mode": |
| |
| "For each register, a status bit is provided in the timer write-posted |
| status (TWPS) register. In this mode, it is mandatory that software check |
| this status bit before any write access. If a write is attempted to a |
| register with a previous access pending, the previous access is discarded |
| without notice." |
| |
| The regression happened when I updated the code to use standard read/write |
| accessors for the driver instead of using __omap_dm_timer_load_start(). |
| We have__omap_dm_timer_load_start() check the TWPS status correctly using |
| __omap_dm_timer_write(). |
| |
| Fixes: 52762fbd1c47 ("clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support") |
| Signed-off-by: Tony Lindgren <tony@atomide.com> |
| Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> |
| Link: https://lore.kernel.org/r/20210304072135.52712-2-tony@atomide.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/clocksource/timer-ti-dm-systimer.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c |
| index 33b3e8aa2cc5..422376680c8a 100644 |
| --- a/drivers/clocksource/timer-ti-dm-systimer.c |
| +++ b/drivers/clocksource/timer-ti-dm-systimer.c |
| @@ -449,13 +449,13 @@ static int dmtimer_set_next_event(unsigned long cycles, |
| struct dmtimer_systimer *t = &clkevt->t; |
| void __iomem *pend = t->base + t->pend; |
| |
| - writel_relaxed(0xffffffff - cycles, t->base + t->counter); |
| while (readl_relaxed(pend) & WP_TCRR) |
| cpu_relax(); |
| + writel_relaxed(0xffffffff - cycles, t->base + t->counter); |
| |
| - writel_relaxed(OMAP_TIMER_CTRL_ST, t->base + t->ctrl); |
| while (readl_relaxed(pend) & WP_TCLR) |
| cpu_relax(); |
| + writel_relaxed(OMAP_TIMER_CTRL_ST, t->base + t->ctrl); |
| |
| return 0; |
| } |
| @@ -490,18 +490,18 @@ static int dmtimer_set_periodic(struct clock_event_device *evt) |
| dmtimer_clockevent_shutdown(evt); |
| |
| /* Looks like we need to first set the load value separately */ |
| - writel_relaxed(clkevt->period, t->base + t->load); |
| while (readl_relaxed(pend) & WP_TLDR) |
| cpu_relax(); |
| + writel_relaxed(clkevt->period, t->base + t->load); |
| |
| - writel_relaxed(clkevt->period, t->base + t->counter); |
| while (readl_relaxed(pend) & WP_TCRR) |
| cpu_relax(); |
| + writel_relaxed(clkevt->period, t->base + t->counter); |
| |
| - writel_relaxed(OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, |
| - t->base + t->ctrl); |
| while (readl_relaxed(pend) & WP_TCLR) |
| cpu_relax(); |
| + writel_relaxed(OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, |
| + t->base + t->ctrl); |
| |
| return 0; |
| } |
| -- |
| 2.30.2 |
| |