summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sh/include/_types.h5
-rw-r--r--sys/arch/sh/sh/clock.c99
-rw-r--r--sys/arch/sh/sh/interrupt.c35
3 files changed, 60 insertions, 79 deletions
diff --git a/sys/arch/sh/include/_types.h b/sys/arch/sh/include/_types.h
index b00da79615a..ce577a7e8f2 100644
--- a/sys/arch/sh/include/_types.h
+++ b/sys/arch/sh/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.10 2011/11/15 17:12:14 deraadt Exp $ */
+/* $OpenBSD: _types.h,v 1.11 2012/09/08 22:01:25 miod Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -143,4 +143,7 @@ typedef int __rune_t;
typedef void * __wctrans_t;
typedef void * __wctype_t;
+/* Feature test macros */
+#define __HAVE_TIMECOUNTER
+
#endif /* _SH__TYPES_H_ */
diff --git a/sys/arch/sh/sh/clock.c b/sys/arch/sh/sh/clock.c
index b14f52144c0..66cb3853d0b 100644
--- a/sys/arch/sh/sh/clock.c
+++ b/sys/arch/sh/sh/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.6 2008/06/26 05:42:13 ray Exp $ */
+/* $OpenBSD: clock.c,v 1.7 2012/09/08 22:01:25 miod Exp $ */
/* $NetBSD: clock.c,v 1.32 2006/09/05 11:09:36 uwe Exp $ */
/*-
@@ -34,6 +34,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
+#include <sys/timetc.h>
#include <dev/clock_subr.h>
@@ -56,7 +57,8 @@
* OpenBSD/sh clock module
* + default 64Hz
* + use TMU channel 0 as clock interrupt source.
- * + use TMU channel 1 and 2 as emulated software interrupt source.
+ * + use TMU channel 1 as emulated software interrupt source.
+ * + use TMU channel 2 as freeruuning counter for timecounter.
* + If RTC module is active, TMU channel 0 input source is RTC output.
* (1.6384kHz)
*/
@@ -73,6 +75,8 @@ struct {
uint32_t pclock; /* PCLOCK */
uint32_t cpuclock; /* CPU clock */
int flags;
+
+ struct timecounter tc;
} sh_clock = {
#ifdef PCLOCK
.pclock = PCLOCK,
@@ -91,6 +95,7 @@ uint32_t maxwdog;
/* interrupt handler is timing critical. prepared for each. */
int sh3_clock_intr(void *);
int sh4_clock_intr(void *);
+u_int sh_timecounter_get(struct timecounter *);
/*
* Estimate CPU and Peripheral clock.
@@ -101,13 +106,14 @@ do { \
_reg_write_4(SH_(TCNT ## x), 0xffffffff); \
_reg_bset_1(SH_(TSTR), TSTR_STR##x); \
} while (/*CONSTCOND*/0)
+
#define TMU_ELAPSED(x) \
(0xffffffff - _reg_read_4(SH_(TCNT ## x)))
void
sh_clock_init(int flags, struct rtc_ops *rtc)
{
- uint32_t s, t0, t1 __attribute__((__unused__));
+ uint32_t s, t0, cnt_1s;
sh_clock.flags = flags;
if (rtc != NULL)
@@ -136,6 +142,9 @@ sh_clock_init(int flags, struct rtc_ops *rtc)
_reg_write_2(SH_(TCR0),
CPU_IS_SH3 ? SH3_TCR_TPSC_RTC : SH4_TCR_TPSC_RTC);
sh_clock.tmuclk = SH_RTC_CLOCK;
+
+ /* Make sure RTC oscillator is enabled */
+ _reg_bset_1(SH_(RCR2), SH_RCR2_ENABLE);
}
s = _cpu_exception_suspend();
@@ -145,31 +154,36 @@ sh_clock_init(int flags, struct rtc_ops *rtc)
t0 = TMU_ELAPSED(0);
_cpu_exception_resume(s);
- sh_clock.cpuclock = ((10000000 * 10) / t0) * sh_clock.tmuclk;
sh_clock.cpucycle_1us = (sh_clock.tmuclk * 10) / t0;
+ cnt_1s = ((uint64_t)sh_clock.tmuclk * 10000000 * 10 + t0 / 2) / t0;
if (CPU_IS_SH4)
- sh_clock.cpuclock >>= 1; /* two-issue */
+ sh_clock.cpuclock = cnt_1s / 2; /* two-issue */
+ else
+ sh_clock.cpuclock = cnt_1s;
/*
* Estimate PCLOCK
*/
if (sh_clock.pclock == 0) {
+ uint32_t t1;
+
/* set TMU channel 1 source to PCLOCK / 4 */
_reg_write_2(SH_(TCR1), TCR_TPSC_P4);
s = _cpu_exception_suspend();
_cpu_spin(1); /* load function on cache. */
TMU_START(0);
TMU_START(1);
- _cpu_spin(sh_clock.cpucycle_1us * 1000000); /* 1 sec. */
+ _cpu_spin(cnt_1s); /* 1 sec. */
t0 = TMU_ELAPSED(0);
t1 = TMU_ELAPSED(1);
_cpu_exception_resume(s);
- sh_clock.pclock = ((t1 * 4)/ t0) * SH_RTC_CLOCK;
+ sh_clock.pclock =
+ ((uint64_t)t1 * 4 * SH_RTC_CLOCK + t0 / 2) / t0;
}
- /* Stop all counter */
+ /* Stop all counters */
_reg_write_1(SH_(TSTR), 0);
#undef TMU_START
@@ -194,35 +208,10 @@ setstatclockrate(int newhz)
/* XXX not yet */
}
-/*
- * Return the best possible estimate of the time in the timeval to
- * which tv points.
- */
-void
-microtime(struct timeval *tv)
+u_int
+sh_timecounter_get(struct timecounter *tc)
{
- static struct timeval lasttime;
- u_int32_t tcnt0;
- int s;
-
- s = splclock();
- *tv = time;
- tcnt0 = _reg_read_4(SH_(TCNT0));
- splx(s);
-
- tv->tv_usec += ((sh_clock.hz_cnt - tcnt0) * 1000000) / sh_clock.tmuclk;
- while (tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
-
- if (tv->tv_sec == lasttime.tv_sec &&
- tv->tv_usec <= lasttime.tv_usec &&
- (tv->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
- lasttime = *tv;
+ return 0xffffffff - _reg_read_4(SH_(TCNT2));
}
/*
@@ -271,13 +260,29 @@ cpu_initclocks()
_reg_bset_1(SH_(TSTR), TSTR_STR0);
/*
- * TMU channel 1, 2 are one shot timer.
+ * TMU channel 1 is one shot timer for soft interrupts.
*/
_reg_write_2(SH_(TCR1), TCR_UNIE | TCR_TPSC_P4);
_reg_write_4(SH_(TCOR1), 0xffffffff);
- _reg_write_2(SH_(TCR2), TCR_UNIE | TCR_TPSC_P4);
+
+ /*
+ * TMU channel 2 is freerunning counter for timecounter.
+ */
+ _reg_write_2(SH_(TCR2), TCR_TPSC_P4);
_reg_write_4(SH_(TCOR2), 0xffffffff);
+ /*
+ * Start and initialize timecounter.
+ */
+ _reg_bset_1(SH_(TSTR), TSTR_STR2);
+
+ sh_clock.tc.tc_get_timecount = sh_timecounter_get;
+ sh_clock.tc.tc_frequency = sh_clock.pclock / 4;
+ sh_clock.tc.tc_name = "tmu_pclock_4";
+ sh_clock.tc.tc_quality = 100;
+ sh_clock.tc.tc_counter_mask = 0xffffffff;
+ tc_init(&sh_clock.tc);
+
/* Make sure to start RTC */
if (sh_clock.rtc.init != NULL)
sh_clock.rtc.init(sh_clock.rtc._cookie);
@@ -287,8 +292,8 @@ void
inittodr(time_t base)
{
struct clock_ymdhms dt;
+ struct timespec ts;
time_t rtc;
- int s;
if (!sh_clock.rtc_initialized)
sh_clock.rtc_initialized = 1;
@@ -313,20 +318,18 @@ inittodr(time_t base)
* Believe the time in the file system for lack of
* anything better, resetting the RTC.
*/
- s = splclock();
- time.tv_sec = base;
- time.tv_usec = 0;
- splx(s);
+ ts.tv_sec = base;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
printf("WARNING: preposterous clock chip time\n");
resettodr();
printf(" -- CHECK AND RESET THE DATE!\n");
return;
}
- s = splclock();
- time.tv_sec = rtc;
- time.tv_usec = 0;
- splx(s);
+ ts.tv_sec = rtc;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
return;
}
@@ -341,7 +344,7 @@ resettodr()
return;
s = splclock();
- clock_secs_to_ymdhms(time.tv_sec, &dt);
+ clock_secs_to_ymdhms(time_second, &dt);
splx(s);
sh_clock.rtc.set(sh_clock.rtc._cookie, &dt);
diff --git a/sys/arch/sh/sh/interrupt.c b/sys/arch/sh/sh/interrupt.c
index 131b26c3292..d2d6f7b247d 100644
--- a/sys/arch/sh/sh/interrupt.c
+++ b/sys/arch/sh/sh/interrupt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interrupt.c,v 1.12 2010/12/21 14:56:24 claudio Exp $ */
+/* $OpenBSD: interrupt.c,v 1.13 2012/09/08 22:01:25 miod Exp $ */
/* $NetBSD: interrupt.c,v 1.18 2006/01/25 00:02:57 uwe Exp $ */
/*-
@@ -55,8 +55,6 @@ void intpri_intr_disable(int);
void netintr(void);
void tmu1_oneshot(void);
int tmu1_intr(void *);
-void tmu2_oneshot(void);
-int tmu2_intr(void *);
void setsoft(int);
/*
@@ -583,10 +581,8 @@ softintr_init(void)
asi->softintr_ipl = IPL_SOFT + i;
}
- intc_intr_establish(SH_INTEVT_TMU1_TUNI1, IST_LEVEL, IPL_SOFT,
+ intc_intr_establish(SH_INTEVT_TMU1_TUNI1, IST_LEVEL, IPL_SOFTNET,
tmu1_intr, NULL, "tmu1");
- intc_intr_establish(SH_INTEVT_TMU2_TUNI2, IST_LEVEL, IPL_SOFTNET,
- tmu2_intr, NULL, "tmu2");
}
void
@@ -617,10 +613,7 @@ softintr_dispatch(int ipl)
void
setsoft(int ipl)
{
- if (ipl < IPL_SOFTNET)
- tmu1_oneshot();
- else
- tmu2_oneshot();
+ tmu1_oneshot();
}
/* Register a software interrupt handler. */
@@ -696,28 +689,10 @@ tmu1_intr(void *arg)
_reg_bclr_1(SH_(TSTR), TSTR_STR1);
_reg_bclr_2(SH_(TCR1), TCR_UNF);
- softintr_dispatch(IPL_SOFTCLOCK);
- softintr_dispatch(IPL_SOFT);
-
- return (0);
-}
-
-void
-tmu2_oneshot(void)
-{
- _reg_bclr_1(SH_(TSTR), TSTR_STR2);
- _reg_write_4(SH_(TCNT2), 0);
- _reg_bset_1(SH_(TSTR), TSTR_STR2);
-}
-
-int
-tmu2_intr(void *arg)
-{
- _reg_bclr_1(SH_(TSTR), TSTR_STR2);
- _reg_bclr_2(SH_(TCR2), TCR_UNF);
-
softintr_dispatch(IPL_SOFTSERIAL);
softintr_dispatch(IPL_SOFTNET);
+ softintr_dispatch(IPL_SOFTCLOCK);
+ softintr_dispatch(IPL_SOFT);
return (0);
}