support UltraSPARC-IIe STICK counter as time base

This commit is contained in:
macallan 2013-08-20 19:19:23 +00:00
parent bcd47cf3a7
commit 975e4c65ca
6 changed files with 183 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: psycho.c,v 1.113 2013/06/21 20:09:58 nakayama Exp $ */
/* $NetBSD: psycho.c,v 1.114 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1999, 2000 Matthew R. Green
@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.113 2013/06/21 20:09:58 nakayama Exp $");
__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.114 2013/08/20 19:19:23 macallan Exp $");
#include "opt_ddb.h"
@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.113 2013/06/21 20:09:58 nakayama Exp $"
#define PDB_INTR 0x04
#define PDB_INTMAP 0x08
#define PDB_CONF 0x10
#define PDB_STICK 0x20
int psycho_debug = 0x0;
#define DPRINTF(l, s) do { if (psycho_debug & l) printf s; } while (0)
#else
@ -220,6 +221,8 @@ struct psycho_names {
{ NULL, 0 }
};
struct psycho_softc *psycho0 = NULL;
static int
psycho_match(device_t parent, cfdata_t match, void *aux)
{
@ -307,7 +310,11 @@ psycho_attach(device_t parent, device_t self, void *aux)
sc->sc_node = ma->ma_node;
sc->sc_bustag = ma->ma_bustag;
sc->sc_dmatag = ma->ma_dmatag;
sc->sc_last_stick = 0;
if (psycho0 == NULL)
psycho0 = sc;
DPRINTF(PDB_STICK, ("init psycho0 %lx\n", (long)sc));
/*
* Identify the device.
*/
@ -375,6 +382,7 @@ found:
ma->ma_address[0], &sc->sc_bh);
sc->sc_regs = (struct psychoreg *)
bus_space_vaddr(sc->sc_bustag, sc->sc_bh);
bus_space_subregion(sc->sc_bustag, sc->sc_bh,
offsetof(struct psychoreg, psy_pcictl),
sizeof(struct pci_ctl), &pci_ctl);
@ -397,7 +405,6 @@ found:
ma->ma_nreg);
}
csr = bus_space_read_8(sc->sc_bustag, sc->sc_bh,
offsetof(struct psychoreg, psy_csr));
sc->sc_ign = 0x7c0; /* APB IGN is always 0x7c */
@ -1510,3 +1517,67 @@ psycho_sabre_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
}
bus_dmamap_sync(t->_parent, map, offset, len, ops);
}
/* US-IIe STICK support */
long
psycho_getstick(void)
{
long foo;
foo = bus_space_read_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CNT_LOW) |
(bus_space_read_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CNT_HIGH) & 0x7fffffff) << 32;
return foo;
}
void
psycho_setstick(long cnt)
{
/*
* looks like we can't actually write the STICK counter, so instead we
* prepare sc_last_stick for the coming interrupt setup
*/
#if 0
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CNT_HIGH, (cnt >> 32));
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CNT_LOW, (uint32_t)(cnt & 0xffffffff));
#endif
if (cnt == 0) {
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CMP_HIGH, 0);
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CMP_LOW, 0);
psycho0->sc_last_stick = 0;
}
psycho0->sc_last_stick = psycho_getstick();
DPRINTF(PDB_STICK, ("stick: %ld\n", psycho0->sc_last_stick));
}
void
psycho_nextstick(long diff)
{
uint64_t cmp, now;
/*
* there is no way we'll ever overflow
* the counter is 63 bits wide, at 12MHz that's >24000 years
*/
now = psycho_getstick() + 1000;
cmp = psycho0->sc_last_stick;
while (cmp < now)
cmp += diff;
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CMP_HIGH, (cmp >> 32) & 0x7fffffff);
bus_space_write_8(psycho0->sc_bustag, psycho0->sc_bh,
STICK_CMP_LOW, (cmp & 0xffffffff));
psycho0->sc_last_stick = cmp;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: psychoreg.h,v 1.18 2013/08/20 10:33:03 macallan Exp $ */
/* $NetBSD: psychoreg.h,v 1.19 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1999 Matthew R. Green
@ -297,6 +297,12 @@ struct psychoreg {
*/
};
#define STICK_CMP_LOW 0xf060
#define STICK_CMP_HIGH 0xf068
#define STICK_CNT_LOW 0xf070
#define STICK_CNT_HIGH 0xf078
#define ESTAR_MODE 0xf080
/* what the bits mean! */
/* PCI [a|b] control/status register */
@ -313,9 +319,8 @@ struct psychoreg {
/* the following registers only exist on US-IIe and US-II'i' */
/* STICK_COMPARE */
#define STICK_ENABLE 0x8000000000000000LL /* enable STICK interrupt */
#define STICK_MASK 0x7fffffffffffffffLL /* counter is 63bit wide */
/* STICK_CMP_HIGH */
#define STICK_DISABLE 0x80000000 /* disable STICK interrupt */
/*
* ESTAR_MODE

View File

@ -1,4 +1,4 @@
/* $NetBSD: psychovar.h,v 1.18 2011/06/02 00:24:23 christos Exp $ */
/* $NetBSD: psychovar.h,v 1.19 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1999, 2000 Matthew R. Green
@ -124,6 +124,7 @@ struct psycho_softc {
struct sysmon_pswitch *sc_smcontext; /* power switch definition */
int sc_powerpressed;/* already signaled */
uint64_t sc_last_stick;
};
/* get a PCI offset address from bus_space_handle_t */
@ -137,4 +138,8 @@ bus_space_tag_t psycho_alloc_bus_tag(struct psycho_pbm *, int);
#define psycho_alloc_mem_tag(pp) psycho_alloc_bus_tag((pp), PCI_MEMORY_BUS_SPACE)
#define psycho_alloc_io_tag(pp) psycho_alloc_bus_tag((pp), PCI_IO_BUS_SPACE)
long psycho_getstick(void);
void psycho_setstick(long);
void psycho_nextstick(long);
#endif /* _SPARC64_DEV_PSYCHOVAR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.102 2013/06/21 20:09:59 nakayama Exp $ */
/* $NetBSD: cpu.h,v 1.103 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1992, 1993
@ -358,11 +358,14 @@ void * reserve_dumppages(void *);
struct timeval;
int tickintr(void *); /* level 10/14 (tick) interrupt code */
int stickintr(void *); /* system tick interrupt code */
int stick2eintr(void *); /* system tick interrupt code */
int clockintr(void *); /* level 10 (clock) interrupt code */
int statintr(void *); /* level 14 (statclock) interrupt code */
int schedintr(void *); /* level 10 (schedclock) interrupt code */
void tickintr_establish(int, int (*)(void *));
void stickintr_establish(int, int (*)(void *));
void stick2eintr_establish(int, int (*)(void *));
/* locore.s */
struct fpstate64;
void savefpstate(struct fpstate64 *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.108 2013/05/24 23:02:08 nakayama Exp $ */
/* $NetBSD: clock.c,v 1.109 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1992, 1993
@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.108 2013/05/24 23:02:08 nakayama Exp $");
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.109 2013/08/20 19:19:23 macallan Exp $");
#include "opt_multiprocessor.h"
@ -90,6 +90,14 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.108 2013/05/24 23:02:08 nakayama Exp $")
#include <sparc64/sparc64/timerreg.h>
#include <sparc64/dev/iommureg.h>
/* just because US-IIe STICK registers live in psycho space */
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <sparc64/dev/iommureg.h>
#include <sparc64/dev/iommuvar.h>
#include <sparc64/dev/psychoreg.h>
#include <sparc64/dev/psychovar.h>
/*
* Clock assignments:
@ -138,6 +146,7 @@ int timerblurb = 10; /* Guess a value; used before clock is attached */
static u_int tick_get_timecount(struct timecounter *);
static u_int stick_get_timecount(struct timecounter *);
static u_int stick2e_get_timecount(struct timecounter *);
/*
* define timecounter "tick-counter"
@ -154,6 +163,8 @@ static struct timecounter tick_timecounter = {
NULL /* next timecounter */
};
/* US-III %stick */
static struct timecounter stick_timecounter = {
stick_get_timecount, /* get_timecount */
0, /* no poll_pps */
@ -165,6 +176,20 @@ static struct timecounter stick_timecounter = {
NULL /* next timecounter */
};
/* US-IIe STICK counter */
static struct timecounter stick2e_timecounter = {
stick2e_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency - set at initialisation */
"stick-counter", /* name */
200, /* quality */
0, /* private reference - UNUSED */
NULL /* next timecounter */
};
/*
* tick_get_timecount provide current tick counter value
*/
@ -180,6 +205,12 @@ stick_get_timecount(struct timecounter *tc)
return getstick();
}
static u_int
stick2e_get_timecount(struct timecounter *tc)
{
return psycho_getstick();
}
#ifdef MULTIPROCESSOR
static u_int counter_get_timecount(struct timecounter *);
@ -368,6 +399,27 @@ stickintr_establish(int pil, int (*fun)(void *))
intr_restore(s);
}
void
stick2eintr_establish(int pil, int (*fun)(void *))
{
int s;
struct intrhand *ih;
struct cpu_info *ci = curcpu();
ih = sparc_softintr_establish(pil, fun, NULL);
ih->ih_number = 1;
if (CPU_IS_PRIMARY(ci))
intr_establish(pil, true, ih);
ci->ci_tick_ih = ih;
/* set the next interrupt time */
ci->ci_tick_increment = ci->ci_system_clockrate[0] / hz;
s = intr_disable();
psycho_nextstick(ci->ci_tick_increment);
intr_restore(s);
}
/*
* Set up the real-time and statistics clocks. Leave stathz 0 only if
* no alternative timer is available.
@ -413,6 +465,11 @@ cpu_initclocks(void)
if (ci->ci_system_clockrate[0] == 0) {
tick_timecounter.tc_frequency = ci->ci_cpu_clockrate[0];
tc_init(&tick_timecounter);
} else if(CPU_IS_HUMMINGBIRD()) {
psycho_setstick(0);
stick2e_timecounter.tc_frequency =
ci->ci_system_clockrate[0];
tc_init(&stick2e_timecounter);
} else {
setstick(0);
stick_timecounter.tc_frequency =
@ -433,6 +490,12 @@ cpu_initclocks(void)
/* We don't have a counter-timer -- use %tick */
tickintr_establish(PIL_CLOCK, tickintr);
} else if(CPU_IS_HUMMINGBIRD()) {
aprint_normal("No counter-timer -- using STICK "
"at %luMHz as system clock.\n",
(unsigned long)ci->ci_system_clockrate[1]);
/* We don't have a counter-timer -- use STICK */
stick2eintr_establish(PIL_CLOCK, stick2eintr);
} else {
aprint_normal("No counter-timer -- using %%stick "
"at %luMHz as system clock.\n",
@ -596,6 +659,22 @@ stickintr(void *cap)
return (1);
}
int
stick2eintr(void *cap)
{
int s;
hardclock((struct clockframe *)cap);
s = intr_disable();
/* Reset the interrupt */
psycho_nextstick(curcpu()->ci_tick_increment);
intr_restore(s);
curcpu()->ci_tick_evcnt.ev_count++;
return (1);
}
#ifndef MULTIPROCESSOR
/*
* Level 14 (stat clock) interrupt handler.

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $ */
/* $NetBSD: cpu.c,v 1.104 2013/08/20 19:19:23 macallan Exp $ */
/*
* Copyright (c) 1996
@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.104 2013/08/20 19:19:23 macallan Exp $");
#include "opt_multiprocessor.h"
@ -299,9 +299,8 @@ cpu_attach(device_t parent, device_t dev, void *aux)
ci->ci_cpu_clockrate[1] = clk / 1000000;
}
if (!CPU_IS_HUMMINGBIRD()) {
sclk = prom_getpropint(findroot(), "stick-frequency", 0);
}
ci->ci_system_clockrate[0] = sclk;
ci->ci_system_clockrate[1] = sclk / 1000000;