diff options
author | Marc Balmer <mbalmer@cvs.openbsd.org> | 2007-10-07 13:41:49 +0000 |
---|---|---|
committer | Marc Balmer <mbalmer@cvs.openbsd.org> | 2007-10-07 13:41:49 +0000 |
commit | bde97fbac7941781ddaf7bffca8603f34869f84c (patch) | |
tree | fb0a8d00c605f503f49b1e45c92ba6cfa926d4ce /sys/arch | |
parent | 7d301fc0cffcf6885a1abd24bcc3402a6dd3e9ec (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/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 9 | ||||
-rw-r--r-- | sys/arch/i386/pci/glxpcib.c | 208 |
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); +} |