Calibrate the processor cycle counter instead of believing what the
firmware says.
This commit is contained in:
parent
d446c6adb0
commit
a72b1925b4
@ -1,4 +1,4 @@
|
||||
/* $Id: clock.c,v 1.7 1999/04/23 19:53:37 dt Exp $ */
|
||||
/* $Id: clock.c,v 1.8 1999/04/25 10:45:59 dt Exp $ */
|
||||
/* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */
|
||||
|
||||
/*
|
||||
@ -114,6 +114,7 @@ static u_int32_t max_cycles_per_tick;
|
||||
static u_int32_t last_time;
|
||||
|
||||
static void handleclock(void* arg);
|
||||
static u_int32_t calibrate_clocks(u_int32_t firmware_freq);
|
||||
|
||||
void
|
||||
clockattach(device_t dev)
|
||||
@ -125,6 +126,7 @@ clockattach(device_t dev)
|
||||
if (clockdev)
|
||||
panic("clockattach: multiple clocks");
|
||||
clockdev = dev;
|
||||
cycles_per_sec = calibrate_clocks(cycles_per_sec);
|
||||
#ifdef EVCNT_COUNTERS
|
||||
evcnt_attach(dev, "intr", &clock_intr_evcnt);
|
||||
#endif
|
||||
@ -150,6 +152,8 @@ clockattach(device_t dev)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
u_int32_t freq;
|
||||
|
||||
if (clockdev == NULL)
|
||||
panic("cpu_initclocks: no clock attached");
|
||||
|
||||
@ -175,11 +179,12 @@ cpu_initclocks()
|
||||
* hardclock, which would then fall over because p->p_stats
|
||||
* isn't set at that time.
|
||||
*/
|
||||
freq = cycles_per_sec;
|
||||
last_time = alpha_rpcc();
|
||||
scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / cycles_per_sec;
|
||||
max_cycles_per_tick = 2*cycles_per_sec / hz;
|
||||
scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / freq;
|
||||
max_cycles_per_tick = 2*freq / hz;
|
||||
|
||||
alpha_timecounter.tc_frequency = cycles_per_sec;
|
||||
alpha_timecounter.tc_frequency = freq;
|
||||
init_timecounter(&alpha_timecounter);
|
||||
|
||||
platform.clockintr = (void (*) __P((void *))) handleclock;
|
||||
@ -190,6 +195,60 @@ cpu_initclocks()
|
||||
CLOCK_INIT(clockdev);
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
calibrate_clocks(u_int32_t firmware_freq)
|
||||
{
|
||||
u_int32_t start_pcc, stop_pcc;
|
||||
int sec, start_sec;
|
||||
|
||||
if (bootverbose)
|
||||
printf("Calibrating clock(s) ... ");
|
||||
|
||||
/* Read the mc146818A seconds counter. */
|
||||
if (CLOCK_GETSECS(clockdev, &sec))
|
||||
goto fail;
|
||||
|
||||
/* Wait for the mC146818A seconds counter to change. */
|
||||
start_sec = sec;
|
||||
for (;;) {
|
||||
if (CLOCK_GETSECS(clockdev, &sec))
|
||||
goto fail;
|
||||
if (sec != start_sec)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start keeping track of the PCC. */
|
||||
start_pcc = alpha_rpcc();
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change.
|
||||
*/
|
||||
start_sec = sec;
|
||||
for (;;) {
|
||||
if (CLOCK_GETSECS(clockdev, &sec))
|
||||
goto fail;
|
||||
if (sec != start_sec)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the PCC again to work out frequency.
|
||||
*/
|
||||
stop_pcc = alpha_rpcc();
|
||||
|
||||
if (bootverbose) {
|
||||
printf("PCC clock: %u Hz (firmware %u Hz)\n",
|
||||
stop_pcc - start_pcc, firmware_freq);
|
||||
}
|
||||
return (stop_pcc - start_pcc);
|
||||
|
||||
fail:
|
||||
if (bootverbose)
|
||||
printf("failed, using firmware default of %u Hz\n",
|
||||
firmware_freq);
|
||||
return (firmware_freq);
|
||||
}
|
||||
|
||||
static void
|
||||
handleclock(void* arg)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $Id: clock_if.m,v 1.1 1998/06/14 13:52:33 dfr Exp $
|
||||
# $Id: clock_if.m,v 1.2 1998/11/08 18:35:51 nsouch Exp $
|
||||
#
|
||||
|
||||
#include <machine/clockvar.h>
|
||||
@ -44,3 +44,8 @@ METHOD void set {
|
||||
device_t dev;
|
||||
struct clocktime *ct;
|
||||
};
|
||||
|
||||
METHOD int getsecs {
|
||||
device_t dev;
|
||||
int *secp;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: mcclock_isa.c,v 1.3 1998/07/31 09:20:35 dfr Exp $ */
|
||||
/* $Id: mcclock_isa.c,v 1.4 1999/05/08 21:58:38 dfr Exp $ */
|
||||
/* $NetBSD: mcclock_tlsb.c,v 1.8 1998/05/13 02:50:29 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
@ -61,6 +61,7 @@ static device_method_t mcclock_isa_methods[] = {
|
||||
DEVMETHOD(clock_init, mcclock_init),
|
||||
DEVMETHOD(clock_get, mcclock_get),
|
||||
DEVMETHOD(clock_set, mcclock_set),
|
||||
DEVMETHOD(clock_getsecs, mcclock_getsecs),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: mcclock.c,v 1.1 1998/06/10 10:56:23 dfr Exp $ */
|
||||
/* $Id: mcclock.c,v 1.2 1998/06/14 13:45:41 dfr Exp $ */
|
||||
/* $NetBSD: mcclock.c,v 1.11 1998/04/19 07:50:25 jonathan Exp $ */
|
||||
|
||||
/*
|
||||
@ -111,3 +111,29 @@ mcclock_set(device_t dev, struct clocktime *ct)
|
||||
MC146818_PUTTOD(dev, ®s);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int
|
||||
mcclock_getsecs(device_t dev, int *secp)
|
||||
{
|
||||
int timeout = 100000000;
|
||||
int sec;
|
||||
int s;
|
||||
|
||||
s = splclock();
|
||||
for (;;) {
|
||||
if (!(MCCLOCK_READ(dev, MC_REGA) & MC_REGA_UIP)) {
|
||||
sec = MCCLOCK_READ(dev, MC_SEC);
|
||||
break;
|
||||
}
|
||||
if (--timeout == 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
splx(s);
|
||||
*secp = sec;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
splx(s);
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
@ -33,3 +33,4 @@ void mcclock_attach(device_t dev);
|
||||
void mcclock_init(device_t);
|
||||
void mcclock_get(device_t, time_t, struct clocktime *);
|
||||
void mcclock_set(device_t, struct clocktime *);
|
||||
int mcclock_getsecs(device_t dev, int *secp);
|
||||
|
Loading…
Reference in New Issue
Block a user