diff options
-rw-r--r-- | sys/arch/sh/include/_types.h | 5 | ||||
-rw-r--r-- | sys/arch/sh/sh/clock.c | 99 | ||||
-rw-r--r-- | sys/arch/sh/sh/interrupt.c | 35 |
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); } |