i80321 timecounter support.

Patch from Garrett D'Amore, tested by me.
This commit is contained in:
gavan 2006-09-10 23:13:59 +00:00
parent 653b061500
commit 8814e529bd
1 changed files with 98 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: i80321_timer.c,v 1.14 2006/09/10 18:57:02 gdamore Exp $ */
/* $NetBSD: i80321_timer.c,v 1.15 2006/09/10 23:13:59 gavan Exp $ */
/*
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: i80321_timer.c,v 1.14 2006/09/10 18:57:02 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: i80321_timer.c,v 1.15 2006/09/10 23:13:59 gavan Exp $");
#include "opt_perfctrs.h"
#include "opt_i80321.h"
@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: i80321_timer.c,v 1.14 2006/09/10 18:57:02 gdamore Ex
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/time.h>
#include <sys/timetc.h>
#include <dev/clock_subr.h>
@ -67,6 +68,10 @@ void (*i80321_hardclock_hook)(void);
#endif
#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000)
#ifdef __HAVE_TIMECOUNTER
static void tmr1_tc_init(void);
#endif
static void *clock_ih;
static uint32_t counts_per_hz;
@ -120,6 +125,57 @@ trr0_write(uint32_t val)
: "r" (val));
}
#ifdef __HAVE_TIMECOUNTER
static inline uint32_t
tmr1_read(void)
{
uint32_t rv;
__asm volatile("mrc p6, 0, %0, c1, c1, 0"
: "=r" (rv));
return (rv);
}
static inline void
tmr1_write(uint32_t val)
{
__asm volatile("mcr p6, 0, %0, c1, c1, 0"
:
: "r" (val));
}
static inline uint32_t
tcr1_read(void)
{
uint32_t rv;
__asm volatile("mrc p6, 0, %0, c3, c1, 0"
: "=r" (rv));
return (rv);
}
static inline void
tcr1_write(uint32_t val)
{
__asm volatile("mcr p6, 0, %0, c3, c1, 0"
:
: "r" (val));
}
static inline void
trr1_write(uint32_t val)
{
__asm volatile("mcr p6, 0, %0, c5, c1, 0"
:
: "r" (val));
}
#endif /* __HAVE_TIMECOUNTER */
static inline void
tisr_write(uint32_t val)
{
@ -169,6 +225,7 @@ cpu_initclocks(void)
aprint_error("Cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
}
#ifndef __HAVE_TIMECOUNTER
tick = 1000000 / hz; /* number of microseconds between interrupts */
tickfix = 1000000 - (hz * tick);
if (tickfix) {
@ -178,6 +235,7 @@ cpu_initclocks(void)
tickfix >>= (ftp - 1);
tickfixinterval = hz >> (ftp - 1);
}
#endif
/*
* We only have one timer available; stathz and profhz are
@ -223,6 +281,10 @@ cpu_initclocks(void)
tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
restore_interrupts(oldirqstate);
#ifdef __HAVE_TIMECOUNTER
tmr1_tc_init();
#endif
}
/*
@ -243,6 +305,8 @@ setstatclockrate(int newhz)
*/
}
#ifndef __HAVE_TIMECOUNTER
/*
* microtime:
*
@ -285,6 +349,38 @@ microtime(struct timeval *tvp)
restore_interrupts(oldirqstate);
}
#else
static inline uint32_t
tmr1_tc_get(struct timecounter *tch)
{
return (~tcr1_read());
}
void
tmr1_tc_init(void)
{
static struct timecounter tmr1_tc = {
.tc_get_timecount = tmr1_tc_get,
.tc_frequency = COUNTS_PER_SEC,
.tc_counter_mask = ~0,
.tc_name = "tmr1_count",
.tc_quality = 100,
};
/* program the tc */
trr1_write(~0); /* reload value */
tcr1_write(~0); /* current value */
tmr1_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
trr1_write(~0);
tc_init(&tmr1_tc);
}
#endif
/*
* delay:
*