diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2005-05-02 17:26:01 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2005-05-02 17:26:01 +0000 |
commit | 6f535402cf6aa61d9045f193ea6def7850de777d (patch) | |
tree | 7bf138fa6cbf17e3ccca4fe8037b861c4a3827d3 /sys/dev/pci | |
parent | 1039653c9b3464c6b94b570416ee3a6ca79adc36 (diff) |
Add ichwdt(4): Intel 6300ESB ICH watchdog timer driver. Disabled for
now due to lack of testing. If you have a machine that uses this
device please contact me.
ok deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/ichwdt.c | 154 |
2 files changed, 160 insertions, 1 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 3b2396e487c..5f5fece1a16 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.174 2005/04/11 08:09:32 dlg Exp $ +# $OpenBSD: files.pci,v 1.175 2005/05/02 17:26:00 grange Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -530,3 +530,8 @@ file dev/pci/if_san_xilinx.c san device piixpm {} attach piixpm at pci file dev/pci/piixpm.c piixpm + +# Intel 6300ESB ICH watchdog timer +device ichwdt {} +attach ichwdt at pci +file dev/pci/ichwdt.c ichwdt diff --git a/sys/dev/pci/ichwdt.c b/sys/dev/pci/ichwdt.c new file mode 100644 index 00000000000..1d21195a7ae --- /dev/null +++ b/sys/dev/pci/ichwdt.c @@ -0,0 +1,154 @@ +/* $OpenBSD: ichwdt.c,v 1.1 2005/05/02 17:26:00 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * + * 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 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. + */ + +/* + * Intel 6300ESB ICH watchdog timer driver. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/pci/ichreg.h> + +#define ICHWDT_DEBUG + +#ifdef ICHWDT_DEBUG +#define DPRINTF(fmt, args...) printf(fmt, ##args) +#else +#define DPRINTF(fmt, args...) +#endif + +struct ichwdt_softc { + struct device sc_dev; + + pci_chipset_tag_t sc_pc; + pcitag_t sc_tag; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + int sc_enabled; + int sc_divisor; +}; + +int ichwdt_match(struct device *, void *, void *); +void ichwdt_attach(struct device *, struct device *, void *); + +int ichwdt_cb(void *, int); + +struct cfattach ichwdt_ca = { + sizeof(struct ichwdt_softc), + ichwdt_match, + ichwdt_attach +}; + +struct cfdriver ichwdt_cd = { + NULL, "ichwdt", DV_DULL +}; + +const struct pci_matchid ichwdt_devices[] = { + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_WDT } +}; + +static __inline void +ichwdt_unlock_write(struct ichwdt_softc *sc, int reg, u_int32_t val) +{ + /* Register unlocking sequence */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, ICH_WDT_RELOAD, 0x80); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, ICH_WDT_RELOAD, 0x86); + + /* Now it's possible to write to the register */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val); +} + +int +ichwdt_match(struct device *parent, void *match, void *aux) +{ + return (pci_matchbyid((struct pci_attach_args *)aux, ichwdt_devices, + sizeof(ichwdt_devices) / sizeof(ichwdt_devices[0]))); +} + +void +ichwdt_attach(struct device *parent, struct device *self, void *aux) +{ + struct ichwdt_softc *sc = (struct ichwdt_softc *)self; + struct pci_attach_args *pa = aux; + u_int32_t reg; + + sc->sc_pc = pa->pa_pc; + sc->sc_tag = pa->pa_tag; + + /* Map memory space */ + sc->sc_iot = pa->pa_iot; + if (pci_mapreg_map(pa, ICH_WDT_BASE, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) { + printf(": failed to map memory space\n"); + return; + } + + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ICH_WDT_CONF); + DPRINTF(": conf 0x%x", reg); + + /* Disable interrupts for now */ + reg &= ~ICH_WDT_CONF_INT_MASK; + reg |= ICH_WDT_CONF_INT_DIS; + + sc->sc_divisor = (reg & ICH_WDT_CONF_PRE ? 2 ^ 5 : 2 ^ 15); + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ICH_WDT_RELOAD); + if (reg & ICH_WDT_RELOAD_TIMEOUT) { + printf(": reboot on timeout"); + ichwdt_unlock_write(sc, ICH_WDT_RELOAD, reg); + } + + printf("\n"); + + /* Register new watchdog */ + wdog_register(sc, ichwdt_cb); +} + +int +ichwdt_cb(void *arg, int period) +{ + struct ichwdt_softc *sc = arg; + pcireg_t reg; + + if (period == 0) { + /* Disable watchdog timer */ + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ICH_WDT_LOCK); + reg &= ~ICH_WDT_LOCK_ENABLED; + pci_conf_write(sc->sc_pc, sc->sc_tag, ICH_WDT_LOCK, reg); + } else { + /* Reset watchdog timer */ + ichwdt_unlock_write(sc, ICH_WDT_PRE1, 1); + ichwdt_unlock_write(sc, ICH_WDT_PRE2, 1); + + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ICH_WDT_LOCK); + reg &= ~ICH_WDT_LOCK_FREERUN; + reg |= ICH_WDT_LOCK_ENABLED; + pci_conf_write(sc->sc_pc, sc->sc_tag, ICH_WDT_LOCK, reg); + } + + return (period); +} |