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;
 

Reply via email to