From 752bee178ee107aa3dd87a9aeba970444034c6fb Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 4 Dec 2006 20:29:21 +0100 Subject: [PATCH] [ARM] 3980/1: extend the ARM Versatile sched_clock implementation from 32 to 63 bit period This provides a 63 bit clock counter guaranteed to be monotonic over a period of 35583 days instead of a clock wrap every 179 seconds, as long as sched_clock() is called at least once every 89 seconds. This should not be a problem in practice, although a kernel timer could be scheduled every 80 seconds for example simply to call sched_clock() making sure top bits are always synchronized if need be. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-versatile/core.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 3b85761..998b398 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -228,14 +229,19 @@ void __init versatile_map_io(void) /* * This is the Versatile sched_clock implementation. This has - * a resolution of 41.7ns, and a maximum value of about 179s. + * a resolution of 41.7ns, and a maximum value of about 35583 days. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 89 seconds between successive + * calls to this function. */ unsigned long long sched_clock(void) { - unsigned long long v; + unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER)); - v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125; - do_div(v, 3); + /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ + v *= 125<<1; + do_div(v, 3<<1); return v; } -- 1.8.2.3