Module Name: src Committed By: macallan Date: Tue Aug 20 19:19:23 UTC 2013
Modified Files: src/sys/arch/sparc64/dev: psycho.c psychoreg.h psychovar.h src/sys/arch/sparc64/include: cpu.h src/sys/arch/sparc64/sparc64: clock.c cpu.c Log Message: support UltraSPARC-IIe STICK counter as time base To generate a diff of this commit: cvs rdiff -u -r1.113 -r1.114 src/sys/arch/sparc64/dev/psycho.c cvs rdiff -u -r1.18 -r1.19 src/sys/arch/sparc64/dev/psychoreg.h \ src/sys/arch/sparc64/dev/psychovar.h cvs rdiff -u -r1.102 -r1.103 src/sys/arch/sparc64/include/cpu.h cvs rdiff -u -r1.108 -r1.109 src/sys/arch/sparc64/sparc64/clock.c cvs rdiff -u -r1.103 -r1.104 src/sys/arch/sparc64/sparc64/cpu.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sparc64/dev/psycho.c diff -u src/sys/arch/sparc64/dev/psycho.c:1.113 src/sys/arch/sparc64/dev/psycho.c:1.114 --- src/sys/arch/sparc64/dev/psycho.c:1.113 Fri Jun 21 20:09:58 2013 +++ src/sys/arch/sparc64/dev/psycho.c Tue Aug 20 19:19:23 2013 @@ -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 #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 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_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; +} Index: src/sys/arch/sparc64/dev/psychoreg.h diff -u src/sys/arch/sparc64/dev/psychoreg.h:1.18 src/sys/arch/sparc64/dev/psychoreg.h:1.19 --- src/sys/arch/sparc64/dev/psychoreg.h:1.18 Tue Aug 20 10:33:03 2013 +++ src/sys/arch/sparc64/dev/psychoreg.h Tue Aug 20 19:19:23 2013 @@ -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 Index: src/sys/arch/sparc64/dev/psychovar.h diff -u src/sys/arch/sparc64/dev/psychovar.h:1.18 src/sys/arch/sparc64/dev/psychovar.h:1.19 --- src/sys/arch/sparc64/dev/psychovar.h:1.18 Thu Jun 2 00:24:23 2011 +++ src/sys/arch/sparc64/dev/psychovar.h Tue Aug 20 19:19:23 2013 @@ -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(str #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_ */ Index: src/sys/arch/sparc64/include/cpu.h diff -u src/sys/arch/sparc64/include/cpu.h:1.102 src/sys/arch/sparc64/include/cpu.h:1.103 --- src/sys/arch/sparc64/include/cpu.h:1.102 Fri Jun 21 20:09:59 2013 +++ src/sys/arch/sparc64/include/cpu.h Tue Aug 20 19:19:23 2013 @@ -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 *); Index: src/sys/arch/sparc64/sparc64/clock.c diff -u src/sys/arch/sparc64/sparc64/clock.c:1.108 src/sys/arch/sparc64/sparc64/clock.c:1.109 --- src/sys/arch/sparc64/sparc64/clock.c:1.108 Fri May 24 23:02:08 2013 +++ src/sys/arch/sparc64/sparc64/clock.c Tue Aug 20 19:19:23 2013 @@ -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. #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; u 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_timecount 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_timecoun 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 * 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)( 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. Index: src/sys/arch/sparc64/sparc64/cpu.c diff -u src/sys/arch/sparc64/sparc64/cpu.c:1.103 src/sys/arch/sparc64/sparc64/cpu.c:1.104 --- src/sys/arch/sparc64/sparc64/cpu.c:1.103 Thu Nov 8 00:34:38 2012 +++ src/sys/arch/sparc64/sparc64/cpu.c Tue Aug 20 19:19:23 2013 @@ -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 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;