Port-arm archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Timecounter patch for testing
Hi all,
please test the attached patch on your or evbarm boards.
It is compile-tested only and I am not sure about the hardware in all
cases. A good test is running "date; sleep 10; date" and "time sleep 1",
which should show the real time. Another test is
src/regress/sys/kern/time. That should be usable on a netbsd-4 world as
well.
I plan to commit this next Sunday.
Joerg
Index: arm/ep93xx/epclk.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/ep93xx/epclk.c,v
retrieving revision 1.10
diff -u -p -r1.10 epclk.c
--- arm/ep93xx/epclk.c 6 Jan 2007 16:18:18 -0000 1.10
+++ arm/ep93xx/epclk.c 7 Jan 2008 17:45:29 -0000
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: epclk.c,v 1.
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/device.h>
#include <machine/bus.h>
@@ -69,8 +70,11 @@ __KERNEL_RCSID(0, "$NetBSD: epclk.c,v 1.
#include "opt_hz.h"
+#define TIMER_FREQ 983040
+
static int epclk_match(struct device *, struct cfdata *, void *);
static void epclk_attach(struct device *, struct device *, void *);
+static u_int epclk_get_timecount(struct timecounter *);
void rtcinit(void);
@@ -88,35 +92,18 @@ struct epclk_softc {
int sc_intr;
};
-static struct epclk_softc *epclk_sc = NULL;
-static u_int32_t tmark;
-
-
-/* This is a quick ARM way to multiply by 983040/1000000 */
-#define US_TO_TIMER4VAL(x) { \
- u_int32_t hi, lo, scalar = 4222124650UL; \
- __asm volatile ( \
- "umull %0, %1, %2, %3;" \
- : "=&r"(lo), "=&r"(hi) \
- : "r"((x)), "r"(scalar) \
- ); \
- (x) = hi; \
-}
-
-/* This is a quick ARM way to multiply by 1000000/983040 */
-#define TIMER4VAL_TO_US(x) { \
- u_int32_t hi, lo, scalar = 2184533333UL; \
- __asm volatile ( \
- "umull %0, %1, %2, %3;" \
- "mov %1, %1, lsl #1;" \
- "mov %0, %0, lsr #31;" \
- "orr %1, %1, %0;" \
- : "=&r"(lo), "=&r"(hi) \
- : "r"((x)), "r"(scalar) \
- ); \
- (x) = hi; \
-}
+static struct timecounter epclk_timecounter = {
+ epclk_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ ~0u, /* counter_mask */
+ TIMER_FREQ, /* frequency */
+ "epclk", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+static struct epclk_softc *epclk_sc = NULL;
CFATTACH_DECL(epclk, sizeof(struct epclk_softc),
epclk_match, epclk_attach, NULL, NULL);
@@ -136,6 +123,7 @@ epclk_attach(struct device *parent, stru
{
struct epclk_softc *sc;
struct epsoc_attach_args *sa;
+ bool first_run;
printf("\n");
@@ -145,8 +133,10 @@ epclk_attach(struct device *parent, stru
sc->sc_baseaddr = sa->sa_addr;
sc->sc_intr = sa->sa_intr;
- if (epclk_sc == NULL)
+ if (epclk_sc == NULL) {
+ first_run = true;
epclk_sc = sc;
+ }
if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size,
0, &sc->sc_ioh))
@@ -160,6 +150,9 @@ epclk_attach(struct device *parent, stru
/* clear and start the debug timer (Timer4) */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, EP93XX_TIMERS_Timer4Enable,
0);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, EP93XX_TIMERS_Timer4Enable,
0x100);
+
+ if (first_run)
+ tc_init(&epclk_timecounter);
}
/*
@@ -172,7 +165,6 @@ epclk_intr(void *arg)
{
struct epclk_softc* sc;
- tmark = TIMER4VAL();
sc = epclk_sc;
#if defined(HZ) && (HZ == 64)
@@ -239,88 +231,54 @@ cpu_initclocks(void)
}
/*
- * microtime:
+ * delay:
*
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
+ * Delay for at least N microseconds.
*/
void
-microtime(register struct timeval *tvp)
+delay(unsigned int n)
{
- u_int oldirqstate;
- u_int tmarknow, delta;
- static struct timeval lasttv;
+ unsigned int cur_tick, initial_tick;
+ int remaining;
#ifdef DEBUG
if (epclk_sc == NULL) {
- printf("microtime: called before initialize epclk\n");
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
+ printf("delay: called before start epclk\n");
return;
}
#endif
- oldirqstate = disable_interrupts(I32_bit);
- tmarknow = TIMER4VAL();
-
- /* Fill in the timeval struct. */
- *tvp = time;
- if (__predict_false(tmarknow < tmark)) { /* overflow */
- delta = tmarknow + (UINT_MAX - tmark);
+ /*
+ * Read the counter first, so that the rest of the setup overhead is
+ * counted.
+ */
+ initial_tick = TIMER4VAL();
+
+ if (n <= UINT_MAX / TIMER_FREQ) {
+ /*
+ * For unsigned arithmetic, division can be replaced with
+ * multiplication with the inverse and a shift.
+ */
+ remaining = n * TIMER_FREQ / 1000000;
} else {
- delta = tmarknow - tmark;
- }
-
- TIMER4VAL_TO_US(delta);
-
- tvp->tv_usec += delta;
-
- /* Make sure microseconds doesn't overflow. */
- while (__predict_false(tvp->tv_usec >= 1000000)) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
+ /* This is a very long delay.
+ * Being slow here doesn't matter.
+ */
+ remaining = (unsigned long long) n * TIMER_FREQ / 1000000;
}
- /* Make sure the time has advanced. */
- if (__predict_false(tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec)) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
+ while (remaining > 0) {
+ cur_tick = TIMER4VAL();
+ if (cur_tick > initial_tick)
+ remaining -= UINT_MAX - (cur_tick - initial_tick);
+ else
+ remaining -= initial_tick - cur_tick;
+ initial_tick = cur_tick;
}
-
- lasttv = *tvp;
-
- restore_interrupts(oldirqstate);
}
-/*
- * delay:
- *
- * Delay for at least N microseconds.
- */
-void
-delay(unsigned int len)
+static u_int
+epclk_get_timecount(struct timecounter *tc)
{
- u_int32_t start, end, ticks;
-
-#ifdef DEBUG
- if (epclk_sc == NULL) {
- printf("delay: called before start epclk\n");
- return;
- }
-#endif
-
- ticks = start = TIMER4VAL();
- US_TO_TIMER4VAL(len);
- end = start + len;
- while (start <= ticks && ticks > end) {
- /* wait for Timer4ValueLow wraparound */
- ticks = TIMER4VAL();
- }
- while (ticks <= end) {
- ticks = TIMER4VAL();
- }
+ return TIMER4VAL();
}
Index: arm/include/types.h
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/include/types.h,v
retrieving revision 1.14
diff -u -p -r1.14 types.h
--- arm/include/types.h 9 Mar 2007 05:40:08 -0000 1.14
+++ arm/include/types.h 7 Jan 2008 16:55:51 -0000
@@ -81,4 +81,6 @@ typedef volatile int __cpu_simple_lock_
#define __HAVE_RAS
#endif
+#define __HAVE_TIMECOUNTER
+
#endif /* _ARM_TYPES_H_ */
Index: arm/ixp12x0/ixp12x0_clk.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/ixp12x0/ixp12x0_clk.c,v
retrieving revision 1.11
diff -u -p -r1.11 ixp12x0_clk.c
--- arm/ixp12x0/ixp12x0_clk.c 6 Jan 2007 16:18:18 -0000 1.11
+++ arm/ixp12x0/ixp12x0_clk.c 8 Jan 2008 17:19:45 -0000
@@ -42,9 +42,11 @@ __KERNEL_RCSID(0, "$NetBSD: ixp12x0_clk.
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/atomic.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/device.h>
#include <machine/bus.h>
@@ -61,6 +63,8 @@ __KERNEL_RCSID(0, "$NetBSD: ixp12x0_clk.
static int ixpclk_match(struct device *, struct cfdata *, void *);
static void ixpclk_attach(struct device *, struct device *, void *);
+static u_int ixpclk_get_timecount(struct timecounter *);
+
int gettick(void);
void rtcinit(void);
@@ -119,6 +123,19 @@ static u_int32_t ccf_to_coreclock[MAX_CC
static struct ixpclk_softc *ixpclk_sc = NULL;
+static struct timecounter ixpclk_timecounter = {
+ ixpclk_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ 0, /* frequency */
+ "ixpclk", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t ixpclk_base;
+
#define TIMER_FREQUENCY 3686400 /* 3.6864MHz */
#define TICKS_PER_MICROSECOND (TIMER_FREQUENCY/1000000)
@@ -143,6 +160,7 @@ ixpclk_attach(struct device *parent, str
struct ixpclk_softc *sc;
struct ixpsip_attach_args *sa;
u_int32_t ccf;
+ bool first_run = ixpclk_sc == NULL;
printf("\n");
@@ -181,6 +199,11 @@ ixpclk_attach(struct device *parent, str
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_CONTROL,
IXPCL_ENABLE | IXPCL_PERIODIC | IXPCL_STP_CORE);
+ if (first_run) {
+ ixpclk_timecounter.tc_frequency = sc->sc_coreclock_freq;
+ tc_init(&ixpclk_timecounter);
+ }
+
printf("%s: IXP12x0 Interval Timer (core clock %d.%03dMHz)\n",
sc->sc_dev.dv_xname,
sc->sc_coreclock_freq / 1000000,
@@ -199,6 +222,8 @@ ixpclk_intr(void *arg)
bus_space_write_4(ixpclk_sc->sc_iot, ixpclk_sc->sc_ioh,
IXPCLK_CLEAR, 1);
+ atomic_add_32(&ixpclk_base, ixpclk_sc->sc_coreclock_freq);
+
hardclock((struct clockframe*) arg);
return (1);
}
@@ -261,55 +286,19 @@ gettick(void)
return counter;
}
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(register struct timeval *tvp)
+static u_int
+ixpclk_get_timecount(struct timecounter *tc)
{
- u_int oldirqstate;
- u_int32_t counts;
- static struct timeval lasttv;
+ u_int savedints, base, counter;
- if (ixpclk_sc == NULL) {
-#ifdef DEBUG
- printf("microtime: called befor initialize ixpclk\n");
-#endif
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- return;
- }
-
- oldirqstate = disable_interrupts(I32_bit);
-
- counts = ixpclk_sc->sc_clock_count - GET_TIMER_VALUE(ixpclk_sc);
-
- /* Fill in the timeval struct. */
- *tvp = time;
- tvp->tv_usec += counts / ixpclk_sc->sc_count_per_usec;
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
-
- /* Make sure the time has advanced. */
- if (tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- lasttv = *tvp;
+ savedints = disable_interrupts(I32_bit);
+ do {
+ base = ixpclk_base;
+ counter = GET_TIMER_VALUE(ixpclk_sc);
+ } while (base != ixpclk_base);
+ restore_interrupts(savedints);
- restore_interrupts(oldirqstate);
+ return base - counter;
}
/*
Index: arm/ofw/ofwgencfg_clock.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/ofw/ofwgencfg_clock.c,v
retrieving revision 1.7
diff -u -p -r1.7 ofwgencfg_clock.c
--- arm/ofw/ofwgencfg_clock.c 8 Mar 2007 20:48:39 -0000 1.7
+++ arm/ofw/ofwgencfg_clock.c 8 Jan 2008 18:12:09 -0000
@@ -135,50 +135,6 @@ cpu_initclocks()
}
}
-
-/*
- * void microtime(struct timeval *tvp)
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-
-void
-microtime(tvp)
- struct timeval *tvp;
-{
- int s;
- static struct timeval oldtv;
-
- s = splhigh();
-
- /* Fill in the timeval struct */
-
- *tvp = time;
-
- /* 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. */
-
- if (tvp->tv_sec == oldtv.tv_sec &&
- tvp->tv_usec <= oldtv.tv_usec) {
- tvp->tv_usec = oldtv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- ++tvp->tv_sec;
- }
- }
-
-
- oldtv = *tvp;
- (void)splx(s);
-}
-
/*
* Estimated loop for n microseconds
*/
Index: arm/omap/omap_mputmr.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/omap/omap_mputmr.c,v
retrieving revision 1.2
diff -u -p -r1.2 omap_mputmr.c
--- arm/omap/omap_mputmr.c 6 Jan 2008 01:37:55 -0000 1.2
+++ arm/omap/omap_mputmr.c 12 Jan 2008 23:29:40 -0000
@@ -80,6 +80,7 @@ __KERNEL_RCSID(0, "$NetBSD: omap_mputmr.
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/device.h>
#include <dev/clock_subr.h>
@@ -115,7 +116,6 @@ struct omapmputmr_softc {
static uint32_t counts_per_usec, counts_per_hz;
static uint32_t hardref;
-static struct timeval hardtime;
static struct omapmputmr_softc *clock_sc = NULL;
static struct omapmputmr_softc *stat_sc = NULL;
static struct omapmputmr_softc *ref_sc = NULL;
@@ -237,11 +237,9 @@ clockintr(void *arg)
int ticks, i, oldirqstate;
oldirqstate = disable_interrupts(I32_bit);
- hardtime = time;
newref = bus_space_read_4(ref_sc->sc_iot, ref_sc->sc_ioh,
MPU_READ_TIMER);
ticks = hardref ? (hardref - newref) / counts_per_hz : 1;
- hardtime.tv_usec += (hardref - newref) / counts_per_usec;
hardref = newref;
restore_interrupts(oldirqstate);
@@ -300,6 +298,31 @@ setstatclockrate(int schz)
| MPU_ST));
}
+static u_int
+mpu_get_timecount(struct timecounter *tc)
+{
+ uint32_t counter;
+ int oldirqstate;
+
+ oldirqstate = disable_interrupts(I32_bit);
+ counter = bus_space_read_4(ref_sc->sc_iot, ref_sc->sc_ioh,
+ MPU_READ_TIMER);
+ restore_interrupts(oldirqstate);
+
+ return counter;
+}
+
+static struct timecounter mpu_timecounter = {
+ mpu_get_timecount,
+ NULL,
+ 0xffffffff,
+ 0,
+ "mpu",
+ 100,
+ NULL,
+ NULL,
+};
+
void
cpu_initclocks(void)
{
@@ -325,61 +348,8 @@ cpu_initclocks(void)
clock_sc->sc_dev.dv_xname, clockintr, 0);
omap_intr_establish(stat_sc->sc_intr, IPL_HIGH,
stat_sc->sc_dev.dv_xname, statintr, 0);
-}
-
-void
-microtime(struct timeval *tvp)
-{
- u_int oldirqstate;
- uint32_t ref, baseref;
- static struct timeval lasttime;
- static uint32_t lastref;
-
- if (clock_sc == NULL) {
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- return;
- }
- oldirqstate = disable_interrupts(I32_bit);
- ref = bus_space_read_4(ref_sc->sc_iot, ref_sc->sc_ioh,
- MPU_READ_TIMER);
-
- *tvp = hardtime;
- baseref = hardref;
-
- /*
- * If time was just jumped forward and hardtime hasn't caught up
- * then just use time.
- */
-
- if (time.tv_sec - hardtime.tv_sec > 1)
- *tvp = time;
-
- if (tvp->tv_sec < lasttime.tv_sec ||
- (tvp->tv_sec == lasttime.tv_sec &&
- tvp->tv_usec < lasttime.tv_usec)) {
- *tvp = lasttime;
- baseref = lastref;
-
- } else {
- lasttime = *tvp;
- lastref = ref;
- }
-
- restore_interrupts(oldirqstate);
-
- /* Prior to the first hardclock completion we don't have a
- microtimer reference. */
-
- if (baseref)
- tvp->tv_usec += (baseref - ref) / counts_per_usec;
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
+ tc_init(&mpu_timecounter);
}
void
Index: arm/s3c2xx0/s3c24x0_clk.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c,v
retrieving revision 1.8
diff -u -p -r1.8 s3c24x0_clk.c
--- arm/s3c2xx0/s3c24x0_clk.c 6 Jan 2008 01:37:55 -0000 1.8
+++ arm/s3c2xx0/s3c24x0_clk.c 12 Jan 2008 23:18:02 -0000
@@ -35,7 +35,9 @@ __KERNEL_RCSID(0, "$NetBSD: s3c24x0_clk.
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/intr.h>
@@ -61,27 +63,26 @@ static unsigned int timer4_mseccount;
#define counter_to_usec(c,pclk) \
(((c)*timer4_prescaler*1000)/(TIMER_FREQUENCY(pclk)/1000))
+static u_int s3c24x0_get_timecount(struct timecounter *);
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
+static struct timecounter s3c24x0_timecounter = {
+ s3c24x0_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ 0, /* frequency */
+ "s3c234x0", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t s3c24x0_base;
+
+static u_int
+s3c24x0_get_timecount(struct timecounter *tc)
{
struct s3c24x0_softc *sc = (struct s3c24x0_softc *) s3c2xx0_softc;
- int save, int_pend0, int_pend1, count, delta;
- static struct timeval last;
- int pclk = s3c2xx0_softc->sc_pclk;
-
- if( timer4_reload_value == 0 ){
- /* not initialized yet */
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- return;
- }
+ int save, int_pend0, int_pend1, count;
save = disable_interrupts(I32_bit);
@@ -92,7 +93,7 @@ microtime(struct timeval *tvp)
count = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh,
TIMER_TCNTO(4));
- for (;;){
+ for (;;) {
int_pend1 = S3C24X0_INT_TIMER4 &
bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_intctl_ioh,
@@ -109,63 +110,22 @@ microtime(struct timeval *tvp)
TIMER_TCNTO(4));
}
- if( __predict_false(count > timer4_reload_value) ){
+ if (__predict_false(count > timer4_reload_value)) {
/*
* Buggy Hardware Warning --- sometimes timer counter
* reads bogus value like 0xffff. I guess it happens when
* the timer is reloaded.
*/
- printf( "Bogus value from timer counter: %d\n", count );
+ printf("Bogus value from timer counter: %d\n", count);
goto again;
}
- /* copy system time */
- *tvp = time;
-
restore_interrupts(save);
- delta = timer4_reload_value - count;
-
- if( int_pend1 ){
- /*
- * down counter underflow, but
- * clock interrupt have not serviced yet
- */
- tvp->tv_usec += tick;
- }
-
- tvp->tv_usec += counter_to_usec(delta, pclk);
-
- /* Make sure microseconds doesn't overflow. */
- tvp->tv_sec += tvp->tv_usec / 1000000;
- tvp->tv_usec = tvp->tv_usec % 1000000;
-
- if (last.tv_sec &&
- (tvp->tv_sec < last.tv_sec ||
- (tvp->tv_sec == last.tv_sec &&
- tvp->tv_usec < last.tv_usec) ) ){
-
- /* XXX: This happens very often when the kernel runs
- under Multi-ICE */
-#if 0
- printf("time reversal: %ld.%06ld(%d,%d) -> %ld.%06ld(%d,%d)\n",
- last.tv_sec, last.tv_usec,
- last_count, last_pend,
- tvp->tv_sec, tvp->tv_usec,
- count, int_pend1 );
-#endif
-
- /* make sure the time has advanced. */
- *tvp = last;
- tvp->tv_usec++;
- if( tvp->tv_usec >= 1000000 ){
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- last = *tvp;
+ if (int_pend1)
+ count -= timer4_reload_value;
+ return s3c24x0_base - count;
}
static inline int
@@ -235,8 +195,15 @@ setstatclockrate(int newhz)
{
}
-#define hardintr (int (*)(void *))hardclock
-#define statintr (int (*)(void *))statclock
+static int
+hardintr(void *arg)
+{
+ atomic_add_32(&s3c24x0_base, timer4_reload_value);
+
+ hardclock((struct clockframe *)arg);
+
+ return 1;
+}
void
cpu_initclocks(void)
@@ -316,6 +283,9 @@ cpu_initclocks(void)
bus_space_write_4(iot, ioh, TIMER_TCON, reg |
TCON_AUTORELOAD(3) | TCON_START(3) |
TCON_AUTORELOAD(4) | TCON_START(4) );
+
+ s3c24x0_timecounter.tc_frequency = pclk;
+ tc_init(&s3c24x0_timecounter);
}
Index: arm/s3c2xx0/s3c2800_clk.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/s3c2xx0/s3c2800_clk.c,v
retrieving revision 1.11
diff -u -p -r1.11 s3c2800_clk.c
--- arm/s3c2xx0/s3c2800_clk.c 6 Jan 2008 01:37:55 -0000 1.11
+++ arm/s3c2xx0/s3c2800_clk.c 12 Jan 2008 23:17:50 -0000
@@ -39,7 +39,9 @@ __KERNEL_RCSID(0, "$NetBSD: s3c2800_clk.
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/intr.h>
@@ -65,26 +67,26 @@ static unsigned int timer0_mseccount;
#define counter_to_usec(c,pclk) \
(((c)*timer0_prescaler*1000)/(TIMER_FREQUENCY(pclk)/1000))
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
+static u_int s3c2800_get_timecount(struct timecounter *);
+
+static struct timecounter s3c2800_timecounter = {
+ s3c2800_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ 0, /* frequency */
+ "s3c23800", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t s3c2800_base;
+
+static u_int
+s3c2800_get_timecount(struct timecounter *tc)
{
struct s3c2800_softc *sc = (struct s3c2800_softc *) s3c2xx0_softc;
- int save, int_pend0, int_pend1, count, delta;
- static struct timeval last;
- int pclk = s3c2xx0_softc->sc_pclk;
-
- if( timer0_reload_value == 0 ){
- /* not initialized yet */
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- return;
- }
+ int save, int_pend0, int_pend1, count;
save = disable_interrupts(I32_bit);
@@ -124,56 +126,12 @@ microtime(struct timeval *tvp)
goto again;
}
- /* copy system time */
- *tvp = time;
-
restore_interrupts(save);
- delta = timer0_reload_value - count;
+ if (int_pend1)
+ count -= timer0_reload_value;
- if( int_pend1 ){
- /*
- * down counter underflow, but
- * clock interrupt have not serviced yet
- */
-#if 1
- tvp->tv_usec += tick;
-#else
- delta = 0;
-#endif
- }
-
- tvp->tv_usec += counter_to_usec(delta, pclk);
-
- /* Make sure microseconds doesn't overflow. */
- tvp->tv_sec += tvp->tv_usec / 1000000;
- tvp->tv_usec = tvp->tv_usec % 1000000;
-
- if (last.tv_sec &&
- (tvp->tv_sec < last.tv_sec ||
- (tvp->tv_sec == last.tv_sec &&
- tvp->tv_usec < last.tv_usec) ) ){
-
- /* XXX: This happens very often when the kernel runs
- under Multi-ICE */
-#if 0
- printf("time reversal: %ld.%06ld(%d,%d) -> %ld.%06ld(%d,%d)\n",
- last.tv_sec, last.tv_usec,
- last_count, last_pend,
- tvp->tv_sec, tvp->tv_usec,
- count, int_pend1 );
-#endif
-
- /* make sure the time has advanced. */
- *tvp = last;
- tvp->tv_usec++;
- if( tvp->tv_usec >= 1000000 ){
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- last = *tvp;
+ return s3c2800_base - count;
}
static inline int
@@ -243,9 +201,15 @@ setstatclockrate(int newhz)
{
}
+static int
+hardintr(void *arg)
+{
+ atomic_add_32(&s3c2800_base, timer4_reload_value);
-#define hardintr (int (*)(void *))hardclock
-#define statintr (int (*)(void *))statclock
+ hardclock((struct clockframe *)arg);
+
+ return 1;
+}
void
cpu_initclocks()
@@ -313,4 +277,7 @@ cpu_initclocks()
S3C2800_TIMER_SIZE);
}
+
+ s3c2800_timecounter.tc_frequency = pclk;
+ tc_init(&s3c2800_timecounter);
}
Index: arm/sa11x0/sa11x0_ost.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/sa11x0/sa11x0_ost.c,v
retrieving revision 1.20
diff -u -p -r1.20 sa11x0_ost.c
--- arm/sa11x0/sa11x0_ost.c 24 Sep 2006 15:40:14 -0000 1.20
+++ arm/sa11x0/sa11x0_ost.c 7 Jan 2008 16:50:48 -0000
@@ -60,9 +60,7 @@ __KERNEL_RCSID(0, "$NetBSD: sa11x0_ost.c
static int saost_match(struct device *, struct cfdata *, void *);
static void saost_attach(struct device *, struct device *, void *);
-#ifdef __HAVE_TIMECOUNTER
static void saost_tc_init(void);
-#endif /* __HAVE_TIMECOUNTER */
static uint32_t gettick(void);
static int clockintr(void *);
@@ -239,12 +237,9 @@ cpu_initclocks(void)
/* Zero the counter value */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, SAOST_CR, 0);
-#ifdef __HAVE_TIMECOUNTER
saost_tc_init();
-#endif /* __HAVE_TIMECOUNTER */
}
-#ifdef __HAVE_TIMECOUNTER
static u_int
saost_tc_get_timecount(struct timecounter *tc)
{
@@ -264,7 +259,6 @@ saost_tc_init(void)
tc_init(&saost_tc);
}
-#endif /* __HAVE_TIMECOUNTER */
static uint32_t
gettick(void)
@@ -280,44 +274,6 @@ gettick(void)
return counter;
}
-#ifndef __HAVE_TIMECOUNTER
-void
-microtime(struct timeval *tvp)
-{
- struct saost_softc *sc = saost_sc;
- int s, tm, deltatm;
- static struct timeval lasttime;
-
- if (sc == NULL) {
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- return;
- }
-
- s = splhigh();
- tm = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAOST_CR);
-
- deltatm = sc->sc_clock_count - tm;
-
- *tvp = time;
- tvp->tv_usec++; /* XXX */
- 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;
- splx(s);
-}
-#endif /* !__HAVE_TIMECOUNTER */
-
void
delay(u_int usecs)
{
Index: arm/xscale/becc_timer.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/xscale/becc_timer.c,v
retrieving revision 1.13
diff -u -p -r1.13 becc_timer.c
--- arm/xscale/becc_timer.c 6 Jan 2008 01:37:57 -0000 1.13
+++ arm/xscale/becc_timer.c 8 Jan 2008 21:01:10 -0000
@@ -45,7 +45,9 @@ __KERNEL_RCSID(0, "$NetBSD: becc_timer.c
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <dev/clock_subr.h>
@@ -65,6 +67,21 @@ void (*becc_hardclock_hook)(void);
static void *clock_ih;
+static u_int becc_get_timecount(struct timecounter *);
+
+static struct timecounter becc_timecounter = {
+ becc_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ COUNTS_PER_SEC, /* frequency */
+ "becc", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t becc_base;
+
/*
* Since the timer interrupts when the counter underflows, we need to
* subtract 1 from counts_per_hz when loading the preload register.
@@ -115,15 +132,6 @@ cpu_initclocks(void)
hz = 100;
}
#endif
- tick = 1000000 / hz; /* number of microseconds between interrupts */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
/*
* We only have one timer available; stathz and profhz are
@@ -168,6 +176,8 @@ cpu_initclocks(void)
#endif
restore_interrupts(oldirqstate);
+
+ tc_init(&becc_timecounter);
}
/*
@@ -188,49 +198,18 @@ setstatclockrate(int new_hz)
*/
}
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
+static u_int
+becc_get_timecount(struct timecounter *tc)
{
- static struct timeval lasttv;
+ uint32_t counter, base;
u_int oldirqstate;
- uint32_t counts;
oldirqstate = disable_interrupts(I32_bit);
-
- /*
- * XXX How do we compensate for the -1 behavior of the preload value?
- */
- counts = counts_per_hz - BECC_CSR_READ(BECC_TCVRA);
-
- /* Fill in the timeval struct. */
- *tvp = time;
- tvp->tv_usec += (counts / COUNTS_PER_USEC);
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
-
- /* Make sure the time has advanced. */
- if (tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- lasttv = *tvp;
-
+ counter = BECC_CSR_READ(BECC_TCVRA);
+ base = becc_base;
restore_interrupts(oldirqstate);
+
+ return base - counter;
}
/*
@@ -283,6 +262,8 @@ clockhandler(void *arg)
hardclock(frame);
+ atomic_add_32(&becc_base, counts_per_hz);
+
if (becc_hardclock_hook != NULL)
(*becc_hardclock_hook)();
Index: arm/xscale/i80321_timer.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/xscale/i80321_timer.c,v
retrieving revision 1.17
diff -u -p -r1.17 i80321_timer.c
--- arm/xscale/i80321_timer.c 3 Dec 2007 15:33:20 -0000 1.17
+++ arm/xscale/i80321_timer.c 7 Jan 2008 16:51:28 -0000
@@ -68,9 +68,7 @@ void (*i80321_hardclock_hook)(void);
#endif
#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000)
-#ifdef __HAVE_TIMECOUNTER
static void tmr1_tc_init(void);
-#endif
static void *clock_ih;
@@ -125,8 +123,6 @@ trr0_write(uint32_t val)
: "r" (val));
}
-#ifdef __HAVE_TIMECOUNTER
-
static inline uint32_t
tmr1_read(void)
{
@@ -174,8 +170,6 @@ trr1_write(uint32_t val)
: "r" (val));
}
-#endif /* __HAVE_TIMECOUNTER */
-
static inline void
tisr_write(uint32_t val)
{
@@ -225,17 +219,6 @@ cpu_initclocks(void)
aprint_error("Cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
}
-#ifndef __HAVE_TIMECOUNTER
- tick = 1000000 / hz; /* number of microseconds between interrupts */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
-#endif
/*
* We only have one timer available; stathz and profhz are
@@ -282,9 +265,7 @@ cpu_initclocks(void)
restore_interrupts(oldirqstate);
-#ifdef __HAVE_TIMECOUNTER
tmr1_tc_init();
-#endif
}
/*
@@ -305,53 +286,6 @@ setstatclockrate(int newhz)
*/
}
-#ifndef __HAVE_TIMECOUNTER
-
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
-{
- static struct timeval lasttv;
- u_int oldirqstate;
- uint32_t counts;
-
- oldirqstate = disable_interrupts(I32_bit);
-
- counts = counts_per_hz - tcr0_read();
-
- /* Fill in the timeval struct. */
- *tvp = time;
- tvp->tv_usec += (counts / COUNTS_PER_USEC);
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
-
- /* Make sure the time has advanced. */
- if (tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- lasttv = *tvp;
-
- restore_interrupts(oldirqstate);
-}
-
-
-#else
-
static inline uint32_t
tmr1_tc_get(struct timecounter *tch)
{
@@ -379,7 +313,6 @@ tmr1_tc_init(void)
trr1_write(~0);
tc_init(&tmr1_tc);
}
-#endif
/*
* delay:
Index: arm/xscale/ixp425_timer.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/arm/xscale/ixp425_timer.c,v
retrieving revision 1.13
diff -u -p -r1.13 ixp425_timer.c
--- arm/xscale/ixp425_timer.c 6 Jan 2007 16:18:18 -0000 1.13
+++ arm/xscale/ixp425_timer.c 8 Jan 2008 20:50:29 -0000
@@ -43,7 +43,9 @@ __KERNEL_RCSID(0, "$NetBSD: ixp425_timer
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/device.h>
#include <dev/clock_subr.h>
@@ -59,6 +61,7 @@ __KERNEL_RCSID(0, "$NetBSD: ixp425_timer
static int ixpclk_match(struct device *, struct cfdata *, void *);
static void ixpclk_attach(struct device *, struct device *, void *);
+static u_int ixpclk_get_timecount(struct timecounter *);
static uint32_t counts_per_hz;
@@ -83,6 +86,19 @@ struct ixpclk_softc {
static struct ixpclk_softc *ixpclk_sc;
+static struct timecounter ixpclk_timecounter = {
+ ixpclk_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ COUNTS_PER_SEC, /* frequency */
+ "ixpclk", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t ixpclk_base;
+
CFATTACH_DECL(ixpclk, sizeof(struct ixpclk_softc),
ixpclk_match, ixpclk_attach, NULL, NULL);
@@ -137,15 +153,6 @@ cpu_initclocks(void)
aprint_error("Cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
}
- tick = 1000000 / hz; /* number of microseconds between interrupts */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
/*
* We only have one timer available; stathz and profhz are
@@ -192,6 +199,8 @@ cpu_initclocks(void)
(counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN);
restore_interrupts(oldirqstate);
+
+ tc_init(&ixpclk_timecounter);
}
/*
@@ -212,47 +221,17 @@ setstatclockrate(int newhz)
*/
}
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
+static u_int
+ixpclk_get_timecount(struct timecounter *tc)
{
- struct ixpclk_softc* sc = ixpclk_sc;
- static struct timeval lasttv;
- u_int oldirqstate;
- uint32_t counts;
-
- oldirqstate = disable_interrupts(I32_bit);
-
- counts = counts_per_hz - GET_TIMER_VALUE(sc);
-
- /* Fill in the timeval struct. */
- *tvp = time;
- tvp->tv_usec += (counts / COUNTS_PER_USEC);
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
-
- /* Make sure the time has advanced. */
- if (tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
+ u_int savedints, base, counter;
- lasttv = *tvp;
+ savedints = disable_interrupts(I32_bit);
+ base = ixpclk_base;
+ counter = GET_TIMER_VALUE(ixpclk_sc);
+ restore_interrupts(savedints);
- restore_interrupts(oldirqstate);
+ return base - counter;
}
/*
@@ -304,6 +283,8 @@ ixpclk_intr(void *arg)
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
OST_TIM0_INT);
+ atomic_add_32(&ixpclk_base, counts_per_hz);
+
hardclock(frame);
return (1);
Index: evbarm/ifpga/ifpga_clock.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/evbarm/ifpga/ifpga_clock.c,v
retrieving revision 1.11
diff -u -p -r1.11 ifpga_clock.c
--- evbarm/ifpga/ifpga_clock.c 22 Dec 2007 01:21:41 -0000 1.11
+++ evbarm/ifpga/ifpga_clock.c 8 Jan 2008 21:23:37 -0000
@@ -45,7 +45,9 @@ __KERNEL_RCSID(0, "$NetBSD: ifpga_clock.
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/device.h>
#include <arm/cpufunc.h>
@@ -81,6 +83,21 @@ static int statprev; /* previous value
#define COUNTS_PER_SEC (IFPGA_TIMER1_FREQ / 16)
+static u_int ifpga_get_timecount(struct timecounter *);
+
+static struct timecounter ifpga_timecounter = {
+ ifpga_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ COUNTS_PER_SEC, /* frequency */
+ "ifpga", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t ifpga_base;
+
extern struct ifpga_softc *ifpga_sc;
static int clock_started = 0;
@@ -115,6 +132,9 @@ clockhandler(void *fr)
bus_space_write_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh,
TIMER_1_CLEAR, 0);
+
+ atomic_add_32(&ifpga_base, ifpga_sc->sc_clock_count);
+
hardclock(frame);
return 0; /* Pass the interrupt on down the chain */
}
@@ -288,60 +308,21 @@ cpu_initclocks()
panic("%s: Cannot install timer 2 interrupt handler",
ifpga_sc->sc_dev.dv_xname);
load_timer(IFPGA_TIMER2_BASE, statint);
-}
+ tc_init(&ifpga_timecounter);
+}
-/*
- * void microtime(struct timeval *tvp)
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-
-void
-microtime(struct timeval *tvp)
+static u_int
+ifpga_get_timecount(struct timecounter *tc)
{
- int s;
- int tm;
- int deltatm;
- static struct timeval oldtv;
+ u_int base, counter;
- if (ifpga_sc == NULL || ifpga_sc->sc_clock_count == 0)
- return;
-
- s = splhigh();
-
- tm = getclock();
-
- deltatm = ifpga_sc->sc_clock_count - tm;
-
-#ifdef DIAGNOSTIC
- if (deltatm < 0)
- panic("opps deltatm < 0 tm=%d deltatm=%d", tm, deltatm);
-#endif
-
- /* Fill in the timeval struct */
- *tvp = time;
- tvp->tv_usec += ((deltatm << 8) / ifpga_sc->sc_clock_ticks_per_256us);
-
- /* 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. */
- if (tvp->tv_sec == oldtv.tv_sec &&
- tvp->tv_usec <= oldtv.tv_usec) {
- tvp->tv_usec = oldtv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- ++tvp->tv_sec;
- }
- }
+ do {
+ base = ifpga_base;
+ counter = getclock();
+ } while (base != ifpga_base);
- oldtv = *tvp;
- (void)splx(s);
+ return base - counter;
}
/*
Index: evbarm/iq80310/iq80310_timer.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/evbarm/iq80310/iq80310_timer.c,v
retrieving revision 1.20
diff -u -p -r1.20 iq80310_timer.c
--- evbarm/iq80310/iq80310_timer.c 19 Feb 2007 02:08:12 -0000 1.20
+++ evbarm/iq80310/iq80310_timer.c 8 Jan 2008 18:21:05 -0000
@@ -52,7 +52,9 @@ __KERNEL_RCSID(0, "$NetBSD: iq80310_time
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <dev/clock_subr.h>
@@ -80,6 +82,21 @@ static void *clock_ih;
static uint32_t counts_per_hz;
+static u_int iq80310_get_timecount(struct timecounter *);
+
+static struct timecounter iq80310_timecounter = {
+ iq80310_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffff, /* counter_mask */
+ COUNTS_PER_SEC, /* frequency */
+ "iq80310", /* name */
+ 100, /* quality */
+ NULL, /* prev */
+ NULL, /* next */
+};
+
+static volatile uint32_t iq80310_base;
+
int clockhandler(void *);
static inline void
@@ -177,15 +194,6 @@ cpu_initclocks(void)
printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
}
- tick = 1000000 / hz; /* number of microseconds between interrupts */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
/*
* We only have one timer available; stathz and profhz are
@@ -221,6 +229,8 @@ cpu_initclocks(void)
timer_enable(TIMER_ENABLE_EN);
restore_interrupts(oldirqstate);
+
+ tc_init(&iq80310_timecounter);
}
/*
@@ -242,46 +252,17 @@ setstatclockrate(int newhz)
*/
}
-/*
- * microtime:
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
-void
-microtime(struct timeval *tvp)
+static u_int
+iq80310_get_timecount(struct timecounter *tc)
{
- static struct timeval lasttv;
- u_int oldirqstate;
- uint32_t counts;
+ u_int oldirqstate, base, counter;
oldirqstate = disable_interrupts(I32_bit);
-
- counts = timer_read();
-
- /* Fill in the timeval struct. */
- *tvp = time;
- tvp->tv_usec += (counts / COUNTS_PER_USEC);
-
- /* Make sure microseconds doesn't overflow. */
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
-
- /* Make sure the time has advanced. */
- if (tvp->tv_sec == lasttv.tv_sec &&
- tvp->tv_usec <= lasttv.tv_usec) {
- tvp->tv_usec = lasttv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- tvp->tv_sec++;
- }
- }
-
- lasttv = *tvp;
-
+ base = iq80310_base;
+ counter = timer_read();
restore_interrupts(oldirqstate);
+
+ return base + counter;
}
/*
@@ -332,6 +313,8 @@ clockhandler(void *arg)
timer_disable(TIMER_ENABLE_INTEN);
timer_enable(TIMER_ENABLE_INTEN);
+ atomic_add_32(&iq80310_base, counts_per_hz);
+
hardclock(frame);
/*
Home |
Main Index |
Thread Index |
Old Index