Home | History | Annotate | Line # | Download | only in isa
clock.c revision 1.13
      1 /*	$NetBSD: clock.c,v 1.13 2006/09/13 07:13:03 gdamore Exp $	*/
      2 
      3 /*
      4  * Copyright 1997
      5  * Digital Equipment Corporation. All rights reserved.
      6  *
      7  * This software is furnished under license and may be used and
      8  * copied only in accordance with the following terms and conditions.
      9  * Subject to these conditions, you may download, copy, install,
     10  * use, modify and distribute this software in source and/or binary
     11  * form. No title or ownership is transferred hereby.
     12  *
     13  * 1) Any source code used, modified or distributed must reproduce
     14  *    and retain this copyright notice and list of conditions as
     15  *    they appear in the source file.
     16  *
     17  * 2) No right is granted to use any trade name, trademark, or logo of
     18  *    Digital Equipment Corporation. Neither the "Digital Equipment
     19  *    Corporation" name nor any trademark or logo of Digital Equipment
     20  *    Corporation may be used to endorse or promote products derived
     21  *    from this software without the prior written permission of
     22  *    Digital Equipment Corporation.
     23  *
     24  * 3) This software is provided "AS-IS" and any express or implied
     25  *    warranties, including but not limited to, any implied warranties
     26  *    of merchantability, fitness for a particular purpose, or
     27  *    non-infringement are disclaimed. In no event shall DIGITAL be
     28  *    liable for any damages whatsoever, and in particular, DIGITAL
     29  *    shall not be liable for special, indirect, consequential, or
     30  *    incidental damages or damages for lost profits, loss of
     31  *    revenue or loss of use, whether such damages arise in contract,
     32  *    negligence, tort, under statute, in equity, at law or otherwise,
     33  *    even if advised of the possibility of such damage.
     34  */
     35 
     36 /*-
     37  * Copyright (c) 1990 The Regents of the University of California.
     38  * All rights reserved.
     39  *
     40  * This code is derived from software contributed to Berkeley by
     41  * William Jolitz and Don Ahn.
     42  *
     43  * Redistribution and use in source and binary forms, with or without
     44  * modification, are permitted provided that the following conditions
     45  * are met:
     46  * 1. Redistributions of source code must retain the above copyright
     47  *    notice, this list of conditions and the following disclaimer.
     48  * 2. Redistributions in binary form must reproduce the above copyright
     49  *    notice, this list of conditions and the following disclaimer in the
     50  *    documentation and/or other materials provided with the distribution.
     51  * 3. Neither the name of the University nor the names of its contributors
     52  *    may be used to endorse or promote products derived from this software
     53  *    without specific prior written permission.
     54  *
     55  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65  * SUCH DAMAGE.
     66  *
     67  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
     68  */
     69 /*-
     70  * Copyright (c) 1993, 1994 Charles M. Hannum.
     71  *
     72  * This code is derived from software contributed to Berkeley by
     73  * William Jolitz and Don Ahn.
     74  *
     75  * Redistribution and use in source and binary forms, with or without
     76  * modification, are permitted provided that the following conditions
     77  * are met:
     78  * 1. Redistributions of source code must retain the above copyright
     79  *    notice, this list of conditions and the following disclaimer.
     80  * 2. Redistributions in binary form must reproduce the above copyright
     81  *    notice, this list of conditions and the following disclaimer in the
     82  *    documentation and/or other materials provided with the distribution.
     83  * 3. All advertising materials mentioning features or use of this software
     84  *    must display the following acknowledgement:
     85  *	This product includes software developed by the University of
     86  *	California, Berkeley and its contributors.
     87  * 4. Neither the name of the University nor the names of its contributors
     88  *    may be used to endorse or promote products derived from this software
     89  *    without specific prior written permission.
     90  *
     91  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     92  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     94  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     95  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     96  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     97  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     98  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     99  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    100  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    101  * SUCH DAMAGE.
    102  *
    103  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
    104  */
    105 /*
    106  * Mach Operating System
    107  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
    108  * All Rights Reserved.
    109  *
    110  * Permission to use, copy, modify and distribute this software and its
    111  * documentation is hereby granted, provided that both the copyright
    112  * notice and this permission notice appear in all copies of the
    113  * software, derivative works or modified versions, and any portions
    114  * thereof, and that both notices appear in supporting documentation.
    115  *
    116  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
    117  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
    118  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
    119  *
    120  * Carnegie Mellon requests users of this software to return to
    121  *
    122  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
    123  *  School of Computer Science
    124  *  Carnegie Mellon University
    125  *  Pittsburgh PA 15213-3890
    126  *
    127  * any improvements or extensions that they make and grant Carnegie Mellon
    128  * the rights to redistribute these changes.
    129  */
    130 /*
    131   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
    132 
    133 		All Rights Reserved
    134 
    135 Permission to use, copy, modify, and distribute this software and
    136 its documentation for any purpose and without fee is hereby
    137 granted, provided that the above copyright notice appears in all
    138 copies and that both the copyright notice and this permission notice
    139 appear in supporting documentation, and that the name of Intel
    140 not be used in advertising or publicity pertaining to distribution
    141 of the software without specific, written prior permission.
    142 
    143 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
    144 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
    145 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
    146 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    147 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
    148 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
    149 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    150 */
    151 
    152 /*
    153  * Primitive clock interrupt routines.
    154  */
    155 
    156 #include <sys/cdefs.h>
    157 __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.13 2006/09/13 07:13:03 gdamore Exp $");
    158 
    159 #include <sys/param.h>
    160 #include <sys/systm.h>
    161 #include <sys/time.h>
    162 #include <sys/timetc.h>
    163 #include <sys/kernel.h>
    164 #include <sys/device.h>
    165 
    166 #include <machine/cpu.h>
    167 #include <machine/intr.h>
    168 #include <machine/pio.h>
    169 #include <arm/cpufunc.h>
    170 
    171 #include <dev/isa/isareg.h>
    172 #include <dev/isa/isavar.h>
    173 #include <dev/ic/mc146818reg.h>
    174 #include <dev/ic/i8253reg.h>
    175 #include <shark/isa/nvram.h>
    176 #include <shark/isa/spkrreg.h>
    177 #include <shark/shark/hat.h>
    178 
    179 void	sysbeepstop(void *);
    180 void	sysbeep(int, int);
    181 void	rtcinit(void);
    182 int     timer_hz_to_count(int);
    183 
    184 static void findcpuspeed(void);
    185 static void delayloop(int);
    186 static int  clockintr(void *);
    187 static int  gettick(void);
    188 static void tc_init_i8253(void);
    189 
    190 void startrtclock(void);
    191 
    192 inline unsigned mc146818_read(void *, unsigned);
    193 inline void mc146818_write(void *, unsigned, unsigned);
    194 
    195 inline unsigned
    196 mc146818_read(void *sc, unsigned reg)
    197 {
    198 
    199 	outb(IO_RTC, reg);
    200 	return (inb(IO_RTC+1));
    201 }
    202 
    203 inline void
    204 mc146818_write(void *sc, unsigned reg, unsigned datum)
    205 {
    206 
    207 	outb(IO_RTC, reg);
    208 	outb(IO_RTC+1, datum);
    209 }
    210 
    211 unsigned int count1024usec; /* calibrated loop variable (1024 microseconds) */
    212 
    213 /* number of timer ticks in a Musec = 2^20 usecs */
    214 #define TIMER_MUSECFREQ\
    215     (((((((TIMER_FREQ) * 1024) + 999) / 1000) * 1024) + 999) / 1000)
    216 #define TIMER_MUSECDIV(x) ((TIMER_MUSECFREQ+(x)/2)/(x))
    217 
    218 /*
    219  * microtime() makes use of the following globals.
    220  * timer_msb_table[] and timer_lsb_table[] are used to compute the
    221  * microsecond increment.
    222  *
    223  * time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb];
    224  */
    225 
    226 u_short	isa_timer_lsb_table[256];	/* timer->usec conversion for LSB */
    227 
    228 /* 64 bit counts from timer 0 */
    229 struct count64 {
    230 	unsigned lo;   /* low 32 bits */
    231 	unsigned hi;   /* high 32 bits */
    232 };
    233 
    234 #define TIMER0_ROLLOVER  0xFFFF  /* maximum rollover for 8254 counter */
    235 
    236 struct count64 timer0count;
    237 struct count64 timer0_at_last_clockintr;
    238 unsigned       timer0last;
    239 
    240 /*#define TESTHAT*/
    241 #ifdef TESTHAT
    242 #define HATSTACKSIZE 1024
    243 #define HATHZ  50000
    244 #define HATHZ2 10000
    245 unsigned char hatStack[HATSTACKSIZE];
    246 
    247 unsigned testHatOn = 0;
    248 unsigned nHats = 0;
    249 unsigned nHatWedges = 0;
    250 unsigned fiqReason = 0;
    251 unsigned hatCount = 0;
    252 unsigned hatCount2 = 0;
    253 
    254 void hatTest(int testReason)
    255 {
    256 
    257 	fiqReason |= testReason;
    258 	nHats++;
    259 }
    260 
    261 void hatWedge(int nFIQs)
    262 {
    263 
    264 	printf("Unwedging the HAT.  fiqs_happened = %d\n", nFIQs);
    265 	nHatWedges++;
    266 }
    267 #endif
    268 
    269 void
    270 startrtclock(void)
    271 {
    272 
    273 	findcpuspeed();		/* use the clock (while it's free) to
    274 				   find the CPU speed */
    275 
    276 	timer0count.lo = 0;
    277 	timer0count.hi = 0;
    278 	timer0_at_last_clockintr.lo = 0;
    279 	timer0_at_last_clockintr.hi = 0;
    280 	timer0last     = 0;
    281 
    282 	/* initialize 8253 clock */
    283 	outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
    284 	outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER % 256);
    285 	outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER / 256);
    286 
    287 #ifdef TESTHAT
    288 	hatCount = timer_hz_to_count(HATHZ);
    289 	hatCount2 = timer_hz_to_count(HATHZ2);
    290 	printf("HAT test on @ %d Hz = %d ticks\n", HATHZ, hatCount);
    291 #endif
    292 }
    293 
    294 int
    295 timer_hz_to_count(int timer_hz)
    296 {
    297 	u_long tval;
    298 
    299 	tval = (TIMER_FREQ * 2) / (u_long) timer_hz;
    300 	tval = (tval / 2) + (tval & 0x1);
    301 
    302 	return (int)tval;
    303 }
    304 
    305 void gettimer0count(struct count64 *);
    306 
    307 /* must be called at SPL_CLOCK or higher */
    308 void gettimer0count(struct count64 *pcount)
    309 {
    310 	unsigned current, ticks, oldlo;
    311 
    312 	/*
    313 	 * Latch the current value of the timer and then read it.
    314 	 * This guarantees an atomic reading of the time.
    315 	 */
    316 
    317 	current = gettick();
    318 
    319 	if (timer0last >= current)
    320 		ticks = timer0last - current;
    321 	else
    322 		ticks = timer0last + (TIMER0_ROLLOVER - current);
    323 
    324 	timer0last = current;
    325 
    326 	oldlo = timer0count.lo;
    327 
    328 	if (oldlo > (timer0count.lo = oldlo + ticks)) /* carry? */
    329 		timer0count.hi++;
    330 
    331 	*pcount = timer0count;
    332 }
    333 
    334 static int
    335 clockintr(void *arg)
    336 {
    337 	struct clockframe *frame = arg;		/* not strictly necessary */
    338 	extern void isa_specific_eoi(int irq);
    339 #ifdef TESTHAT
    340 	static int ticks = 0;
    341 #endif
    342 	static int hatUnwedgeCtr = 0;
    343 
    344 	gettimer0count(&timer0_at_last_clockintr);
    345 
    346 	mc146818_read(NULL, MC_REGC); /* clear the clock interrupt */
    347 
    348 	/* check to see if the high-availability timer needs to be unwedged */
    349 	if (++hatUnwedgeCtr >= (hz / HAT_MIN_FREQ)) {
    350 		hatUnwedgeCtr = 0;
    351 		hatUnwedge();
    352 	}
    353 
    354 #ifdef TESTHAT
    355 	++ticks;
    356 
    357 	if (testHatOn && ((ticks & 0x3f) == 0)) {
    358 		if (testHatOn == 1) {
    359 			hatClkAdjust(hatCount2);
    360 			testHatOn = 2;
    361 		} else {
    362 			testHatOn = 0;
    363 			hatClkOff();
    364 			printf("hat off status: %d %d %x\n", nHats,
    365 			    nHatWedges, fiqReason);
    366 		}
    367 	} else if (!testHatOn && (ticks & 0x1ff) == 0) {
    368 		printf("hat on status: %d %d %x\n",
    369 		    nHats, nHatWedges, fiqReason);
    370 		testHatOn = 1;
    371 		nHats = 0;
    372 		fiqReason = 0;
    373 		hatClkOn(hatCount, hatTest, 0xfeedface,
    374 		    hatStack + HATSTACKSIZE - sizeof(unsigned),
    375 		    hatWedge);
    376 	}
    377 #endif
    378 	hardclock(frame);
    379 	return(0);
    380 }
    381 
    382 static int
    383 gettick(void)
    384 {
    385 	u_char lo, hi;
    386 	u_int savedints;
    387 
    388 	/* Don't want someone screwing with the counter while we're here. */
    389 	savedints = disable_interrupts(I32_bit);
    390 	/* Select counter 0 and latch it. */
    391 	outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
    392 	lo = inb(IO_TIMER1 + TIMER_CNTR0);
    393 	hi = inb(IO_TIMER1 + TIMER_CNTR0);
    394 	restore_interrupts(savedints);
    395 	return ((hi << 8) | lo);
    396 }
    397 
    398 /* modifications from i386 to shark isa version:
    399    - removed hardcoded "n -=" values that approximated the time to
    400      calculate delay ticks
    401    - made the time to calculate delay ticks almost negligable. 4 multiplies
    402      = maximum of 12 cycles = 75ns on a slow SA-110, plus a bunch of shifts;
    403      as opposed to 4 multiplies plus a bunch of divides.
    404    - removed i386 assembly language hack
    405    - put code in findcpuspeed that works even if FIRST_GUESS is orders
    406      of magnitude low
    407    - put code in delay() to use delayloop() for short delays
    408    - microtime no longer in assembly language
    409 */
    410 
    411 /*
    412  * Wait "n" microseconds.
    413  * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz.
    414  * Note: timer had better have been programmed before this is first used!
    415  * (Note that we use `rate generator' mode, which counts at 1:1; `square
    416  * wave' mode counts at 2:1).
    417  */
    418 void
    419 delay(unsigned n)
    420 {
    421 	int ticks, otick;
    422 	int nticks;
    423 
    424 	if (n < 100) {
    425 		/* it can take a long time (1 usec or longer) just for
    426 		   1 ISA read, so it's best not to use the timer for
    427 		   short delays */
    428 		delayloop((n * count1024usec) >> 10);
    429 		return;
    430 	}
    431 
    432 	/*
    433 	 * Read the counter first, so that the rest of the setup overhead is
    434 	 * counted.
    435 	 */
    436 	otick = gettick();
    437 
    438 	/*
    439 	 * Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and
    440 	 * without any avoidable overflows.
    441 	 */
    442 	{
    443 	        /* a Musec = 2^20 usec */
    444 		int Musec = n >> 20,
    445 		    usec = n & ((1 << 20) - 1);
    446 		nticks
    447 		  = (Musec * TIMER_MUSECFREQ) +
    448 		    (usec * (TIMER_MUSECFREQ >> 20)) +
    449 		    ((usec * ((TIMER_MUSECFREQ & ((1 <<20) - 1)) >>10)) >>10) +
    450 		    ((usec * (TIMER_MUSECFREQ & ((1 << 10) - 1))) >> 20);
    451 	}
    452 
    453 	while (nticks > 0) {
    454 		ticks = gettick();
    455 		if (ticks > otick)
    456 			nticks -= TIMER0_ROLLOVER - (ticks - otick);
    457 		else
    458 			nticks -= otick - ticks;
    459 		otick = ticks;
    460 	}
    461 
    462 }
    463 
    464 void
    465 sysbeepstop(void *arg)
    466 {
    467 }
    468 
    469 void
    470 sysbeep(int pitch, int period)
    471 {
    472 }
    473 
    474 #define FIRST_GUESS   0x2000
    475 
    476 static void
    477 findcpuspeed(void)
    478 {
    479 	int ticks;
    480 	unsigned int guess = FIRST_GUESS;
    481 
    482 	while (1) { /* loop until accurate enough */
    483 		/* Put counter in count down mode */
    484 		outb(IO_TIMER1 + TIMER_MODE,
    485 		    TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
    486 		outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
    487 		outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
    488 		delayloop(guess);
    489 
    490 		/* Read the value left in the counter */
    491 		/*
    492 		 * Formula for delaycount is:
    493 		 *  (loopcount * timer clock speed) / (counter ticks * 1000)
    494 		 */
    495 		ticks = 0xFFFF - gettick();
    496 		if (ticks == 0) ticks = 1; /* just in case */
    497 		if (ticks < (TIMER_MUSECDIV(1024))) { /* not accurate enough */
    498 			guess *= max(2, (TIMER_MUSECDIV(1024) / ticks));
    499 			continue;
    500 		}
    501 		count1024usec = (guess * (TIMER_MUSECDIV(1024))) / ticks;
    502 		return;
    503 	}
    504 }
    505 
    506 static void
    507 delayloop(int counts)
    508 {
    509 	while (counts--)
    510 		__insn_barrier();
    511 }
    512 
    513 void
    514 cpu_initclocks(void)
    515 {
    516         unsigned hzval;
    517 
    518 	printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
    519 
    520 	/* install RTC interrupt handler */
    521 	(void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK,
    522 				 clockintr, 0);
    523 
    524 	/* set  up periodic interrupt @ hz
    525 	   this is the subset of hz values in kern_clock.c that are
    526 	   supported by the ISA RTC */
    527 	switch (hz) {
    528 	case 64:
    529 		hzval = MC_RATE_64_Hz;
    530 		break;
    531 	case 128:
    532 		hzval = MC_RATE_128_Hz;
    533 		break;
    534 	case 256:
    535 		hzval = MC_RATE_256_Hz;
    536 		break;
    537 	case 1024:
    538 		hzval = MC_RATE_1024_Hz;
    539 		break;
    540 	default:
    541 		panic("cannot configure hz = %d", hz);
    542         }
    543 
    544 	rtcinit(); /* make sure basics are done by now */
    545 
    546 	/* blast values to set up clock interrupt */
    547 	mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | hzval);
    548 	/* enable periodic interrupt */
    549 	mc146818_write(NULL, MC_REGB,
    550 		       mc146818_read(NULL, MC_REGB) | MC_REGB_PIE);
    551 
    552 	tc_init_i8253();
    553 }
    554 
    555 void
    556 rtcinit(void)
    557 {
    558 	static int first_rtcopen_ever = 1;
    559 
    560 	if (!first_rtcopen_ever)
    561 		return;
    562 	first_rtcopen_ever = 0;
    563 
    564 	mc146818_write(NULL, MC_REGA,			/* XXX softc */
    565 	    MC_BASE_32_KHz | MC_RATE_1024_Hz);
    566 	mc146818_write(NULL, MC_REGB, MC_REGB_24HR);	/* XXX softc */
    567 }
    568 
    569 void
    570 setstatclockrate(int arg)
    571 {
    572 }
    573 
    574 static uint32_t
    575 i8253_get_timecount(struct timecounter *tc)
    576 {
    577 	return (TIMER0_ROLLOVER - gettick());
    578 }
    579 
    580 void
    581 tc_init_i8253(void)
    582 {
    583 	static struct timecounter i8253_tc = {
    584 		.tc_get_timecount = i8253_get_timecount,
    585 		.tc_counter_mask = TIMER0_ROLLOVER,
    586 		.tc_frequency = TIMER_FREQ,
    587 		.tc_name = "i8253",
    588 		.tc_quality = 100
    589 	};
    590 
    591 	tc_init(&i8253_tc);
    592 }
    593 
    594 /* End of clock.c */
    595