summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMarc Balmer <mbalmer@cvs.openbsd.org>2007-10-07 13:41:49 +0000
committerMarc Balmer <mbalmer@cvs.openbsd.org>2007-10-07 13:41:49 +0000
commitbde97fbac7941781ddaf7bffca8603f34869f84c (patch)
treefb0a8d00c605f503f49b1e45c92ba6cfa926d4ce /sys/arch
parent7d301fc0cffcf6885a1abd24bcc3402a6dd3e9ec (diff)
Add support for the PCI-ISA bridge, timecounter, and watchdog timer
found in the CS5536 companion chip to the AMD Geode LX-800 processor. glxpcib(4) driver written by mickey, with some tweaks by me. Manpage nits by jmc. Tested on the Soekris net5501 (by me) and the Alix 2a2 (by earxtacy@dixinet.com) ok kettenis
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/conf/GENERIC4
-rw-r--r--sys/arch/i386/conf/files.i3869
-rw-r--r--sys/arch/i386/pci/glxpcib.c208
3 files changed, 218 insertions, 3 deletions
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index ff7e30ae060..f8d5a237bd9 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.578 2007/09/30 10:16:56 jsg Exp $
+# $OpenBSD: GENERIC,v 1.579 2007/10/07 13:41:48 mbalmer Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -54,6 +54,7 @@ isa0 at pcib?
isa0 at ichpcib?
isa0 at piixpcib?
isa0 at gscpcib?
+isa0 at glxpcib?
eisa0 at mainbus0
pci* at mainbus0
@@ -85,6 +86,7 @@ ichpcib* at pci? # Intel ICHx/ICHx-M LPC bridges
piixpcib* at pci? # Intel PIIX4 PCI-ISA bridge
gscpcib* at pci? # NS Geode SC1100 PCI-ISA bridge
gpio* at gscpcib?
+glxpcib* at pci? # AMD CS5536 PCI-ISA bridge
# power management and other environmental stuff
elansc* at pci? # AMD Elan SC520 System Controller
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index cb27486a830..1ff9e84a4e6 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.164 2007/07/04 08:16:13 mpf Exp $
+# $OpenBSD: files.i386,v 1.165 2007/10/07 13:41:48 mbalmer Exp $
#
# new style config file for i386 architecture
#
@@ -132,10 +132,15 @@ device gscpm
attach gscpm at pci
file arch/i386/pci/gscpm.c gscpm
+# AMD Geode CS5536 PCI-ISA bridge
+device glxpcib: isabus
+attach glxpcib at pci
+file arch/i386/pci/glxpcib.c glxpcib
+
# PCI-ISA bridge chipsets
device pcib: isabus
attach pcib at pci
-file arch/i386/pci/pcib.c pcib | ichpcib | gscpcib | piixpcib
+file arch/i386/pci/pcib.c pcib | ichpcib | gscpcib | glxpcib | piixpcib
# Intel ICHx/ICHx-M LPC bridges
device ichpcib: isabus
diff --git a/sys/arch/i386/pci/glxpcib.c b/sys/arch/i386/pci/glxpcib.c
new file mode 100644
index 00000000000..64d179616f3
--- /dev/null
+++ b/sys/arch/i386/pci/glxpcib.c
@@ -0,0 +1,208 @@
+/* $OpenBSD: glxpcib.c,v 1.1 2007/10/07 13:41:48 mbalmer Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * AMD CS5536 series LPC bridge also containing timer and watchdog
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/sysctl.h>
+#include <sys/timetc.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#define AMD5536_REV 0x51400017
+#define AMD5536_REV_MASK 0xff
+#define AMD5536_TMC 0x51400050
+
+#define MSR_LBAR_MFGPT 0x5140000d
+#define AMD5536_MFGPT0_CMP1 0x00000000
+#define AMD5536_MFGPT0_CMP2 0x00000002
+#define AMD5536_MFGPT0_CNT 0x00000004
+#define AMD5536_MFGPT0_SETUP 0x00000006
+#define AMD5536_MFGPT_DIV_MASK 0x000f /* div = 1 << mask */
+#define AMD5536_MFGPT_CLKSEL 0x0010
+#define AMD5536_MFGPT_REV_EN 0x0020
+#define AMD5536_MFGPT_CMP1DIS 0x0000
+#define AMD5536_MFGPT_CMP1EQ 0x0040
+#define AMD5536_MFGPT_CMP1GE 0x0080
+#define AMD5536_MFGPT_CMP1EV 0x00c0
+#define AMD5536_MFGPT_CMP2DIS 0x0000
+#define AMD5536_MFGPT_CMP2EQ 0x0100
+#define AMD5536_MFGPT_CMP2GE 0x0200
+#define AMD5536_MFGPT_CMP2EV 0x0300
+#define AMD5536_MFGPT_STOP_EN 0x0800
+#define AMD5536_MFGPT_SET 0x1000
+#define AMD5536_MFGPT_CMP1 0x2000
+#define AMD5536_MFGPT_CMP2 0x4000
+#define AMD5536_MFGPT_CNT_EN 0x8000
+#define AMD5536_MFGPT_IRQ 0x51400028
+#define AMD5536_MFGPT0_C1_IRQM 0x00000001
+#define AMD5536_MFGPT1_C1_IRQM 0x00000002
+#define AMD5536_MFGPT2_C1_IRQM 0x00000004
+#define AMD5536_MFGPT3_C1_IRQM 0x00000008
+#define AMD5536_MFGPT4_C1_IRQM 0x00000010
+#define AMD5536_MFGPT5_C1_IRQM 0x00000020
+#define AMD5536_MFGPT6_C1_IRQM 0x00000040
+#define AMD5536_MFGPT7_C1_IRQM 0x00000080
+#define AMD5536_MFGPT0_C2_IRQM 0x00000100
+#define AMD5536_MFGPT1_C2_IRQM 0x00000200
+#define AMD5536_MFGPT2_C2_IRQM 0x00000400
+#define AMD5536_MFGPT3_C2_IRQM 0x00000800
+#define AMD5536_MFGPT4_C2_IRQM 0x00001000
+#define AMD5536_MFGPT5_C2_IRQM 0x00002000
+#define AMD5536_MFGPT6_C2_IRQM 0x00004000
+#define AMD5536_MFGPT7_C2_IRQM 0x00008000
+#define AMD5536_MFGPT_NR 0x51400029
+#define AMD5536_MFGPT0_C1_NMIM 0x00000001
+#define AMD5536_MFGPT1_C1_NMIM 0x00000002
+#define AMD5536_MFGPT2_C1_NMIM 0x00000004
+#define AMD5536_MFGPT3_C1_NMIM 0x00000008
+#define AMD5536_MFGPT4_C1_NMIM 0x00000010
+#define AMD5536_MFGPT5_C1_NMIM 0x00000020
+#define AMD5536_MFGPT6_C1_NMIM 0x00000040
+#define AMD5536_MFGPT7_C1_NMIM 0x00000080
+#define AMD5536_MFGPT0_C2_NMIM 0x00000100
+#define AMD5536_MFGPT1_C2_NMIM 0x00000200
+#define AMD5536_MFGPT2_C2_NMIM 0x00000400
+#define AMD5536_MFGPT3_C2_NMIM 0x00000800
+#define AMD5536_MFGPT4_C2_NMIM 0x00001000
+#define AMD5536_MFGPT5_C2_NMIM 0x00002000
+#define AMD5536_MFGPT6_C2_NMIM 0x00004000
+#define AMD5536_MFGPT7_C2_NMIM 0x00008000
+#define AMD5536_NMI_LEG 0x00010000
+#define AMD5536_MFGPT0_C2_RSTEN 0x01000000
+#define AMD5536_MFGPT1_C2_RSTEN 0x02000000
+#define AMD5536_MFGPT2_C2_RSTEN 0x04000000
+#define AMD5536_MFGPT3_C2_RSTEN 0x08000000
+#define AMD5536_MFGPT4_C2_RSTEN 0x10000000
+#define AMD5536_MFGPT5_C2_RSTEN 0x20000000
+#define AMD5536_MFGPT_SETUP 0x5140002b
+
+struct glxpcib_softc {
+ struct device sc_dev;
+
+ struct timecounter sc_timecounter;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct cfdriver glxpcib_cd = {
+ NULL, "glxpcib", DV_DULL
+};
+
+int glxpcib_match(struct device *, void *, void *);
+void glxpcib_attach(struct device *, struct device *, void *);
+
+struct cfattach glxpcib_ca = {
+ sizeof(struct glxpcib_softc), glxpcib_match, glxpcib_attach
+};
+
+/* from arch/<*>/pci/pcib.c */
+void pcibattach(struct device *parent, struct device *self, void *aux);
+
+u_int glxpcib_get_timecount(struct timecounter *tc);
+int glxpcib_wdogctl_cb(void *, int);
+
+const struct pci_matchid glxpcib_devices[] = {
+ { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB }
+};
+
+int
+glxpcib_match(struct device *parent, void *match, void *aux)
+{
+ if (pci_matchbyid((struct pci_attach_args *)aux, glxpcib_devices,
+ sizeof(glxpcib_devices) / sizeof(glxpcib_devices[0])))
+ return 2;
+
+ return 0;
+}
+
+void
+glxpcib_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct glxpcib_softc *sc = (struct glxpcib_softc *)self;
+ struct timecounter *tc = &sc->sc_timecounter;
+ struct pci_attach_args *pa = aux;
+ u_int64_t wa;
+
+ tc->tc_get_timecount = glxpcib_get_timecount;
+ tc->tc_counter_mask = 0xffffffff;
+ tc->tc_frequency = 3579545;
+ tc->tc_name = "CS5536";
+ tc->tc_quality = 1000;
+ tc->tc_priv = sc;
+ tc_init(tc);
+
+ printf(": rev %d, 32-bit %lluHz timer",
+ (int)rdmsr(AMD5536_REV) & AMD5536_REV_MASK,
+ tc->tc_frequency);
+
+ sc->sc_iot = pa->pa_iot;
+ wa = rdmsr(MSR_LBAR_MFGPT);
+ if (wa & 0x100000000ULL &&
+ !bus_space_map(sc->sc_iot, wa & 0xffff, 64, 0, &sc->sc_ioh)) {
+
+ /* count in seconds (as upper level desires) */
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP,
+ AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2EV |
+ AMD5536_MFGPT_CMP2 | AMD5536_MFGPT_DIV_MASK);
+ wdog_register(sc, glxpcib_wdogctl_cb);
+
+ printf(", watchdog");
+ }
+
+ pcibattach(parent, self, aux);
+}
+
+u_int
+glxpcib_get_timecount(struct timecounter *tc)
+{
+ return rdmsr(AMD5536_TMC);
+}
+
+int
+glxpcib_wdogctl_cb(void *v, int period)
+{
+ struct glxpcib_softc *sc = v;
+
+ if (period > 0xffff)
+ period = 0xffff;
+
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP,
+ AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2);
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_CNT, 0);
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_CMP2, period);
+
+ if (period)
+ wrmsr(AMD5536_MFGPT_NR,
+ rdmsr(AMD5536_MFGPT_NR) | AMD5536_MFGPT0_C2_RSTEN);
+ else
+ wrmsr(AMD5536_MFGPT_NR,
+ rdmsr(AMD5536_MFGPT_NR) & ~AMD5536_MFGPT0_C2_RSTEN);
+
+ return (period);
+}