summaryrefslogtreecommitdiff
path: root/arch/arm/mach-versatile
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2006-12-04 22:29:21 +0300
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-12-07 19:06:53 +0300
commit752bee178ee107aa3dd87a9aeba970444034c6fb (patch)
tree7bc5f554781182c88602c2dd43ddd664a32aac24 /arch/arm/mach-versatile
parent2f1675c11a0a214855ff6cba23aca239eef7a5fb (diff)
downloadlinux-752bee178ee107aa3dd87a9aeba970444034c6fb.tar.xz
[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 <nico@cam.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-versatile')
-rw-r--r--arch/arm/mach-versatile/core.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 3b8576111c16..998b398df30e 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -27,6 +27,7 @@
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
+#include <asm/cnt32_to_63.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -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;
}