Support for timecounters on acorn32, supplied by Mike Pumford. Only
compile-tested by me, but he promises it works.
This commit is contained in:
parent
cf3258890d
commit
62d6ab40d3
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: types.h,v 1.3 2002/02/28 03:17:24 simonb Exp $ */
|
/* $NetBSD: types.h,v 1.4 2006/08/03 23:19:06 bjh21 Exp $ */
|
||||||
|
|
||||||
#ifndef _ARM32_TYPES_H_
|
#ifndef _ARM32_TYPES_H_
|
||||||
#define _ARM32_TYPES_H_
|
#define _ARM32_TYPES_H_
|
||||||
@ -7,5 +7,5 @@
|
|||||||
|
|
||||||
#define __HAVE_DEVICE_REGISTER
|
#define __HAVE_DEVICE_REGISTER
|
||||||
#define __HAVE_NWSCONS
|
#define __HAVE_NWSCONS
|
||||||
|
#define __HAVE_TIMECOUNTER
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: iomd_clock.c,v 1.18 2006/06/25 21:32:41 christos Exp $ */
|
/* $NetBSD: iomd_clock.c,v 1.19 2006/08/03 23:19:06 bjh21 Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1994-1997 Mark Brinicombe.
|
* Copyright (c) 1994-1997 Mark Brinicombe.
|
||||||
@ -47,12 +47,14 @@
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
__KERNEL_RCSID(0, "$NetBSD: iomd_clock.c,v 1.18 2006/06/25 21:32:41 christos Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: iomd_clock.c,v 1.19 2006/08/03 23:19:06 bjh21 Exp $");
|
||||||
|
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/timetc.h>
|
||||||
#include <sys/device.h>
|
#include <sys/device.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
|
||||||
#include <dev/clock_subr.h>
|
#include <dev/clock_subr.h>
|
||||||
|
|
||||||
@ -76,6 +78,7 @@ static void *clockirq;
|
|||||||
static void *statclockirq;
|
static void *statclockirq;
|
||||||
static struct clock_softc *clock_sc;
|
static struct clock_softc *clock_sc;
|
||||||
static int timer0_count;
|
static int timer0_count;
|
||||||
|
static int timeset;
|
||||||
|
|
||||||
static int clockmatch __P((struct device *parent, struct cfdata *cf, void *aux));
|
static int clockmatch __P((struct device *parent, struct cfdata *cf, void *aux));
|
||||||
static void clockattach __P((struct device *parent, struct device *self, void *aux));
|
static void clockattach __P((struct device *parent, struct device *self, void *aux));
|
||||||
@ -83,6 +86,26 @@ static void clockattach __P((struct device *parent, struct device *self, void *a
|
|||||||
static void checkdelay __P((void));
|
static void checkdelay __P((void));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static u_int iomd_timecounter0_get(struct timecounter *tc);
|
||||||
|
|
||||||
|
|
||||||
|
static volatile uint32_t timer0_lastcount;
|
||||||
|
static volatile uint32_t timer0_offset;
|
||||||
|
static volatile int timer0_ticked;
|
||||||
|
/* TODO: Get IRQ status */
|
||||||
|
|
||||||
|
static struct simplelock tmr_lock = SIMPLELOCK_INITIALIZER; /* protect TC timer variables */
|
||||||
|
|
||||||
|
|
||||||
|
static struct timecounter iomd_timecounter = {
|
||||||
|
iomd_timecounter0_get,
|
||||||
|
0, /* No poll_pps */
|
||||||
|
~0, /* 32bit accuracy */
|
||||||
|
TIMER_FREQUENCY,
|
||||||
|
"iomd_timer0",
|
||||||
|
100
|
||||||
|
};
|
||||||
|
|
||||||
int clockhandler __P((void *));
|
int clockhandler __P((void *));
|
||||||
int statclockhandler __P((void *));
|
int statclockhandler __P((void *));
|
||||||
|
|
||||||
@ -136,6 +159,24 @@ clockattach(parent, self, aux)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
tickle_tc(void)
|
||||||
|
{
|
||||||
|
if (timer0_count &&
|
||||||
|
timecounter->tc_get_timecount == iomd_timecounter0_get) {
|
||||||
|
simple_lock(&tmr_lock);
|
||||||
|
if (timer0_ticked)
|
||||||
|
timer0_ticked = 0;
|
||||||
|
else {
|
||||||
|
timer0_offset += timer0_count;
|
||||||
|
timer0_lastcount = 0;
|
||||||
|
}
|
||||||
|
simple_unlock(&tmr_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* int clockhandler(struct clockframe *frame)
|
* int clockhandler(struct clockframe *frame)
|
||||||
*
|
*
|
||||||
@ -149,6 +190,7 @@ clockhandler(cookie)
|
|||||||
void *cookie;
|
void *cookie;
|
||||||
{
|
{
|
||||||
struct clockframe *frame = cookie;
|
struct clockframe *frame = cookie;
|
||||||
|
tickle_tc();
|
||||||
|
|
||||||
hardclock(frame);
|
hardclock(frame);
|
||||||
return(0); /* Pass the interrupt on down the chain */
|
return(0); /* Pass the interrupt on down the chain */
|
||||||
@ -268,35 +310,21 @@ cpu_initclocks()
|
|||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
checkdelay();
|
checkdelay();
|
||||||
#endif
|
#endif
|
||||||
|
tc_init(&iomd_timecounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* void microtime(struct timeval *tvp)
|
|
||||||
*
|
|
||||||
* Fill in the specified timeval struct with the current time
|
|
||||||
* accurate to the microsecond.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
static u_int iomd_timecounter0_get(struct timecounter *tc)
|
||||||
microtime(tvp)
|
|
||||||
struct timeval *tvp;
|
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int tm;
|
u_int tm;
|
||||||
int deltatm;
|
|
||||||
static struct timeval oldtv;
|
|
||||||
|
|
||||||
if (timer0_count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = splhigh();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Latch the current value of the timer and then read it.
|
* Latch the current value of the timer and then read it.
|
||||||
* This garentees an atmoic reading of the time.
|
* This garentees an atmoic reading of the time.
|
||||||
*/
|
*/
|
||||||
|
s = splhigh();
|
||||||
bus_space_write_1(clock_sc->sc_iot, clock_sc->sc_ioh,
|
bus_space_write_1(clock_sc->sc_iot, clock_sc->sc_ioh,
|
||||||
IOMD_T0LATCH, 0);
|
IOMD_T0LATCH, 0);
|
||||||
|
|
||||||
@ -304,37 +332,27 @@ microtime(tvp)
|
|||||||
IOMD_T0LOW);
|
IOMD_T0LOW);
|
||||||
tm += (bus_space_read_1(clock_sc->sc_iot, clock_sc->sc_ioh,
|
tm += (bus_space_read_1(clock_sc->sc_iot, clock_sc->sc_ioh,
|
||||||
IOMD_T0HIGH) << 8);
|
IOMD_T0HIGH) << 8);
|
||||||
|
splx(s);
|
||||||
|
simple_lock(&tmr_lock);
|
||||||
|
|
||||||
deltatm = timer0_count - tm;
|
tm = timer0_count - tm;
|
||||||
if (deltatm < 0)
|
|
||||||
printf("opps deltatm < 0 tm=%d deltatm=%d\n",
|
|
||||||
tm, deltatm);
|
|
||||||
|
|
||||||
/* Fill in the timeval struct */
|
if (timer0_count &&
|
||||||
*tvp = time;
|
(tm < timer0_lastcount || (!timer0_ticked && FALSE/* XXX: clkintr_pending */))) {
|
||||||
|
timer0_ticked = 1;
|
||||||
tvp->tv_usec += (deltatm / TICKS_PER_MICROSECOND);
|
timer0_offset += timer0_count;
|
||||||
|
|
||||||
/* Make sure the micro seconds don't overflow. */
|
|
||||||
while (tvp->tv_usec >= 1000000) {
|
|
||||||
tvp->tv_usec -= 1000000;
|
|
||||||
++tvp->tv_sec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the time has advanced. */
|
timer0_lastcount = tm;
|
||||||
if (tvp->tv_sec == oldtv.tv_sec &&
|
tm += timer0_offset;
|
||||||
tvp->tv_usec <= oldtv.tv_usec) {
|
|
||||||
tvp->tv_usec = oldtv.tv_usec + 1;
|
simple_unlock(&tmr_lock);
|
||||||
if (tvp->tv_usec >= 1000000) {
|
return tm;
|
||||||
tvp->tv_usec -= 1000000;
|
|
||||||
++tvp->tv_sec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
oldtv = *tvp;
|
|
||||||
(void)splx(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Estimated loop for n microseconds
|
* Estimated loop for n microseconds
|
||||||
*/
|
*/
|
||||||
@ -389,7 +407,13 @@ inittodr(time_t base)
|
|||||||
{
|
{
|
||||||
time_t deltat;
|
time_t deltat;
|
||||||
int badbase;
|
int badbase;
|
||||||
|
int badtime;
|
||||||
|
struct timeval time;
|
||||||
|
struct timespec tc_time; /* for timecounters */
|
||||||
|
|
||||||
|
/* Default is to assume that time from somewhere will be okay.
|
||||||
|
* If not badtime will be set to 1 */
|
||||||
|
badtime = 0;
|
||||||
if (base < (MINYEAR - 1970) * SECYR) {
|
if (base < (MINYEAR - 1970) * SECYR) {
|
||||||
printf("WARNING: preposterous time in file system");
|
printf("WARNING: preposterous time in file system");
|
||||||
/* read the system clock anyway */
|
/* read the system clock anyway */
|
||||||
@ -411,7 +435,7 @@ inittodr(time_t base)
|
|||||||
printf("WARNING: preposterous clock chip time\n");
|
printf("WARNING: preposterous clock chip time\n");
|
||||||
resettodr();
|
resettodr();
|
||||||
}
|
}
|
||||||
goto bad;
|
badtime = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!badbase) {
|
if (!badbase) {
|
||||||
@ -422,14 +446,20 @@ inittodr(time_t base)
|
|||||||
deltat = time.tv_sec - base;
|
deltat = time.tv_sec - base;
|
||||||
if (deltat < 0)
|
if (deltat < 0)
|
||||||
deltat = -deltat;
|
deltat = -deltat;
|
||||||
if (deltat < 2 * SECDAY)
|
if (deltat >= 2 * SECDAY)
|
||||||
return; /* all is well */
|
|
||||||
printf("WARNING: clock %s %ld days\n",
|
printf("WARNING: clock %s %ld days\n",
|
||||||
time.tv_sec < base ? "lost" : "gained",
|
time.tv_sec < base ? "lost" : "gained",
|
||||||
(long)deltat / SECDAY);
|
(long)deltat / SECDAY);
|
||||||
}
|
}
|
||||||
bad:
|
/* At this point time is a time value we can initialise the system
|
||||||
printf("WARNING: CHECK AND RESET THE DATE!\n");
|
* clock with */
|
||||||
|
tc_time.tv_sec = time.tv_sec;
|
||||||
|
tc_time.tv_nsec = time.tv_usec * 1000;
|
||||||
|
tc_setclock(&tc_time);
|
||||||
|
timeset = 1;
|
||||||
|
|
||||||
|
if (badtime)
|
||||||
|
printf("WARNING: CHECK AND RESET THE DATE!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -440,10 +470,11 @@ inittodr(time_t base)
|
|||||||
void
|
void
|
||||||
resettodr(void)
|
resettodr(void)
|
||||||
{
|
{
|
||||||
|
struct timeval time;
|
||||||
if (time.tv_sec == 0)
|
if (!timeset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
getmicrotime(&time);
|
||||||
if (todr_handle != NULL &&
|
if (todr_handle != NULL &&
|
||||||
todr_settime(todr_handle, &time) != 0)
|
todr_settime(todr_handle, &time) != 0)
|
||||||
printf("resettodr: failed to set time\n");
|
printf("resettodr: failed to set time\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user