Convert x68k to timecounters. This conversion is not tested, due to lack

of available test candidates.  It uses the previously unused (as far as I
can tell) Timer D, in freerunning mode.  It only uses a 1/200 prescaler
(20KHz), as anything faster would roll over too fast for the system timer.
(Gotta love 8-bit resolution timers!)  Approved for untested commit by core@.
This commit is contained in:
gdamore 2006-09-19 10:13:10 +00:00
parent fc13afb3a4
commit b7648fa4c0
2 changed files with 32 additions and 42 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: types.h,v 1.10 2006/09/14 01:18:11 gdamore Exp $ */
/* $NetBSD: types.h,v 1.11 2006/09/19 10:13:10 gdamore Exp $ */
#ifndef _MACHINE_TYPES_H_
#define _MACHINE_TYPES_H_
@ -7,5 +7,6 @@
#define __HAVE_DEVICE_REGISTER
#define __HAVE_GENERIC_TODR
#define __HAVE_TIMECOUNTER
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.23 2006/09/14 01:18:11 gdamore Exp $ */
/* $NetBSD: clock.c,v 1.24 2006/09/19 10:13:10 gdamore Exp $ */
/*
* Copyright (c) 1982, 1990, 1993
@ -77,7 +77,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.23 2006/09/14 01:18:11 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.24 2006/09/19 10:13:10 gdamore Exp $");
#include "clock.h"
@ -87,6 +87,7 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.23 2006/09/14 01:18:11 gdamore Exp $");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/timetc.h>
#include <machine/psl.h>
#include <machine/cpu.h>
@ -110,6 +111,8 @@ CFATTACH_DECL(clock, sizeof(struct clock_softc),
static int clock_attached;
static unsigned mfp_get_timecount(struct timecounter *);
static int
clock_match(struct device *parent, struct cfdata *cf, void *aux)
{
@ -135,25 +138,21 @@ clock_attach(struct device *parent, struct device *self, void *aux)
/*
* MFP of X68k uses 4MHz clock always and we use 1/200 prescaler here.
* Therefore, clock interval is 50 usec.
*
* Note that for timecounters, we'd like to use a finger grained clock, but
* since we only have an 8-bit clock, we can't do that without increasing
* the system clock rate. (Otherwise the counter would roll in less than
* a single system clock.)
*/
#define CLK_RESOLUTION (50)
#define CLOCKS_PER_SEC (1000000 / CLK_RESOLUTION)
static int clkint; /* clock interval */
static int clkread(void);
/*
* Machine-dependent clock routines.
*
* Startrtclock restarts the real-time clock, which provides
* hardclock interrupts to kern_clock.c.
*
* Inittodr initializes the time of day hardware which provides
* date functions.
*
* Resettodr restores the time of day hardware after a time change.
*
* A note on the real-time clock:
* We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL.
* This is because the counter decrements to zero after N+1 enabled clock
@ -168,18 +167,30 @@ static int clkread(void);
void
cpu_initclocks(void)
{
static struct timecounter tc = {
.tc_name = "mfp",
.tc_frequency = CLOCKS_PER_SEC,
.tc_counter_mask = 0xff,
.tc_get_timecount = mfp_get_timecount,
.tc_quality = 100,
};
if (CLOCKS_PER_SEC % hz ||
hz <= (CLOCKS_PER_SEC / 256) || hz > CLOCKS_PER_SEC) {
printf("cannot set %d Hz clock. using 100 Hz\n", hz);
hz = 100;
}
clkint = CLOCKS_PER_SEC / hz;
mfp_set_tcdcr(mfp_get_tcdcr() & 0x0f); /* stop timer C */
mfp_set_tcdcr(0); /* stop timers C and D */
mfp_set_tcdcr(mfp_get_tcdcr() | 0x70); /* 1/200 delay mode */
mfp_set_tcdr(clkint);
mfp_set_tcdr(CLOCKS_PER_SEC / hz);
mfp_bit_set_ierb(MFP_INTR_TIMER_C);
mfp_set_tddr(0xff); /* maximum free run -- only 8 bits wide */
mfp_set_tcdcr(mfp_get_tcdcr() | 0x07); /* 1/200 prescaler */
tc_init(&tc);
}
/*
@ -196,13 +207,14 @@ setstatclockrate(int newhz)
* Returns number of usec since last recorded clock "tick"
* (i.e. clock interrupt).
*/
int
clkread(void)
unsigned
mfp_get_timecount(struct timecounter *tc)
{
return (clkint - mfp_get_tcdr()) * CLK_RESOLUTION;
uint8_t val;
val = ~(mfp_get_tddr());
return (val);
}
#if 0
void
DELAY(mic)
@ -512,29 +524,6 @@ profclock(caddr_t pc, int ps)
#endif /* PROF */
#endif /* PROFTIMER */
/*
* Return the best possible estimate of the current time.
*/
void
microtime(struct timeval *tvp)
{
static struct timeval lasttime;
*tvp = time;
tvp->tv_usec += clkread();
while (tvp->tv_usec >= 1000000) {
tvp->tv_sec++;
tvp->tv_usec -= 1000000;
}
if (tvp->tv_sec == lasttime.tv_sec &&
tvp->tv_usec <= lasttime.tv_usec &&
(tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
tvp->tv_sec++;
tvp->tv_usec -= 1000000;
}
lasttime = *tvp;
}
#else /* NCLOCK */
#error loose.
#endif