Home | History | Annotate | Line # | Download | only in footbridge
footbridge_clock.c revision 1.20.12.1
      1  1.20.12.1     tron /*	$NetBSD: footbridge_clock.c,v 1.20.12.1 2006/05/24 15:47:51 tron Exp $	*/
      2        1.1    chris 
      3        1.1    chris /*
      4        1.1    chris  * Copyright (c) 1997 Mark Brinicombe.
      5        1.1    chris  * Copyright (c) 1997 Causality Limited.
      6        1.1    chris  * All rights reserved.
      7        1.1    chris  *
      8        1.1    chris  * Redistribution and use in source and binary forms, with or without
      9        1.1    chris  * modification, are permitted provided that the following conditions
     10        1.1    chris  * are met:
     11        1.1    chris  * 1. Redistributions of source code must retain the above copyright
     12        1.1    chris  *    notice, this list of conditions and the following disclaimer.
     13        1.1    chris  * 2. Redistributions in binary form must reproduce the above copyright
     14        1.1    chris  *    notice, this list of conditions and the following disclaimer in the
     15        1.1    chris  *    documentation and/or other materials provided with the distribution.
     16        1.1    chris  * 3. All advertising materials mentioning features or use of this software
     17        1.1    chris  *    must display the following acknowledgement:
     18        1.1    chris  *	This product includes software developed by Mark Brinicombe
     19        1.1    chris  *	for the NetBSD Project.
     20        1.1    chris  * 4. The name of the company nor the name of the author may be used to
     21        1.1    chris  *    endorse or promote products derived from this software without specific
     22        1.1    chris  *    prior written permission.
     23        1.1    chris  *
     24        1.1    chris  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25        1.1    chris  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26        1.1    chris  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27        1.1    chris  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     28        1.1    chris  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     29        1.1    chris  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     30        1.1    chris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31        1.1    chris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32        1.1    chris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33        1.1    chris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34        1.1    chris  * SUCH DAMAGE.
     35        1.1    chris  */
     36       1.17    chris 
     37       1.17    chris #include <sys/cdefs.h>
     38  1.20.12.1     tron __KERNEL_RCSID(0, "$NetBSD: footbridge_clock.c,v 1.20.12.1 2006/05/24 15:47:51 tron Exp $");
     39        1.1    chris 
     40        1.1    chris /* Include header files */
     41        1.1    chris 
     42        1.1    chris #include <sys/types.h>
     43        1.1    chris #include <sys/param.h>
     44        1.1    chris #include <sys/systm.h>
     45        1.1    chris #include <sys/kernel.h>
     46        1.1    chris #include <sys/time.h>
     47        1.1    chris #include <sys/device.h>
     48        1.1    chris 
     49        1.2     matt #include <machine/intr.h>
     50        1.3  thorpej 
     51        1.3  thorpej #include <arm/cpufunc.h>
     52        1.3  thorpej 
     53        1.1    chris #include <arm/footbridge/dc21285reg.h>
     54        1.1    chris #include <arm/footbridge/footbridgevar.h>
     55        1.6    chris #include <arm/footbridge/footbridge.h>
     56        1.1    chris 
     57        1.1    chris extern struct footbridge_softc *clock_sc;
     58        1.1    chris extern u_int dc21285_fclk;
     59        1.1    chris 
     60        1.4    chris int clockhandler __P((void *));
     61        1.4    chris int statclockhandler __P((void *));
     62        1.4    chris static int load_timer __P((int, int));
     63        1.4    chris 
     64       1.11    chris /*
     65       1.11    chris  * Statistics clock variance, in usec.  Variance must be a
     66       1.11    chris  * power of two.  Since this gives us an even number, not an odd number,
     67       1.11    chris  * we discard one case and compensate.  That is, a variance of 1024 would
     68       1.11    chris  * give us offsets in [0..1023].  Instead, we take offsets in [1..1023].
     69       1.11    chris  * This is symmetric about the point 512, or statvar/2, and thus averages
     70       1.11    chris  * to that value (assuming uniform random numbers).
     71       1.11    chris  */
     72       1.11    chris const int statvar = 1024;
     73       1.11    chris int statmin;			/* minimum stat clock count in ticks */
     74       1.11    chris int statcountperusec;		/* number of ticks per usec at current stathz */
     75       1.11    chris int statprev;			/* last value of we set statclock to */
     76        1.4    chris 
     77        1.1    chris #if 0
     78        1.1    chris static int clockmatch	__P((struct device *parent, struct cfdata *cf, void *aux));
     79        1.1    chris static void clockattach	__P((struct device *parent, struct device *self, void *aux));
     80        1.1    chris 
     81       1.10  thorpej CFATTACH_DECL(footbridge_clock, sizeof(struct clock_softc),
     82       1.10  thorpej     clockmatch, clockattach, NULL, NULL);
     83        1.1    chris 
     84        1.1    chris /*
     85        1.1    chris  * int clockmatch(struct device *parent, void *match, void *aux)
     86        1.1    chris  *
     87        1.1    chris  * Just return ok for this if it is device 0
     88        1.1    chris  */
     89        1.1    chris 
     90        1.1    chris static int
     91        1.1    chris clockmatch(parent, cf, aux)
     92        1.1    chris 	struct device *parent;
     93        1.1    chris 	struct cfdata *cf;
     94        1.1    chris 	void *aux;
     95        1.1    chris {
     96        1.1    chris 	union footbridge_attach_args *fba = aux;
     97        1.1    chris 
     98        1.1    chris 	if (strcmp(fba->fba_ca.ca_name, "clk") == 0)
     99        1.1    chris 		return(1);
    100        1.1    chris 	return(0);
    101        1.1    chris }
    102        1.1    chris 
    103        1.1    chris 
    104        1.1    chris /*
    105        1.1    chris  * void clockattach(struct device *parent, struct device *dev, void *aux)
    106        1.1    chris  *
    107        1.1    chris  */
    108        1.1    chris 
    109        1.1    chris static void
    110        1.1    chris clockattach(parent, self, aux)
    111        1.1    chris 	struct device *parent;
    112        1.1    chris 	struct device *self;
    113        1.1    chris 	void *aux;
    114        1.1    chris {
    115        1.1    chris 	struct clock_softc *sc = (struct clock_softc *)self;
    116        1.1    chris 	union footbridge_attach_args *fba = aux;
    117        1.1    chris 
    118        1.1    chris 	sc->sc_iot = fba->fba_ca.ca_iot;
    119        1.1    chris 	sc->sc_ioh = fba->fba_ca.ca_ioh;
    120        1.1    chris 
    121        1.1    chris 	clock_sc = sc;
    122        1.1    chris 
    123        1.1    chris 	/* Cannot do anything until cpu_initclocks() has been called */
    124        1.1    chris 
    125        1.1    chris 	printf("\n");
    126        1.1    chris }
    127        1.1    chris #endif
    128        1.1    chris 
    129        1.1    chris /*
    130        1.1    chris  * int clockhandler(struct clockframe *frame)
    131        1.1    chris  *
    132        1.1    chris  * Function called by timer 1 interrupts.
    133        1.1    chris  * This just clears the interrupt condition and calls hardclock().
    134        1.1    chris  */
    135        1.1    chris 
    136        1.1    chris int
    137        1.4    chris clockhandler(aframe)
    138        1.4    chris 	void *aframe;
    139        1.1    chris {
    140        1.4    chris 	struct clockframe *frame = aframe;
    141        1.1    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    142        1.1    chris 	    TIMER_1_CLEAR, 0);
    143        1.1    chris 	hardclock(frame);
    144        1.1    chris 	return(0);	/* Pass the interrupt on down the chain */
    145        1.1    chris }
    146        1.1    chris 
    147        1.1    chris /*
    148        1.1    chris  * int statclockhandler(struct clockframe *frame)
    149        1.1    chris  *
    150        1.1    chris  * Function called by timer 2 interrupts.
    151        1.1    chris  * This just clears the interrupt condition and calls statclock().
    152        1.1    chris  */
    153        1.1    chris 
    154        1.1    chris int
    155        1.4    chris statclockhandler(aframe)
    156        1.4    chris 	void *aframe;
    157        1.1    chris {
    158        1.4    chris 	struct clockframe *frame = aframe;
    159       1.11    chris 	int newint, r;
    160       1.11    chris 	int currentclock ;
    161       1.11    chris 
    162       1.11    chris 	/* start the clock off again */
    163       1.11    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    164       1.11    chris 			TIMER_2_CLEAR, 0);
    165       1.11    chris 
    166       1.11    chris 	do {
    167       1.11    chris 		r = random() & (statvar-1);
    168       1.11    chris 	} while (r == 0);
    169       1.11    chris 	newint = statmin + (r * statcountperusec);
    170       1.11    chris 
    171       1.11    chris 	/* fetch the current count */
    172       1.11    chris 	currentclock = bus_space_read_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    173       1.11    chris 		    TIMER_2_VALUE);
    174       1.11    chris 
    175       1.11    chris 	/*
    176       1.11    chris 	 * work out how much time has run, add another usec for time spent
    177       1.11    chris 	 * here
    178       1.11    chris 	 */
    179       1.11    chris 	r = ((statprev - currentclock) + statcountperusec);
    180       1.11    chris 
    181       1.11    chris 	if (r < newint) {
    182       1.11    chris 		newint -= r;
    183       1.11    chris 		r = 0;
    184       1.11    chris 	}
    185       1.11    chris 	else
    186       1.11    chris 		printf("statclockhandler: Statclock overrun\n");
    187       1.11    chris 
    188       1.11    chris 
    189       1.11    chris 	/*
    190       1.11    chris 	 * update the clock to the new counter, this reloads the existing
    191       1.11    chris 	 * timer
    192       1.11    chris 	 */
    193        1.1    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    194       1.11    chris 	    		TIMER_2_LOAD, newint);
    195       1.11    chris 	statprev = newint;
    196        1.1    chris 	statclock(frame);
    197       1.11    chris 	if (r)
    198       1.11    chris 		/*
    199       1.11    chris 		 * We've completely overrun the previous interval,
    200       1.11    chris 		 * make sure we report the correct number of ticks.
    201       1.11    chris 		 */
    202       1.11    chris 		statclock(frame);
    203       1.11    chris 
    204        1.1    chris 	return(0);	/* Pass the interrupt on down the chain */
    205        1.1    chris }
    206        1.1    chris 
    207        1.1    chris static int
    208       1.19       he load_timer(base, herz)
    209        1.1    chris 	int base;
    210       1.19       he 	int herz;
    211        1.1    chris {
    212        1.1    chris 	unsigned int timer_count;
    213        1.1    chris 	int control;
    214        1.1    chris 
    215       1.19       he 	timer_count = dc21285_fclk / herz;
    216       1.16  thorpej 	if (timer_count > TIMER_MAX_VAL * 16) {
    217        1.1    chris 		control = TIMER_FCLK_256;
    218        1.1    chris 		timer_count >>= 8;
    219       1.16  thorpej 	} else if (timer_count > TIMER_MAX_VAL) {
    220        1.1    chris 		control = TIMER_FCLK_16;
    221        1.1    chris 		timer_count >>= 4;
    222        1.1    chris 	} else
    223        1.1    chris 		control = TIMER_FCLK;
    224        1.1    chris 
    225        1.1    chris 	control |= (TIMER_ENABLE | TIMER_MODE_PERIODIC);
    226        1.1    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    227        1.1    chris 	    base + TIMER_LOAD, timer_count);
    228        1.1    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    229        1.1    chris 	    base + TIMER_CONTROL, control);
    230        1.1    chris 	bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    231        1.1    chris 	    base + TIMER_CLEAR, 0);
    232        1.1    chris 	return(timer_count);
    233        1.1    chris }
    234        1.1    chris 
    235        1.1    chris /*
    236       1.19       he  * void setstatclockrate(int herz)
    237        1.1    chris  *
    238        1.1    chris  * Set the stat clock rate. The stat clock uses timer2
    239        1.1    chris  */
    240        1.1    chris 
    241        1.1    chris void
    242       1.19       he setstatclockrate(herz)
    243       1.19       he 	int herz;
    244        1.1    chris {
    245       1.11    chris 	int statint;
    246       1.11    chris 	int countpersecond;
    247       1.11    chris 	int statvarticks;
    248       1.11    chris 
    249       1.19       he 	/* statint == num in counter to drop by desired herz */
    250       1.14  tsutsui 	statint = statprev = clock_sc->sc_statclock_count =
    251       1.19       he 	    load_timer(TIMER_2_BASE, herz);
    252       1.11    chris 
    253       1.11    chris 	/* Get the total ticks a second */
    254       1.19       he 	countpersecond = statint * herz;
    255       1.11    chris 
    256       1.11    chris 	/* now work out how many ticks per usec */
    257       1.11    chris 	statcountperusec = countpersecond / 1000000;
    258        1.1    chris 
    259       1.11    chris 	/* calculate a variance range of statvar */
    260       1.11    chris 	statvarticks = statcountperusec * statvar;
    261       1.11    chris 
    262       1.11    chris 	/* minimum is statint - 50% of variant */
    263       1.11    chris 	statmin = statint - (statvarticks / 2);
    264        1.1    chris }
    265        1.1    chris 
    266        1.1    chris /*
    267        1.1    chris  * void cpu_initclocks(void)
    268        1.1    chris  *
    269        1.1    chris  * Initialise the clocks.
    270        1.1    chris  *
    271        1.1    chris  * Timer 1 is used for the main system clock (hardclock)
    272        1.1    chris  * Timer 2 is used for the statistics clock (statclock)
    273        1.1    chris  */
    274        1.1    chris 
    275        1.1    chris void
    276        1.1    chris cpu_initclocks()
    277        1.1    chris {
    278        1.9    chris 	/* stathz and profhz should be set to something, we have the timer */
    279        1.9    chris 	if (stathz == 0)
    280       1.11    chris 		stathz = hz;
    281        1.9    chris 
    282        1.9    chris 	if (profhz == 0)
    283        1.9    chris 		profhz = stathz * 5;
    284        1.1    chris 
    285        1.1    chris 	/* Report the clock frequencies */
    286        1.1    chris 	printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
    287        1.1    chris 
    288        1.1    chris 	/* Setup timer 1 and claim interrupt */
    289        1.1    chris 	clock_sc->sc_clock_count = load_timer(TIMER_1_BASE, hz);
    290        1.1    chris 
    291        1.1    chris 	/*
    292        1.1    chris 	 * Use ticks per 256us for accuracy since ticks per us is often
    293        1.1    chris 	 * fractional e.g. @ 66MHz
    294        1.1    chris 	 */
    295        1.1    chris 	clock_sc->sc_clock_ticks_per_256us =
    296        1.1    chris 	    ((((clock_sc->sc_clock_count * hz) / 1000) * 256) / 1000);
    297       1.15    chris 	clock_sc->sc_clockintr = footbridge_intr_claim(IRQ_TIMER_1, IPL_CLOCK,
    298        1.1    chris 	    "tmr1 hard clk", clockhandler, 0);
    299        1.1    chris 
    300        1.1    chris 	if (clock_sc->sc_clockintr == NULL)
    301        1.7   provos 		panic("%s: Cannot install timer 1 interrupt handler",
    302        1.1    chris 		    clock_sc->sc_dev.dv_xname);
    303        1.1    chris 
    304        1.1    chris 	/* If stathz is non-zero then setup the stat clock */
    305        1.1    chris 	if (stathz) {
    306        1.1    chris 		/* Setup timer 2 and claim interrupt */
    307        1.1    chris 		setstatclockrate(stathz);
    308       1.15    chris        		clock_sc->sc_statclockintr = footbridge_intr_claim(IRQ_TIMER_2, IPL_STATCLOCK,
    309        1.1    chris        		    "tmr2 stat clk", statclockhandler, 0);
    310        1.1    chris 		if (clock_sc->sc_statclockintr == NULL)
    311        1.7   provos 			panic("%s: Cannot install timer 2 interrupt handler",
    312        1.1    chris 			    clock_sc->sc_dev.dv_xname);
    313        1.1    chris 	}
    314        1.1    chris }
    315        1.1    chris 
    316        1.1    chris 
    317        1.1    chris /*
    318        1.1    chris  * void microtime(struct timeval *tvp)
    319        1.1    chris  *
    320        1.1    chris  * Fill in the specified timeval struct with the current time
    321        1.1    chris  * accurate to the microsecond.
    322        1.1    chris  */
    323        1.1    chris 
    324        1.1    chris void
    325        1.1    chris microtime(tvp)
    326        1.1    chris 	struct timeval *tvp;
    327        1.1    chris {
    328        1.1    chris 	int s;
    329        1.1    chris 	int tm;
    330        1.1    chris 	int deltatm;
    331        1.1    chris 	static struct timeval oldtv;
    332        1.1    chris 
    333        1.1    chris 	if (clock_sc == NULL || clock_sc->sc_clock_count == 0)
    334        1.1    chris 		return;
    335        1.1    chris 
    336        1.1    chris 	s = splhigh();
    337        1.1    chris 
    338        1.1    chris 	tm = bus_space_read_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    339        1.1    chris 	    TIMER_1_VALUE);
    340        1.1    chris 
    341        1.1    chris 	deltatm = clock_sc->sc_clock_count - tm;
    342        1.1    chris 
    343        1.1    chris #ifdef DIAGNOSTIC
    344        1.1    chris 	if (deltatm < 0)
    345        1.7   provos 		panic("opps deltatm < 0 tm=%d deltatm=%d", tm, deltatm);
    346        1.1    chris #endif
    347        1.1    chris 
    348        1.1    chris 	/* Fill in the timeval struct */
    349        1.1    chris 	*tvp = time;
    350        1.1    chris 	tvp->tv_usec += ((deltatm << 8) / clock_sc->sc_clock_ticks_per_256us);
    351        1.1    chris 
    352        1.1    chris 	/* Make sure the micro seconds don't overflow. */
    353        1.1    chris 	while (tvp->tv_usec >= 1000000) {
    354        1.1    chris 		tvp->tv_usec -= 1000000;
    355        1.1    chris 		++tvp->tv_sec;
    356        1.1    chris 	}
    357        1.1    chris 
    358        1.1    chris 	/* Make sure the time has advanced. */
    359        1.1    chris 	if (tvp->tv_sec == oldtv.tv_sec &&
    360        1.1    chris 	    tvp->tv_usec <= oldtv.tv_usec) {
    361        1.1    chris 		tvp->tv_usec = oldtv.tv_usec + 1;
    362        1.1    chris 		if (tvp->tv_usec >= 1000000) {
    363        1.1    chris 			tvp->tv_usec -= 1000000;
    364        1.1    chris 			++tvp->tv_sec;
    365        1.1    chris 		}
    366        1.1    chris 	}
    367        1.1    chris 
    368        1.1    chris 	oldtv = *tvp;
    369        1.1    chris 	(void)splx(s);
    370        1.1    chris }
    371        1.1    chris 
    372        1.1    chris /*
    373        1.6    chris  * Use a timer to track microseconds, if the footbridge hasn't been setup we
    374        1.6    chris  * rely on an estimated loop, however footbridge is attached very early on.
    375        1.1    chris  */
    376        1.1    chris 
    377        1.6    chris static int delay_clock_count = 0;
    378        1.6    chris static int delay_count_per_usec = 0;
    379        1.1    chris 
    380        1.6    chris void
    381        1.6    chris calibrate_delay(void)
    382        1.6    chris {
    383        1.6    chris      delay_clock_count = load_timer(TIMER_3_BASE, 100);
    384        1.6    chris      delay_count_per_usec = delay_clock_count/10000;
    385       1.12    chris #ifdef VERBOSE_DELAY_CALIBRATION
    386       1.12    chris      printf("delay calibration: delay_cc = %d, delay_c/us=%d\n",
    387       1.12    chris 		     delay_clock_count, delay_count_per_usec);
    388       1.12    chris 
    389       1.12    chris      printf("0..");
    390       1.12    chris      delay(1000000);
    391       1.12    chris      printf("1..");
    392       1.12    chris      delay(1000000);
    393       1.12    chris      printf("2..");
    394       1.12    chris      delay(1000000);
    395       1.12    chris      printf("3..");
    396       1.12    chris      delay(1000000);
    397       1.12    chris      printf("4..");
    398       1.12    chris       delay(1000000);
    399       1.12    chris      printf("5..");
    400       1.12    chris       delay(1000000);
    401       1.12    chris      printf("6..");
    402       1.12    chris       delay(1000000);
    403       1.12    chris      printf("7..");
    404       1.12    chris       delay(1000000);
    405       1.12    chris      printf("8..");
    406       1.12    chris       delay(1000000);
    407       1.12    chris      printf("9..");
    408       1.12    chris       delay(1000000);
    409       1.12    chris      printf("10\n");
    410       1.12    chris #endif
    411        1.6    chris }
    412        1.1    chris 
    413       1.18     matt int delaycount = 25000;
    414        1.1    chris 
    415        1.1    chris void
    416        1.1    chris delay(n)
    417        1.1    chris 	u_int n;
    418        1.1    chris {
    419        1.6    chris 	volatile u_int i;
    420        1.6    chris 	uint32_t cur, last, delta, usecs;
    421        1.1    chris 
    422        1.1    chris 	if (n == 0) return;
    423        1.6    chris 
    424       1.18     matt 	/*
    425       1.18     matt 	 * not calibrated the timer yet, so try to live with this horrible
    426       1.18     matt 	 * loop!
    427       1.18     matt 	 */
    428        1.6    chris 	if (delay_clock_count == 0)
    429        1.6    chris 	{
    430        1.6    chris 	    while (n-- > 0) {
    431        1.6    chris 		for (i = delaycount; --i;);
    432        1.6    chris 	    }
    433        1.6    chris 	    return;
    434        1.6    chris 	}
    435       1.13    chris 
    436       1.13    chris 	/*
    437       1.13    chris 	 * read the current value (do not reset it as delay is reentrant)
    438       1.13    chris 	 */
    439       1.13    chris 	last = bus_space_read_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    440       1.13    chris 		    TIMER_3_VALUE);
    441       1.12    chris 
    442  1.20.12.1     tron 	delta = 0;
    443  1.20.12.1     tron 
    444  1.20.12.1     tron 	usecs = n * delay_count_per_usec;
    445        1.6    chris 
    446  1.20.12.1     tron 	while (usecs > delta)
    447        1.6    chris 	{
    448        1.6    chris 	    cur = bus_space_read_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    449        1.6    chris 		    TIMER_3_VALUE);
    450        1.6    chris 	    if (last < cur)
    451        1.6    chris 		/* timer has wrapped */
    452        1.6    chris 		delta += ((delay_clock_count - cur) + last);
    453        1.6    chris 	    else
    454        1.6    chris 		delta += (last - cur);
    455        1.6    chris 
    456       1.12    chris 	    if (cur == 0)
    457        1.6    chris 	    {
    458       1.13    chris 		/*
    459       1.13    chris 		 * reset the timer, note that if something blocks us for more
    460       1.13    chris 		 * than 1/100s we may delay for too long, but I believe that
    461       1.13    chris 		 * is fairly unlikely.
    462       1.13    chris 		 */
    463        1.6    chris 		bus_space_write_4(clock_sc->sc_iot, clock_sc->sc_ioh,
    464        1.6    chris 			TIMER_3_CLEAR, 0);
    465        1.6    chris 	    }
    466        1.6    chris 	    last = cur;
    467        1.1    chris 	}
    468        1.1    chris }
    469        1.1    chris 
    470        1.1    chris /* End of footbridge_clock.c */
    471