support UltraSPARC-IIe STICK counter as time base
This commit is contained in:
parent
bcd47cf3a7
commit
975e4c65ca
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
@ -249,11 +249,11 @@ struct psychoreg {
|
||||
/* 1fe.0000.d000-f058 */
|
||||
uint64_t pad20[1036];
|
||||
/* US-IIe and II'i' only */
|
||||
uint64_t stick_cmp_low;
|
||||
uint64_t stick_cmp_high;
|
||||
uint64_t stick_count_low;
|
||||
uint64_t stick_count_high;
|
||||
uint64_t estar_mode;
|
||||
uint64_t stick_cmp_low;
|
||||
uint64_t stick_cmp_high;
|
||||
uint64_t stick_count_low;
|
||||
uint64_t stick_count_high;
|
||||
uint64_t estar_mode;
|
||||
|
||||
/*
|
||||
* Here is the rest of the map, which we're not specifying:
|
||||
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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 *);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
sclk = prom_getpropint(findroot(), "stick-frequency", 0);
|
||||
|
||||
ci->ci_system_clockrate[0] = sclk;
|
||||
ci->ci_system_clockrate[1] = sclk / 1000000;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user