]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue
authorTony Lindgren <tony@atomide.com>
Fri, 9 Jul 2021 07:37:44 +0000 (10:37 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 11 Jul 2021 10:49:32 +0000 (12:49 +0200)
commit 3efe7a878a11c13b5297057bfc1e5639ce1241ce upstream.

There is a timer wrap issue on dra7 for the ARM architected timer.
In a typical clock configuration the timer fails to wrap after 388 days.

To work around the issue, we need to use timer-ti-dm timers instead.

Let's prepare for adding support for percpu timers by adding a common
dmtimer_clkevt_init_common() and call it from __omap_sync32k_timer_init().
This patch makes no intentional functional changes.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Keerthy <j-keerthy@ti.com>
Cc: Tero Kristo <kristo@kernel.org>
[tony@atomide.com: backported to 4.19.y]
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/mach-omap2/timer.c

index 0c0ee29751a84a09177dbdc85348996f08276cac..f24858d5ac693065f55afd8d73cbde7ef9bd0a17 100644 (file)
@@ -368,18 +368,21 @@ void tick_broadcast(const struct cpumask *mask)
 }
 #endif
 
-static void __init omap2_gp_clockevent_init(int gptimer_id,
-                                               const char *fck_source,
-                                               const char *property)
+static void __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt,
+                                             int gptimer_id,
+                                             const char *fck_source,
+                                             unsigned int features,
+                                             const struct cpumask *cpumask,
+                                             const char *property,
+                                             int rating, const char *name)
 {
-       struct dmtimer_clockevent *clkevt = &clockevent;
        struct omap_dm_timer *timer = &clkevt->timer;
        int res;
 
        timer->id = gptimer_id;
        timer->errata = omap_dm_timer_get_errata();
-       clkevt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-       clkevt->dev.rating = 300;
+       clkevt->dev.features = features;
+       clkevt->dev.rating = rating;
        clkevt->dev.set_next_event = omap2_gp_timer_set_next_event;
        clkevt->dev.set_state_shutdown = omap2_gp_timer_shutdown;
        clkevt->dev.set_state_periodic = omap2_gp_timer_set_periodic;
@@ -397,19 +400,15 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
                                     &clkevt->dev.name, OMAP_TIMER_POSTED);
        BUG_ON(res);
 
-       clkevt->dev.cpumask = cpu_possible_mask;
+       clkevt->dev.cpumask = cpumask;
        clkevt->dev.irq = omap_dm_timer_get_irq(timer);
 
-       if (request_irq(timer->irq, omap2_gp_timer_interrupt,
-                       IRQF_TIMER | IRQF_IRQPOLL, "gp_timer", clkevt))
-               pr_err("Failed to request irq %d (gp_timer)\n", timer->irq);
+       if (request_irq(clkevt->dev.irq, omap2_gp_timer_interrupt,
+                       IRQF_TIMER | IRQF_IRQPOLL, name, clkevt))
+               pr_err("Failed to request irq %d (gp_timer)\n", clkevt->dev.irq);
 
        __omap_dm_timer_int_enable(timer, OMAP_TIMER_INT_OVERFLOW);
 
-       clockevents_config_and_register(&clkevt->dev, timer->rate,
-                                       3, /* Timer internal resynch latency */
-                                       0xffffffff);
-
        if (soc_is_am33xx() || soc_is_am43xx()) {
                clkevt->dev.suspend = omap_clkevt_idle;
                clkevt->dev.resume = omap_clkevt_unidle;
@@ -559,7 +558,12 @@ static void __init __omap_sync32k_timer_init(int clkev_nr, const char *clkev_src
 {
        omap_clk_init();
        omap_dmtimer_init();
-       omap2_gp_clockevent_init(clkev_nr, clkev_src, clkev_prop);
+       dmtimer_clkevt_init_common(&clockevent, clkev_nr, clkev_src,
+                                  CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+                                  cpu_possible_mask, clkev_prop, 300, "clockevent");
+       clockevents_config_and_register(&clockevent.dev, clockevent.timer.rate,
+                                       3, /* Timer internal resynch latency */
+                                       0xffffffff);
 
        /* Enable the use of clocksource="gp_timer" kernel parameter */
        if (use_gptimer_clksrc || gptimer)