summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2008-02-14 19:53:23 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2008-02-14 19:53:23 +0000
commitcdd4b66aa5b30b1745543f004a7a03bbf737ee55 (patch)
tree72c64b25f84e4bc88a0dbdf31c1e96f1a81c6cce /sys
parentd4d7315c02e82897333b1f0c16b55ec069fe68e7 (diff)
Some armish machines do not have very accurate clock generators,
instead of using a fixed number for the time base, measure the "accurate" value based on the rtc. ok kettenis@ mbalmer@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm/xscale/i80321_clock.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/sys/arch/arm/xscale/i80321_clock.c b/sys/arch/arm/xscale/i80321_clock.c
index 2eb4e950d4f..bdc346ba4e9 100644
--- a/sys/arch/arm/xscale/i80321_clock.c
+++ b/sys/arch/arm/xscale/i80321_clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i80321_clock.c,v 1.7 2007/05/21 14:54:35 drahn Exp $ */
+/* $OpenBSD: i80321_clock.c,v 1.8 2008/02/14 19:53:22 drahn Exp $ */
/*
* Copyright (c) 2006 Dale Rahn <drahn@openbsd.org>
@@ -69,6 +69,7 @@ static struct timecounter tcr1_timecounter = {
tcr1_get_timecount, NULL, 0xffffffff, 0, "tcr1", 0, NULL
};
+todr_chip_handle_t todr_handle;
/*
* TMR0 is used in non-reload mode as it is used for both the clock
@@ -266,14 +267,55 @@ void
cpu_initclocks()
{
uint32_t now;
+ struct timeval rtctime;
+ time_t first_sec, sec;
+ u_int32_t first_tb, second_tb;
/* would it make sense to have this be 100/1000 to round nicely? */
/* 100/1000 or 128/1024 ? */
stathz = 100;
profhz = 1000;
+
ticks_per_second = 200 * 1000000; /* 200 MHz */
+
+ if (todr_handle != NULL && todr_gettime(todr_handle, &rtctime) == 0) {
+ int psw;
+ int new_tps;
+ int tps_diff;
+
+ psw = disable_interrupts(I32_bit);
+
+ first_sec = rtctime.tv_sec;
+ do {
+ first_tb = tcr1_read();
+ todr_gettime(todr_handle, &rtctime);
+ sec = rtctime.tv_sec;
+ } while (sec == first_sec);
+ first_sec = sec;
+ do {
+ second_tb = tcr1_read();
+ todr_gettime(todr_handle, &rtctime);
+ sec = rtctime.tv_sec;
+ } while (sec == first_sec);
+
+ new_tps = first_tb - second_tb;
+ tps_diff = ticks_per_second - new_tps;
+ if (tps_diff < 0)
+ tps_diff = -tps_diff;
+
+ /*
+ * only if the calculated time is more than 0.1% use the
+ * new calculate time. Otherwise system with accurate clocks
+ * can be penalized. (error in measurement)
+ */
+ if (tps_diff > ticks_per_second/1000)
+ ticks_per_second = new_tps;
+
+ restore_interrupts(psw);
+ }
+
setstatclockrate(stathz);
ticks_per_intr = ticks_per_second / hz;
@@ -376,7 +418,6 @@ i80321_calibrate_delay(void)
tmr1_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_PRIV|TMRx_CSEL_CORE);
}
-todr_chip_handle_t todr_handle;
/*
* inittodr: