Home | History | Annotate | Line # | Download | only in gemini
gemini_timer.c revision 1.1.2.2
      1  1.1.2.2  skrll /*	$NetBSD: gemini_timer.c,v 1.1.2.2 2009/04/28 07:33:44 skrll Exp $	*/
      2      1.1   matt 
      3      1.1   matt /* adapted from:
      4      1.1   matt  *	NetBSD: omap2_geminitmr.c,v 1.1 2008/08/27 11:03:10 matt Exp
      5      1.1   matt  */
      6      1.1   matt 
      7      1.1   matt /*
      8      1.1   matt  * GEMINI Timers
      9      1.1   matt  */
     10      1.1   matt 
     11      1.1   matt /*
     12      1.1   matt  * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c
     13      1.1   matt  *
     14      1.1   matt  * Copyright (c) 1997 Mark Brinicombe.
     15      1.1   matt  * Copyright (c) 1997 Causality Limited.
     16      1.1   matt  * All rights reserved.
     17      1.1   matt  *
     18      1.1   matt  * This code is derived from software contributed to The NetBSD Foundation
     19      1.1   matt  * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
     20      1.1   matt  *
     21      1.1   matt  * Redistribution and use in source and binary forms, with or without
     22      1.1   matt  * modification, are permitted provided that the following conditions
     23      1.1   matt  * are met:
     24      1.1   matt  * 1. Redistributions of source code must retain the above copyright
     25      1.1   matt  *    notice, this list of conditions and the following disclaimer.
     26      1.1   matt  * 2. Redistributions in binary form must reproduce the above copyright
     27      1.1   matt  *    notice, this list of conditions and the following disclaimer in the
     28      1.1   matt  *    documentation and/or other materials provided with the distribution.
     29      1.1   matt  * 3. All advertising materials mentioning features or use of this software
     30      1.1   matt  *    must display the following acknowledgement:
     31      1.1   matt  *	This product includes software developed by the NetBSD
     32      1.1   matt  *	Foundation, Inc. and its contributors.
     33      1.1   matt  * 4. Neither the name of The NetBSD Foundation nor the names of its
     34      1.1   matt  *    contributors may be used to endorse or promote products derived
     35      1.1   matt  *    from this software without specific prior written permission.
     36      1.1   matt  *
     37      1.1   matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     38      1.1   matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     39      1.1   matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     40      1.1   matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     41      1.1   matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     42      1.1   matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     43      1.1   matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     44      1.1   matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     45      1.1   matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     46      1.1   matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     47      1.1   matt  * POSSIBILITY OF SUCH DAMAGE.
     48      1.1   matt  *
     49      1.1   matt  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
     50      1.1   matt  * All rights reserved.
     51      1.1   matt  *
     52      1.1   matt  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
     53      1.1   matt  *
     54      1.1   matt  * Redistribution and use in source and binary forms, with or without
     55      1.1   matt  * modification, are permitted provided that the following conditions
     56      1.1   matt  * are met:
     57      1.1   matt  * 1. Redistributions of source code must retain the above copyright
     58      1.1   matt  *    notice, this list of conditions and the following disclaimer.
     59      1.1   matt  * 2. Redistributions in binary form must reproduce the above copyright
     60      1.1   matt  *    notice, this list of conditions and the following disclaimer in the
     61      1.1   matt  *    documentation and/or other materials provided with the distribution.
     62      1.1   matt  * 3. All advertising materials mentioning features or use of this software
     63      1.1   matt  *    must display the following acknowledgement:
     64      1.1   matt  *	This product includes software developed for the NetBSD Project by
     65      1.1   matt  *	Wasabi Systems, Inc.
     66      1.1   matt  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     67      1.1   matt  *    or promote products derived from this software without specific prior
     68      1.1   matt  *    written permission.
     69      1.1   matt  *
     70      1.1   matt  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     71      1.1   matt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     72      1.1   matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     73      1.1   matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     74      1.1   matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     75      1.1   matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     76      1.1   matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     77      1.1   matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     78      1.1   matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     79      1.1   matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     80      1.1   matt  * POSSIBILITY OF SUCH DAMAGE.
     81      1.1   matt  */
     82      1.1   matt 
     83      1.1   matt #include <sys/cdefs.h>
     84  1.1.2.2  skrll __KERNEL_RCSID(0, "$NetBSD: gemini_timer.c,v 1.1.2.2 2009/04/28 07:33:44 skrll Exp $");
     85      1.1   matt 
     86      1.1   matt #include "opt_gemini.h"
     87      1.1   matt #include "opt_cpuoptions.h"
     88      1.1   matt 
     89      1.1   matt #include <sys/types.h>
     90      1.1   matt #include <sys/param.h>
     91      1.1   matt #include <sys/systm.h>
     92      1.1   matt #include <sys/kernel.h>
     93      1.1   matt #include <sys/time.h>
     94      1.1   matt #include <sys/timetc.h>
     95      1.1   matt #include <sys/device.h>
     96      1.1   matt 
     97      1.1   matt #include <dev/clock_subr.h>
     98      1.1   matt 
     99      1.1   matt #include <machine/bus.h>
    100      1.1   matt #include <machine/intr.h>
    101      1.1   matt 
    102      1.1   matt #include <arm/cpufunc.h>
    103      1.1   matt #include <arm/pic/picvar.h>
    104      1.1   matt 
    105      1.1   matt #include <arm/gemini/gemini_reg.h>
    106      1.1   matt #include <arm/gemini/gemini_timervar.h>
    107      1.1   matt #include <arm/gemini/gemini_timervar.h>
    108      1.1   matt 
    109      1.1   matt 
    110      1.1   matt static const uint32_t counts_per_usec = (GEMINI_TIMER_CLOCK_FREQ / 1000000);
    111      1.1   matt static uint32_t counts_per_hz = ~0;
    112      1.1   matt 
    113      1.1   matt struct geminitmr_softc *clock_sc;
    114      1.1   matt struct geminitmr_softc *stat_sc;
    115      1.1   matt struct geminitmr_softc *ref_sc;
    116      1.1   matt static uint32_t gemini_get_timecount(struct timecounter *);
    117      1.1   matt static void timer_init(geminitmr_softc_t *, int, boolean_t, boolean_t);
    118      1.1   matt static void timer_factors(geminitmr_softc_t *, int, boolean_t);
    119      1.1   matt 
    120      1.1   matt #ifdef GEMINI_TIMER_DEBUG
    121      1.1   matt static void tfprint(uint, timer_factors_t *);
    122      1.1   matt #endif
    123      1.1   matt 
    124      1.1   matt static struct timecounter gemini_timecounter = {
    125      1.1   matt 	.tc_get_timecount = gemini_get_timecount,
    126      1.1   matt 	.tc_counter_mask = 0xffffffff,
    127      1.1   matt 	.tc_frequency = GEMINI_TIMER_CLOCK_FREQ,
    128      1.1   matt 	.tc_name = "gpt",
    129      1.1   matt 	.tc_quality = 100,
    130      1.1   matt 	.tc_priv = NULL
    131      1.1   matt };
    132      1.1   matt 
    133      1.1   matt static inline void
    134      1.1   matt _timer_intr_dis(struct geminitmr_softc *sc)
    135      1.1   matt {
    136      1.1   matt 	uint32_t r;
    137      1.1   matt 
    138      1.1   matt 	r  = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK);
    139      1.1   matt 	r |= GEMINI_TIMERn_INTRMASK(sc->sc_timerno);
    140      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK, r);
    141      1.1   matt }
    142      1.1   matt 
    143      1.1   matt static inline void
    144      1.1   matt _timer_intr_enb(struct geminitmr_softc *sc)
    145      1.1   matt {
    146      1.1   matt 	uint32_t r;
    147      1.1   matt 
    148      1.1   matt 	r  = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK);
    149      1.1   matt 	r &= ~TIMER_INTRMASK_TMnMATCH1(sc->sc_timerno);
    150      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK, r);
    151      1.1   matt }
    152      1.1   matt 
    153      1.1   matt static inline void
    154      1.1   matt _timer_intr_clr(struct geminitmr_softc *sc)
    155      1.1   matt {
    156      1.1   matt 	uint32_t r;
    157      1.1   matt 	int psw;
    158      1.1   matt 
    159      1.1   matt 	psw = disable_interrupts(I32_bit);
    160      1.1   matt 	r  = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRSTATE);
    161      1.1   matt 	r &= ~GEMINI_TIMERn_INTRMASK(sc->sc_timerno);
    162      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRSTATE, r);
    163      1.1   matt 	restore_interrupts(psw);
    164      1.1   matt }
    165      1.1   matt 
    166      1.1   matt static inline uint32_t
    167      1.1   matt _timer_read(struct geminitmr_softc *sc)
    168      1.1   matt {
    169      1.1   matt 	uint32_t r;
    170      1.1   matt 
    171      1.1   matt 	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    172      1.1   matt 		GEMINI_TIMERn_COUNTER(sc->sc_timerno));
    173      1.1   matt 
    174      1.1   matt 	return r;
    175      1.1   matt }
    176      1.1   matt 
    177      1.1   matt static inline void
    178      1.1   matt _timer_stop(struct geminitmr_softc *sc)
    179      1.1   matt {
    180      1.1   matt 	uint32_t r;
    181      1.1   matt 
    182      1.1   matt 	r  = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR);
    183      1.1   matt 	r &= ~GEMINI_TIMER_TMnCR_MASK(sc->sc_timerno);
    184      1.1   matt }
    185      1.1   matt 
    186      1.1   matt /*
    187      1.1   matt  * note:
    188      1.1   matt  *  This function assumes the timer is enabled.
    189      1.1   matt  *  If the timer is disabled, GEMINI_TIMERn_COUNTER(n) will hold the value.
    190      1.1   matt  */
    191      1.1   matt static inline void
    192      1.1   matt _timer_reload(struct geminitmr_softc *sc, uint32_t val)
    193      1.1   matt {
    194      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    195      1.1   matt 		GEMINI_TIMERn_COUNTER(sc->sc_timerno), val);
    196      1.1   matt }
    197      1.1   matt 
    198      1.1   matt static inline void
    199      1.1   matt _timer_start(struct geminitmr_softc *sc)
    200      1.1   matt {
    201      1.1   matt 	uint32_t r;
    202      1.1   matt 	uint n = sc->sc_timerno;
    203      1.1   matt 	timer_factors_t *tfp = &sc->sc_tf;
    204      1.1   matt 
    205      1.1   matt 	/* set Counter, TmLoad, Match1, Match2 */
    206      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    207      1.1   matt 		GEMINI_TIMERn_COUNTER(n), tfp->tf_counter);
    208      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    209      1.1   matt 		GEMINI_TIMERn_LOAD(n), tfp->tf_reload);
    210      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    211      1.1   matt 		GEMINI_TIMERn_MATCH1(n), tfp->tf_match1);
    212      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    213      1.1   matt 		GEMINI_TIMERn_MATCH2(n), tfp->tf_match2);
    214      1.1   matt 
    215      1.1   matt 	/* set TmCR */
    216      1.1   matt 	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR);
    217      1.1   matt 	r &= ~GEMINI_TIMER_TMnCR_MASK(n);
    218      1.1   matt 	r |= tfp->tf_tmcr & GEMINI_TIMER_TMnCR_MASK(n);
    219      1.1   matt 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR, r);
    220      1.1   matt 
    221      1.1   matt }
    222      1.1   matt 
    223      1.1   matt static uint32_t
    224      1.1   matt gemini_get_timecount(struct timecounter *tc)
    225      1.1   matt {
    226      1.1   matt 	uint32_t r;
    227      1.1   matt 
    228      1.1   matt 	r = _timer_read(ref_sc);
    229      1.1   matt 
    230      1.1   matt 	return -r;
    231      1.1   matt }
    232      1.1   matt 
    233      1.1   matt int
    234      1.1   matt clockintr(void *frame)
    235      1.1   matt {
    236      1.1   matt 	struct geminitmr_softc *sc = clock_sc;;
    237      1.1   matt 
    238      1.1   matt 	_timer_intr_clr(sc);
    239      1.1   matt 	_timer_reload(sc, sc->sc_tf.tf_counter);
    240      1.1   matt 	hardclock(frame);
    241  1.1.2.1  skrll 	if (clock_sc == stat_sc)
    242  1.1.2.1  skrll 		statclock(frame);
    243      1.1   matt 	return 1;
    244      1.1   matt }
    245      1.1   matt 
    246      1.1   matt int
    247      1.1   matt statintr(void *frame)
    248      1.1   matt {
    249      1.1   matt 	struct geminitmr_softc *sc = stat_sc;;
    250      1.1   matt 
    251      1.1   matt 	_timer_intr_clr(sc);
    252      1.1   matt 	_timer_reload(sc, sc->sc_tf.tf_counter);
    253      1.1   matt 	statclock(frame);
    254      1.1   matt 	return 1;
    255      1.1   matt }
    256      1.1   matt 
    257      1.1   matt static void
    258      1.1   matt timer_init(geminitmr_softc_t *sc, int schz, boolean_t autoload, boolean_t intr)
    259      1.1   matt {
    260      1.1   matt 	int psw;
    261      1.1   matt 
    262      1.1   matt 	psw = disable_interrupts(I32_bit);
    263      1.1   matt 	timer_factors(sc, schz, autoload);
    264      1.1   matt 	_timer_stop(sc);
    265      1.1   matt 	_timer_intr_dis(sc);
    266      1.1   matt 	_timer_intr_clr(sc);
    267      1.1   matt 	if (intr)
    268      1.1   matt 		_timer_intr_enb(sc);
    269      1.1   matt 	_timer_start(sc);
    270      1.1   matt 	psw = disable_interrupts(I32_bit);
    271      1.1   matt }
    272      1.1   matt 
    273      1.1   matt void
    274  1.1.2.2  skrll gemini_microtime_init(void)
    275      1.1   matt {
    276      1.1   matt 	if (ref_sc == NULL)
    277      1.1   matt 		panic("microtime reference timer was not configured.");
    278      1.1   matt 	timer_init(ref_sc, 0, TRUE, FALSE);
    279      1.1   matt }
    280      1.1   matt 
    281      1.1   matt void
    282      1.1   matt setstatclockrate(int schz)
    283      1.1   matt {
    284      1.1   matt 	if (stat_sc == NULL)
    285      1.1   matt 		panic("Statistics timer was not configured.");
    286  1.1.2.1  skrll 	if (stat_sc != clock_sc)
    287  1.1.2.1  skrll 		timer_init(stat_sc, schz, FALSE, TRUE);
    288      1.1   matt }
    289      1.1   matt 
    290      1.1   matt /*
    291      1.1   matt  * clock_sc and stat_sc starts here
    292      1.1   matt  * ref_sc is initialized already by obiotimer_attach
    293      1.1   matt  */
    294      1.1   matt void
    295      1.1   matt cpu_initclocks(void)
    296      1.1   matt {
    297      1.1   matt 	if (clock_sc == NULL)
    298      1.1   matt 		panic("Clock timer was not configured.");
    299      1.1   matt 	if (stat_sc == NULL)
    300      1.1   matt 		panic("Statistics timer was not configured.");
    301      1.1   matt 	if (ref_sc == NULL)
    302      1.1   matt 		panic("Microtime reference timer was not configured.");
    303      1.1   matt 
    304      1.1   matt 	/*
    305      1.1   matt 	 * We already have the timers running, but not generating interrupts.
    306      1.1   matt 	 * In addition, we've set stathz and profhz.
    307      1.1   matt 	 */
    308      1.1   matt 	printf("clock: hz=%d stathz=%d\n", hz, stathz);
    309      1.1   matt 
    310      1.1   matt 	/*
    311      1.1   matt 	 * The "cookie" parameter must be zero to pass the interrupt frame
    312      1.1   matt 	 * through to hardclock() and statclock().
    313      1.1   matt 	 */
    314      1.1   matt 	intr_establish(clock_sc->sc_intr, IPL_CLOCK, IST_LEVEL_HIGH,
    315      1.1   matt 		clockintr, 0);
    316      1.1   matt 
    317  1.1.2.1  skrll 	if (clock_sc != stat_sc)
    318  1.1.2.1  skrll 		intr_establish(stat_sc->sc_intr, IPL_HIGH, IST_LEVEL_HIGH,
    319  1.1.2.1  skrll 			statintr, 0);
    320  1.1.2.1  skrll 
    321  1.1.2.1  skrll 	timer_init(clock_sc, hz, FALSE, TRUE);
    322  1.1.2.1  skrll 	if (clock_sc != stat_sc)
    323  1.1.2.1  skrll 		timer_init(stat_sc, stathz, FALSE, TRUE);
    324      1.1   matt 
    325      1.1   matt 	tc_init(&gemini_timecounter);
    326      1.1   matt }
    327      1.1   matt 
    328      1.1   matt void
    329      1.1   matt delay(u_int n)
    330      1.1   matt {
    331      1.1   matt 	struct geminitmr_softc *sc = ref_sc;
    332      1.1   matt 	uint32_t cur, last, delta, usecs;
    333      1.1   matt 
    334      1.1   matt 	if (sc == NULL)
    335      1.1   matt 		panic("The timer must be initialized sooner.");
    336      1.1   matt 
    337      1.1   matt 	/*
    338      1.1   matt 	 * This works by polling the timer and counting the
    339      1.1   matt 	 * number of microseconds that go by.
    340      1.1   matt 	 */
    341      1.1   matt 	last = _timer_read(sc);
    342      1.1   matt 
    343      1.1   matt 	delta = usecs = 0;
    344      1.1   matt 
    345      1.1   matt 	while (n > usecs) {
    346      1.1   matt 		cur = _timer_read(sc);
    347      1.1   matt 
    348      1.1   matt 		/* Check to see if the timer has wrapped around. */
    349      1.1   matt 		if (last < cur)
    350      1.1   matt 			delta += (last + (counts_per_hz - cur));
    351      1.1   matt 		else
    352      1.1   matt 			delta += (last - cur);
    353      1.1   matt 
    354      1.1   matt 		last = cur;
    355      1.1   matt 
    356      1.1   matt 		if (delta >= counts_per_usec) {
    357      1.1   matt 			usecs += delta / counts_per_usec;
    358      1.1   matt 			delta %= counts_per_usec;
    359      1.1   matt 		}
    360      1.1   matt 	}
    361      1.1   matt }
    362      1.1   matt 
    363      1.1   matt static void
    364      1.1   matt timer_factors(
    365      1.1   matt 	geminitmr_softc_t *sc,
    366      1.1   matt 	int ints_per_sec,
    367      1.1   matt 	boolean_t autoload)
    368      1.1   matt {
    369      1.1   matt 	timer_factors_t *tfp = &sc->sc_tf;
    370      1.1   matt 	uint n = sc->sc_timerno;
    371      1.1   matt 	const uint32_t us_per_sec = 1000000;
    372      1.1   matt 
    373      1.1   matt 	/*
    374      1.1   matt 	 * UPDOWN=0		(Down)
    375      1.1   matt 	 * OFENABLE=0		(no Irpt on overflow)
    376      1.1   matt 	 * CLOCK=0		(PCLK)
    377      1.1   matt 	 * ENABLE=1
    378      1.1   matt 	 */
    379      1.1   matt 	tfp->tf_tmcr = TIMER_TMCR_TMnENABLE(n);
    380      1.1   matt 
    381      1.1   matt 	if (ints_per_sec == 0) {
    382      1.1   matt 		tfp->tf_counter = ~0U;
    383      1.1   matt 	} else {
    384      1.1   matt 		uint32_t count_freq;
    385      1.1   matt 
    386      1.1   matt 		count_freq = GEMINI_TIMER_CLOCK_FREQ;
    387      1.1   matt 		count_freq /= ints_per_sec;
    388      1.1   matt 		tfp->tf_counter = count_freq;
    389      1.1   matt 	}
    390      1.1   matt 	tfp->tf_counts_per_usec = GEMINI_TIMER_CLOCK_FREQ / us_per_sec;
    391      1.1   matt 
    392      1.1   matt 	if (autoload)
    393      1.1   matt 		tfp->tf_reload = tfp->tf_counter;	/* auto-reload */
    394      1.1   matt 	else
    395      1.1   matt 		tfp->tf_reload = 0;			/* no-auto_reload */
    396      1.1   matt 
    397      1.1   matt 	tfp->tf_match1 = 0;
    398      1.1   matt 	tfp->tf_match2 = 0;
    399      1.1   matt 
    400      1.1   matt #ifdef GEMINI_TIMER_DEBUG
    401      1.1   matt 	tfprint(sc->sc_timerno, tfp);
    402      1.1   matt 	Debugger();
    403      1.1   matt #endif
    404      1.1   matt }
    405      1.1   matt 
    406      1.1   matt #ifdef GEMINI_TIMER_DEBUG
    407      1.1   matt void
    408      1.1   matt tfprint(uint n, timer_factors_t *tfp)
    409      1.1   matt {
    410      1.1   matt 	printf("%s: timer# %d\n", __FUNCTION__, n);
    411      1.1   matt 	printf("\ttf_counts_per_usec: %#x\n", tfp->tf_counts_per_usec);
    412      1.1   matt 	printf("\ttf_tmcr: %#x\n", tfp->tf_tmcr);
    413      1.1   matt 	printf("\ttf_counter: %#x\n", tfp->tf_counter);
    414      1.1   matt 	printf("\ttf_reload: %#x\n", tfp->tf_reload);
    415      1.1   matt 	printf("\ttf_match1: %#x\n", tfp->tf_match1);
    416      1.1   matt 	printf("\ttf_match2: %#x\n", tfp->tf_match2);
    417      1.1   matt }
    418      1.1   matt #endif
    419