diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-04-29 17:35:28 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-04-29 17:35:28 +0000 |
commit | 1b286df3ed9277fd99eeec31bf110a7a98d330b6 (patch) | |
tree | 0139245290c7ed4d647c6eddfb27290f58690a89 | |
parent | 9cd34d823384c1dac0abdfd009da6d8be68e43e5 (diff) |
The cpu clock frequency we get from ARCBIOS may be off by something in the
order of 1%. So calibrate the CP0 timecounter frequency using the TOD clock
if we have one.
"looks like good stuff" deraadt@, also tested by jsg@
-rw-r--r-- | sys/arch/mips64/mips64/clock.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/sys/arch/mips64/mips64/clock.c b/sys/arch/mips64/mips64/clock.c index 0bf8a2d63a0..bb41e9f92c1 100644 --- a/sys/arch/mips64/mips64/clock.c +++ b/sys/arch/mips64/mips64/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.17 2006/06/19 15:13:35 deraadt Exp $ */ +/* $OpenBSD: clock.c,v 1.18 2007/04/29 17:35:27 kettenis Exp $ */ /* * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -252,6 +252,9 @@ void cpu_initclocks() { struct clock_softc *sc = (struct clock_softc *)clock_cd.cd_devs[0]; + struct tod_time ct; + u_int first_cp0, second_cp0, cycles_per_sec; + int first_sec; hz = sc->sc_clock.clk_hz; stathz = sc->sc_clock.clk_stathz; @@ -263,6 +266,29 @@ cpu_initclocks() if (sc->sc_clock.clk_init != NULL) (*sc->sc_clock.clk_init)(sc); + /* + * Calibrate the cycle counter frequency. + */ + if (sc->sc_clock.clk_get != NULL) { + (*sc->sc_clock.clk_get)(sc, 0, &ct); + first_sec = ct.sec; + + /* Let the clock tick one second. */ + do { + first_cp0 = cp0_get_count(); + (*sc->sc_clock.clk_get)(sc, 0, &ct); + } while (ct.sec == first_sec); + first_sec = ct.sec; + /* Let the clock tick one more second. */ + do { + second_cp0 = cp0_get_count(); + (*sc->sc_clock.clk_get)(sc, 0, &ct); + } while (ct.sec == first_sec); + + cycles_per_sec = second_cp0 - first_cp0; + sys_config.cpu[0].clock = cycles_per_sec * 2; + } + tick = 1000000 / hz; /* number of micro-seconds between interrupts */ tickadj = 240000 / (60 * hz); /* can adjust 240ms in 60s */ |