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

AltStyle によって変換されたページ (->オリジナル) /