ARM: tegra: timer: Remove 32k clocksource
authorColin Cross <ccross@android.com>
Sun, 24 Oct 2010 06:22:53 +0000 (23:22 -0700)
committerColin Cross <ccross@android.com>
Tue, 26 Oct 2010 01:46:20 +0000 (18:46 -0700)
The 32k clocksource is never used, because it is always registered
at the same time as the us clocksource, which has a higher rating.
Using the 32k clocksource would cause a race condition with the
tegra_rtc driver on the RTC shadow registers.  Remove the 32k
clocksource, add a replacement tegra_read_rtc_ms function for the
suspend code to track suspend time, and add a comment on
read_persistent_clock that it should never be called while the
tegra_rtc driver is running.  It is currently only called from
timekeeping init, suspend, and resume.

Change-Id: Ic964578e9923b0f0338959f75de1ac170f850337
Signed-off-by: Colin Cross <ccross@android.com>
arch/arm/mach-tegra/power.h
arch/arm/mach-tegra/timer.c

index 7831cbd09f625a86f2ecf04456e26051f30b3fe3..37992415b9c6ae73e1a6a0aa011de2ff37182951 100644 (file)
@@ -49,6 +49,7 @@
 #ifndef __ASSEMBLY__
 extern void *tegra_context_area;
 
+u64 tegra_rtc_read_ms(void);
 void tegra_lp2_set_trigger(unsigned long cycles);
 unsigned long tegra_lp2_timer_remain(void);
 void __cortex_a9_save(unsigned int mode);
index cc9ec7020533efb7ad8a4c29da248e99acf4fc16..72dc904813b26a571e6a7d2d1f9ff08fd0363680 100644 (file)
@@ -112,13 +112,6 @@ void tegra_clocksource_us_resume(struct clocksource *cs)
        tegra_us_clocksource_offset = tegra_us_resume_offset;
 }
 
-static cycle_t tegra_clocksource_32k_read(struct clocksource *cs)
-{
-       u32 ms = readl(rtc_base + RTC_MILLISECONDS);
-       u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
-       return (u64)s * 1000 + ms;
-}
-
 static struct clock_event_device tegra_clockevent = {
        .name           = "timer0",
        .rating         = 300,
@@ -137,43 +130,47 @@ static struct clocksource tegra_clocksource_us = {
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static struct clocksource tegra_clocksource_32k = {
-       .name   = "rtc_32k",
-       .rating = 100,
-       .read   = tegra_clocksource_32k_read,
-       .mask   = 0x7FFFFFFFFFFFFFFFULL,
-       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 unsigned long long sched_clock(void)
 {
        return tegra_clocksource_us.read(&tegra_clocksource_us) * 1000;
 }
 
-/**
+
+/*
+ * tegra_rtc_read - Reads the Tegra RTC registers
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
+ */
+u64 tegra_rtc_read_ms(void)
+{
+       u32 ms = readl(rtc_base + RTC_MILLISECONDS);
+       u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
+       return (u64)s * 1000 + ms;
+}
+
+/*
  * read_persistent_clock -  Return time from a persistent clock.
  *
  * Reads the time from a source which isn't disabled during PM, the
  * 32k sync timer.  Convert the cycles elapsed since last read into
  * nsecs and adds to a monotonically increasing timespec.
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
  */
 static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
+static u64 persistent_ms, last_persistent_ms;
 void read_persistent_clock(struct timespec *ts)
 {
-       unsigned long long nsecs;
-       cycles_t delta;
+       u64 delta;
        struct timespec *tsp = &persistent_ts;
 
-       last_cycles = cycles;
-       cycles = tegra_clocksource_32k.read(&tegra_clocksource_32k);
-       delta = cycles - last_cycles;
-
-       nsecs = clocksource_cyc2ns(delta,
-                                  tegra_clocksource_32k.mult,
-                                  tegra_clocksource_32k.shift);
+       last_persistent_ms = persistent_ms;
+       persistent_ms = tegra_rtc_read_ms();
+       delta = persistent_ms - last_persistent_ms;
 
-       timespec_add_ns(tsp, nsecs);
+       timespec_add_ns(tsp, delta * 1000000);
        *ts = *tsp;
 }
 
@@ -238,11 +235,6 @@ static void __init tegra_init_timer(void)
                BUG();
        }
 
-       if (clocksource_register_hz(&tegra_clocksource_32k, 1000)) {
-               printk(KERN_ERR "Failed to register 32k clocksource\n");
-               BUG();
-       }
-
        ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
        if (ret) {
                printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret);