summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/mvme88k/dev/nvram.c59
-rw-r--r--sys/arch/mvme88k/include/_types.h5
-rw-r--r--sys/arch/mvme88k/mvme88k/m188_machdep.c102
-rw-r--r--sys/arch/mvme88k/mvme88k/m1x7_machdep.c69
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)
{