aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorKevin Hilman <khilman@deeprootsystems.com>2009-09-24 19:35:48 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2010-01-20 21:16:08 -0500
commitd92cfcbe39fdb2328a28b5505f31cb8be40fc339 (patch)
tree709d6537fae858fb700aa83884eec2080a11b0bf /arch/arm
parentdccaad895094a699c37c065bff3fa9bb997daeb9 (diff)
OMAP: timekeeping: time should not stop during suspend
During suspend, the kernel timekeeping subsystem is shut down. Before suspend and upon resume, it uses a weak function read_persistent_clock() to determine the amount of time that elapsed during suspend. This function was not implemented on OMAP, so from the timekeeping subsystem perspective (and thus userspace as well) it appeared that no time elapsed during suspend. This patch uses the 32k sync timer as a the persistent clock. NOTE: This does *NOT* fully handle wrapping of the 32k sync timer, so more than one wrapping of the 32k sync timer during suspend may cause problems. Also note there are not interrupts when the 32k sync timer wraps, so something else has to be done. Reported-by: Jon Hunter <jon-hunter@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-omap/common.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index bf1eaf3a27d4..dddc0273bc8b 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -172,6 +172,32 @@ unsigned long long sched_clock(void)
172 clocksource_32k.mult, clocksource_32k.shift); 172 clocksource_32k.mult, clocksource_32k.shift);
173} 173}
174 174
175/**
176 * read_persistent_clock - Return time from a persistent clock.
177 *
178 * Reads the time from a source which isn't disabled during PM, the
179 * 32k sync timer. Convert the cycles elapsed since last read into
180 * nsecs and adds to a monotonically increasing timespec.
181 */
182static struct timespec persistent_ts;
183static cycles_t cycles, last_cycles;
184void read_persistent_clock(struct timespec *ts)
185{
186 unsigned long long nsecs;
187 cycles_t delta;
188 struct timespec *tsp = &persistent_ts;
189
190 last_cycles = cycles;
191 cycles = clocksource_32k.read(&clocksource_32k);
192 delta = cycles - last_cycles;
193
194 nsecs = clocksource_cyc2ns(delta,
195 clocksource_32k.mult, clocksource_32k.shift);
196
197 timespec_add_ns(tsp, nsecs);
198 *ts = *tsp;
199}
200
175static int __init omap_init_clocksource_32k(void) 201static int __init omap_init_clocksource_32k(void)
176{ 202{
177 static char err[] __initdata = KERN_ERR 203 static char err[] __initdata = KERN_ERR