diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-09 19:51:19 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-09 19:51:19 +0000 |
commit | ba73cc1b579e9c6eeaa67ca0b258f3a800af6cdc (patch) | |
tree | 0da5026fe259a155f724a30a51504dd50159feb1 | |
parent | 2f97351aff1f0b243038c0475dfebf4dc43dddac (diff) |
Switch mvme88k to timecounters.
-rw-r--r-- | sys/arch/mvme88k/dev/nvram.c | 59 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/_types.h | 5 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m188_machdep.c | 102 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m1x7_machdep.c | 69 |
4 files changed, 167 insertions, 68 deletions
diff --git a/sys/arch/mvme88k/dev/nvram.c b/sys/arch/mvme88k/dev/nvram.c index 2c81d1f8695..e8d239014c9 100644 --- a/sys/arch/mvme88k/dev/nvram.c +++ b/sys/arch/mvme88k/dev/nvram.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nvram.c,v 1.30 2007/12/20 05:19:38 miod Exp $ */ +/* $OpenBSD: nvram.c,v 1.31 2009/03/09 19:51:16 miod Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -33,6 +33,7 @@ #include <sys/proc.h> #include <sys/ioctl.h> #include <sys/uio.h> +#include <sys/timetc.h> #include <machine/autoconf.h> #include <machine/bugio.h> @@ -132,38 +133,6 @@ nvramattach(parent, self, args) } /* - * Return the best possible estimate of the time in the timeval - * to which tvp points. We do this by returning the current time - * plus the amount of time since the last clock interrupt (clock.c:clkread). - * - * Check that this time is no less than any previously-reported time, - * which could happen around the time of a clock adjustment. Just for fun, - * we guarantee that the time will be greater than the value obtained by a - * previous call. - */ -void -microtime(tvp) - struct timeval *tvp; -{ - int s = splhigh(); - static struct timeval lasttime; - - *tvp = time; - 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); -} - -/* * BCD to decimal and decimal to BCD. */ #define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf)) @@ -232,7 +201,7 @@ void timetochip(c) struct chiptime *c; { - int t, t2, t3, now = time.tv_sec; + time_t t, t2, t3, now = time_second; /* January 1 1970 was a Thursday (4 in unix wdays) */ /* compute the days since the epoch */ @@ -282,12 +251,14 @@ timetochip(c) */ void -inittodr(base) - time_t base; +inittodr(time_t base) { struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0]; int sec, min, hour, day, mon, year; int badbase = 0, waszero = base == 0; + struct timespec ts; + + ts.tv_sec = ts.tv_nsec = 0; if (base < 35 * SECYR) { /* @@ -297,7 +268,7 @@ inittodr(base) if (base != 0) printf("WARNING: preposterous time in file system\n"); /* not going to use it anyway, if the chip is readable */ - base = 36 * SECYR + 109 * SECDAY + 22 * 3600; + base = 39 * SECYR; badbase = 1; } @@ -345,7 +316,7 @@ inittodr(base) sc->sc_regs + CLK_CSR) & ~CLK_READ); } - if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) { + if ((ts.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) { printf("WARNING: bad date in nvram"); #ifdef DEBUG printf("\nday = %d, mon = %d, year = %d, hour = %d, min = %d, sec = %d", @@ -356,20 +327,22 @@ inittodr(base) * Believe the time in the file system for lack of * anything better, resetting the clock. */ - time.tv_sec = base; + ts.tv_sec = base; if (!badbase) resettodr(); } else { - int deltat = time.tv_sec - base; + int deltat = ts.tv_sec - base; if (deltat < 0) deltat = -deltat; if (waszero || deltat < 2 * SECDAY) - return; + goto done; printf("WARNING: clock %s %d days", - time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + ts.tv_sec < base ? "lost" : "gained", deltat / SECDAY); } printf(" -- CHECK AND RESET THE DATE!\n"); +done: + tc_setclock(&ts); } /* @@ -384,7 +357,7 @@ resettodr() struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0]; struct chiptime c; - if (!time.tv_sec || sc == NULL) + if (time_second == 0 || sc == NULL) return; timetochip(&c); diff --git a/sys/arch/mvme88k/include/_types.h b/sys/arch/mvme88k/include/_types.h index 0c299f944f2..d2e8f646f53 100644 --- a/sys/arch/mvme88k/include/_types.h +++ b/sys/arch/mvme88k/include/_types.h @@ -1,4 +1,7 @@ -/* $OpenBSD: _types.h,v 1.3 2007/05/15 01:56:47 deraadt Exp $ */ +/* $OpenBSD: _types.h,v 1.4 2009/03/09 19:51:18 miod Exp $ */ /* public domain */ #include <m88k/_types.h> + +/* Feature test macros */ +#define __HAVE_TIMECOUNTER diff --git a/sys/arch/mvme88k/mvme88k/m188_machdep.c b/sys/arch/mvme88k/mvme88k/m188_machdep.c index d2c9b3fbabc..097580a2086 100644 --- a/sys/arch/mvme88k/mvme88k/m188_machdep.c +++ b/sys/arch/mvme88k/mvme88k/m188_machdep.c @@ -1,4 +1,19 @@ -/* $OpenBSD: m188_machdep.c,v 1.51 2009/03/08 16:03:06 miod Exp $ */ +/* $OpenBSD: m188_machdep.c,v 1.52 2009/03/09 19:51:18 miod Exp $ */ +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -114,6 +129,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/errno.h> +#include <sys/timetc.h> #include <uvm/uvm_extern.h> @@ -698,24 +714,18 @@ void write_cio(int, u_int); int m188_clockintr(void *); int m188_calibrateintr(void *); int m188_statintr(void *); +u_int m188_cio_get_timecount(struct timecounter *); volatile int m188_calibrate_phase = 0; /* multiplication factor for delay() */ u_int m188_delay_const = 25; /* no MVME188 is faster than 25MHz */ -#if defined(MULTIPROCESSOR) && 0 -#include <machine/lock.h> -__cpu_simple_lock_t m188_cio_lock; +uint32_t cio_step; +uint32_t cio_refcnt; +uint32_t cio_lastcnt; -#define CIO_LOCK_INIT() __cpu_simple_lock_init(&m188_cio_lock) -#define CIO_LOCK() __cpu_simple_lock(&m188_cio_lock) -#define CIO_UNLOCK() __cpu_simple_unlock(&m188_cio_lock) -#else -#define CIO_LOCK_INIT() do { } while (0) -#define CIO_LOCK() do { } while (0) -#define CIO_UNLOCK() do { } while (0) -#endif +struct mutex cio_mutex = MUTEX_INITIALIZER(IPL_CLOCK); /* * Notes on the MVME188 clock usage: @@ -758,6 +768,16 @@ __cpu_simple_lock_t m188_cio_lock; #define DART_CTLR 0xfff8201f /* counter/timer LSB */ #define DART_OPCR 0xfff82037 /* output port config*/ +struct timecounter m188_cio_timecounter = { + m188_cio_get_timecount, + NULL, + 0xffffffff, + 0, + "cio", + 0, + NULL +}; + void m188_init_clocks(void) { @@ -769,8 +789,6 @@ m188_init_clocks(void) psr = get_psr(); set_psr(psr | PSR_IND); - CIO_LOCK_INIT(); - #ifdef DIAGNOSTIC if (1000000 % hz) { printf("cannot get %d Hz clock; using 100 Hz\n", hz); @@ -849,17 +867,16 @@ m188_init_clocks(void) sysconintr_establish(INTSRC_CIO, &clock_ih, "clock"); set_psr(psr); + + tc_init(&m188_cio_timecounter); } int m188_calibrateintr(void *eframe) { - CIO_LOCK(); + /* no need to grab the mutex, only one processor is running for now */ /* ack the interrupt */ write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_C_IP); - /* restart counter */ - write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_TCB | ZCIO_CTCS_S_IE); - CIO_UNLOCK(); m188_calibrate_phase++; @@ -869,12 +886,11 @@ m188_calibrateintr(void *eframe) int m188_clockintr(void *eframe) { - CIO_LOCK(); + mtx_enter(&cio_mutex); /* ack the interrupt */ write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_C_IP); - /* restart counter */ - write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_TCB | ZCIO_CTCS_S_IE); - CIO_UNLOCK(); + cio_refcnt += cio_step; + mtx_leave(&cio_mutex); hardclock(eframe); @@ -996,4 +1012,46 @@ m188_cio_init(u_int period) /* enable counter #1 */ write_cio(ZCIO_MCC, ZCIO_MCC_CT1E | ZCIO_MCC_PBE); write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_TCB | ZCIO_CTCS_S_IE); + + cio_step = period; + m188_cio_timecounter.tc_frequency = (u_int64_t)cio_step * hz; +} + +u_int +m188_cio_get_timecount(struct timecounter *tc) +{ + u_int cmsb, clsb, counter, curcnt; + + /* + * The CIO counter is free running, but by setting the + * RCC bit in its control register, we can read a frozen + * value of the counter. + * The counter will automatically unfreeze after reading + * its LSB. + */ + + mtx_enter(&cio_mutex); + write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_RCC); + cmsb = read_cio(ZCIO_CT1CCM); + clsb = read_cio(ZCIO_CT1CCL); + curcnt = cio_refcnt; + + counter = (cmsb << 8) | clsb; +#if 0 /* this will never happen unless the period itself is 65536 */ + if (counter == 0) + counter = 65536; +#endif + + /* + * The counter counts down from its initialization value to 1. + */ + counter = cio_step - counter; + + curcnt += counter; + if (curcnt < cio_lastcnt) + curcnt += cio_step; + + cio_lastcnt = curcnt; + mtx_leave(&cio_mutex); + return curcnt; } diff --git a/sys/arch/mvme88k/mvme88k/m1x7_machdep.c b/sys/arch/mvme88k/mvme88k/m1x7_machdep.c index cd230963fab..62d6822f7dc 100644 --- a/sys/arch/mvme88k/mvme88k/m1x7_machdep.c +++ b/sys/arch/mvme88k/mvme88k/m1x7_machdep.c @@ -1,4 +1,19 @@ -/* $OpenBSD: m1x7_machdep.c,v 1.8 2009/03/04 19:35:54 miod Exp $ */ +/* $OpenBSD: m1x7_machdep.c,v 1.9 2009/03/09 19:51:18 miod Exp $ */ +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /* * Copyright (c) 1999 Steve Murphree, Jr. * Copyright (c) 1995 Theo de Raadt @@ -74,6 +89,8 @@ #include <sys/systm.h> #include <sys/device.h> #include <sys/kernel.h> +#include <sys/mutex.h> +#include <sys/timetc.h> #include <machine/bus.h> @@ -85,6 +102,20 @@ int m1x7_clockintr(void *); int m1x7_statintr(void *); +u_int pcc_get_timecount(struct timecounter *); + +uint32_t pcc_refcnt; +struct mutex pcc_mutex = MUTEX_INITIALIZER(IPL_CLOCK); + +struct timecounter pcc_timecounter = { + pcc_get_timecount, + NULL, + 0xffffffff, + 1000000, /* 1MHz */ + "pcctwo", + 0, + NULL +}; #define PROF_RESET (IPL_CLOCK | PCC2_IRQ_IEN | PCC2_IRQ_ICLR) #define STAT_RESET (IPL_STATCLOCK | PCC2_IRQ_IEN | PCC2_IRQ_ICLR) @@ -148,6 +179,8 @@ m1x7_init_clocks(void) statclock_ih.ih_wantframe = 1; statclock_ih.ih_ipl = IPL_STATCLOCK; pcctwointr_establish(PCC2V_TIMER2, &statclock_ih, "stat"); + + tc_init(&pcc_timecounter); } /* @@ -158,12 +191,14 @@ m1x7_clockintr(void *eframe) { uint oflow; + mtx_enter(&pcc_mutex); oflow = (*(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T1CTL) & PCC2_TCTL_OVF) >> PCC2_TCTL_OVF_SHIFT; *(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T1CTL) = PCC2_TCTL_CEN | PCC2_TCTL_COC | PCC2_TCTL_COVF; - + pcc_refcnt += oflow * tick; *(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T1ICR) = PROF_RESET; + mtx_leave(&pcc_mutex); while (oflow-- != 0) { hardclock(eframe); @@ -180,6 +215,36 @@ m1x7_clockintr(void *eframe) return (1); } +u_int +pcc_get_timecount(struct timecounter *tc) +{ + uint32_t tcr1, tcr2; + uint8_t tctl; + uint cnt, oflow; + + mtx_enter(&pcc_mutex); + tcr1 = *(volatile u_int32_t *)(PCC2_BASE + PCCTWO_T1COUNT); + tctl = *(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T1CTL); + /* + * Since we can not freeze the counter while reading the count + * and overflow registers, read it a second time; if it has + * wrapped, pick the second reading. + */ + tcr2 = *(volatile u_int32_t *)(PCC2_BASE + PCCTWO_T1COUNT); + if (tcr2 < tcr1) { + tcr1 = tcr2; + tctl = *(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T1CTL); + } + cnt = pcc_refcnt; + mtx_leave(&pcc_mutex); + + oflow = (tctl & PCC2_TCTL_OVF) >> PCC2_TCTL_OVF_SHIFT; + if (oflow != 0) + return cnt + tcr1 + oflow * tick; + else + return cnt + tcr1; +} + int m1x7_statintr(void *eframe) { |