summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sparc64/dev/psycho.c30
-rw-r--r--sys/arch/sparc64/dev/psychoreg.h9
2 files changed, 37 insertions, 2 deletions
diff --git a/sys/arch/sparc64/dev/psycho.c b/sys/arch/sparc64/dev/psycho.c
index 42baeb77e5e..40c2c8baf38 100644
--- a/sys/arch/sparc64/dev/psycho.c
+++ b/sys/arch/sparc64/dev/psycho.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: psycho.c,v 1.60 2008/07/12 10:07:25 kettenis Exp $ */
+/* $OpenBSD: psycho.c,v 1.61 2008/07/20 10:37:43 kettenis Exp $ */
/* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */
/*
@@ -42,6 +42,7 @@
#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/reboot.h>
#include <uvm/uvm_extern.h>
@@ -123,6 +124,12 @@ void psycho_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
/* base pci_chipset */
extern struct sparc_pci_chipset _sparc_pci_chipset;
+u_int stick_get_timecount(struct timecounter *);
+
+struct timecounter stick_timecounter = {
+ stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
+};
+
/*
* autoconfiguration
*/
@@ -238,6 +245,7 @@ psycho_attach(struct device *parent, struct device *self, void *aux)
int psycho_br[2], n;
struct psycho_type *ptype;
char buf[32];
+ u_int stick_rate;
sc->sc_node = ma->ma_node;
sc->sc_bustag = ma->ma_bustag;
@@ -557,6 +565,18 @@ psycho_attach(struct device *parent, struct device *self, void *aux)
}
/*
+ * The UltraSPARC IIe has new STICK logic that provides a
+ * timebase counter that doesn't scale with processor
+ * frequency. Use it to provide a timecounter.
+ */
+ stick_rate = getpropint(findroot(), "stick-frequency", 0);
+ if (stick_rate > 0 && sc->sc_mode == PSYCHO_MODE_SABRE) {
+ stick_timecounter.tc_frequency = stick_rate;
+ stick_timecounter.tc_priv = sc;
+ tc_init(&stick_timecounter);
+ }
+
+ /*
* attach the pci.. note we pass PCI A tags, etc., for the sabre here.
*/
pba.pba_busname = "pci";
@@ -1284,3 +1304,11 @@ psycho_sabre_dvmamap_sync(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map,
if (ops & (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE))
membar(MemIssue);
}
+
+u_int
+stick_get_timecount(struct timecounter *tc)
+{
+ struct psycho_softc *sc = tc->tc_priv;
+
+ return psycho_psychoreg_read(sc, stick_reg_low);
+}
diff --git a/sys/arch/sparc64/dev/psychoreg.h b/sys/arch/sparc64/dev/psychoreg.h
index 93a01382129..5d174d76702 100644
--- a/sys/arch/sparc64/dev/psychoreg.h
+++ b/sys/arch/sparc64/dev/psychoreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: psychoreg.h,v 1.12 2008/07/12 13:08:04 kettenis Exp $ */
+/* $OpenBSD: psychoreg.h,v 1.13 2008/07/20 10:37:43 kettenis Exp $ */
/* $NetBSD: psychoreg.h,v 1.6.4.2 2001/09/13 01:14:40 thorpej Exp $ */
/*
@@ -219,6 +219,13 @@ struct psychoreg {
u_int64_t pad19[208];
} psy_strbufdiag[2]; /* For PCI a and b */
+ u_int64_t pad18[1036];
+
+ u_int64_t stick_cmp_low; /* STICK comparison low reg */ /* 1fe.0000.f060 */
+ u_int64_t stick_cmp_high; /* STICK comparison high reg */ /* 1fe.0000.f068 */
+ u_int64_t stick_reg_low; /* STICK counter low reg */ /* 1fe.0000.f070 */
+ u_int64_t stick_reg_high; /* STICK counter high reg */ /* 1fe.0000.f078 */
+
/*
* Here is the rest of the map, which we're not specifying:
*