Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/marvell Rework mvsoctmr(4), improving timekeepi...
details: https://anonhg.NetBSD.org/src/rev/11c1869ce573
branches: trunk
changeset: 765895:11c1869ce573
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Thu Jun 09 13:43:44 2011 +0000
description:
Rework mvsoctmr(4), improving timekeeping accuracy
Inconveniently the Marvell hardware only counts down.
We need to reverse this for timecounter(9), and we need
to do it in a very lightweight way.
- use Timer0 for the clock interrupt
- use Timer1 for timecounter(9) and delay(9)
- drop statclock due to lack of timers (does anyone actually use this?)
diffstat:
sys/arch/arm/marvell/mvsoctmr.c | 82 +++++++++--------------------------------
1 files changed, 18 insertions(+), 64 deletions(-)
diffs (189 lines):
diff -r a637a3b4ddae -r 11c1869ce573 sys/arch/arm/marvell/mvsoctmr.c
--- a/sys/arch/arm/marvell/mvsoctmr.c Thu Jun 09 13:41:40 2011 +0000
+++ b/sys/arch/arm/marvell/mvsoctmr.c Thu Jun 09 13:43:44 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsoctmr.c,v 1.1 2010/10/03 05:49:24 kiyohara Exp $ */
+/* $NetBSD: mvsoctmr.c,v 1.2 2011/06/09 13:43:44 jakllsch Exp $ */
/*
* Copyright (c) 2007, 2008 KIYOHARA Takashi
* All rights reserved.
@@ -25,7 +25,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v 1.1 2010/10/03 05:49:24 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v 1.2 2011/06/09 13:43:44 jakllsch Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -60,18 +60,12 @@
static void mvsoctmr_attach(device_t, device_t, void *);
static int clockhandler(void *);
-static int statclockhandler(void *);
static u_int mvsoctmr_get_timecount(struct timecounter *);
static void mvsoctmr_cntl(struct mvsoctmr_softc *, int, u_int, int, int);
-#ifndef STATHZ
-#define STATHZ 64
-#endif
-
static struct mvsoctmr_softc *mvsoctmr_sc;
-static uint32_t clock_ticks, statclock_ticks;
static struct timecounter mvsoctmr_timecounter = {
mvsoctmr_get_timecount, /* get_timecount */
0, /* no poll_pps */
@@ -82,7 +76,6 @@
NULL, /* prev */
NULL, /* next */
};
-static volatile uint32_t mvsoctmr_base;
CFATTACH_DECL_NEW(mvsoctmr, sizeof(struct mvsoctmr_softc),
mvsoctmr_match, mvsoctmr_attach, NULL, NULL);
@@ -121,6 +114,9 @@
if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
mva->mva_offset, mva->mva_size, &sc->sc_ioh))
panic("%s: Cannot map registers", device_xname(self));
+
+ mvsoctmr_timecounter.tc_name = device_xname(self);
+ mvsoctmr_cntl(sc, MVSOCTMR_TIMER1, 0xffffffff, 1, 1);
}
/*
@@ -133,48 +129,20 @@
{
struct clockframe *frame = arg;
- atomic_add_32(&mvsoctmr_base, clock_ticks);
-
hardclock(frame);
return 1;
}
/*
- * statclockhandler:
- *
- * Handle the statclock interrupt.
- */
-static int
-statclockhandler(void *arg)
-{
- struct clockframe *frame = arg;
-
- statclock(frame);
-
- return 1;
-}
-
-
-/*
* setstatclockrate:
*
* Set the rate of the statistics clock.
- *
- * We assume that hz is either stathz or profhz, and that neither
- * will change after being set by cpu_initclocks(). We could
- * recalculate the intervals here, but that would be a pain.
*/
/* ARGSUSED */
void
setstatclockrate(int newhz)
{
- struct mvsoctmr_softc *sc = mvsoctmr_sc;
- const int en = 1, autoen = 1;
-
- statclock_ticks = mvTclk / newhz;
-
- mvsoctmr_cntl(sc, MVSOCTMR_TIMER1, statclock_ticks, en, autoen);
}
/*
@@ -188,32 +156,26 @@
struct mvsoctmr_softc *sc;
void *clock_ih;
const int en = 1, autoen = 1;
+ uint32_t timer0_tval;
sc = mvsoctmr_sc;
if (sc == NULL)
panic("cpu_initclocks: mvsoctmr not found");
- stathz = profhz = STATHZ;
+ mvsoctmr_timecounter.tc_priv = sc;
mvsoctmr_timecounter.tc_frequency = mvTclk;
- clock_ticks = mvTclk / hz;
- mvsoctmr_cntl(sc, MVSOCTMR_TIMER0, clock_ticks, en, autoen);
+ timer0_tval = (mvTclk * 2) / (u_long) hz;
+ timer0_tval = (timer0_tval / 2) + (timer0_tval & 1);
+
+ mvsoctmr_cntl(sc, MVSOCTMR_TIMER0, timer0_tval, en, autoen);
+ mvsoctmr_cntl(sc, MVSOCTMR_TIMER1, 0xffffffff, en, autoen);
clock_ih = mvsoc_bridge_intr_establish(MVSOC_MLMB_MLMBI_CPUTIMER0INTREQ,
IPL_CLOCK, clockhandler, NULL);
if (clock_ih == NULL)
panic("cpu_initclocks: unable to register timer interrupt");
- if (stathz) {
- setstatclockrate(stathz);
- clock_ih = mvsoc_bridge_intr_establish(
- MVSOC_MLMB_MLMBI_CPUTIMER1INTREQ, IPL_HIGH,
- statclockhandler, NULL);
- if (clock_ih == NULL)
- panic("cpu_initclocks:"
- " unable to register statclock timer interrupt");
- }
-
tc_init(&mvsoctmr_timecounter);
}
@@ -237,7 +199,7 @@
* counted.
*/
initial_tick = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- MVSOCTMR_TIMER(MVSOCTMR_TIMER0));
+ MVSOCTMR_TIMER(MVSOCTMR_TIMER1));
if (n <= UINT_MAX / mvTclk) {
/*
@@ -255,9 +217,9 @@
while (remaining > 0) {
cur_tick = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- MVSOCTMR_TIMER(MVSOCTMR_TIMER0));
+ MVSOCTMR_TIMER(MVSOCTMR_TIMER1));
if (cur_tick > initial_tick)
- remaining -= clock_ticks - cur_tick + initial_tick;
+ remaining -= 0xffffffff - cur_tick + initial_tick;
else
remaining -= (initial_tick - cur_tick);
initial_tick = cur_tick;
@@ -267,20 +229,12 @@
static u_int
mvsoctmr_get_timecount(struct timecounter *tc)
{
- struct mvsoctmr_softc *sc = mvsoctmr_sc;
- uint32_t counter, base;
- u_int intrstat;
+ struct mvsoctmr_softc *sc = tc->tc_priv;
- intrstat = disable_interrupts(I32_bit);
- base = mvsoctmr_base;
- counter = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- MVSOCTMR_TIMER(MVSOCTMR_TIMER0));
- restore_interrupts(intrstat);
-
- return base - counter;
+ return 0xffffffff - bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ MVSOCTMR_TIMER(MVSOCTMR_TIMER1));
}
-
static void
mvsoctmr_cntl(struct mvsoctmr_softc *sc, int num, u_int ticks, int en,
int autoen)
Home |
Main Index |
Thread Index |
Old Index