From d9c89e4ca5b8ffba3ff406551fe3de5edefe2586 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 20 Jul 2008 10:37:43 +0000 Subject: [PATCH] Provide a timecounter based on the UltraSPARC IIe STICK logic. --- sys/arch/sparc64/dev/psycho.c | 30 +++++++++++++++++++++++++++++- sys/arch/sparc64/dev/psychoreg.h | 9 ++++++++- 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 #include #include +#include #include #include @@ -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; @@ -556,6 +564,18 @@ psycho_attach(struct device *parent, struct device *self, void *aux) printf("\n"); } + /* + * 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. */ @@ -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: * -- 2.20.1