diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2008-02-14 19:53:23 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2008-02-14 19:53:23 +0000 |
commit | cdd4b66aa5b30b1745543f004a7a03bbf737ee55 (patch) | |
tree | 72c64b25f84e4bc88a0dbdf31c1e96f1a81c6cce /sys | |
parent | d4d7315c02e82897333b1f0c16b55ec069fe68e7 (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.c | 45 |
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: |