Hi I have created a driver for the watchdog on the W83627HF. It would be very easy to support other Winbond watchdogs with this driver but I didnt bother to because I dont have access to any other chips. I have tested it on both the SuperMicro 5013G-M and 5015M-MT, and with OpenBSD 3.6, 4.0, and 4.1.
Thanks Jonathan Steel ===================== File: /sys/dev/isa/wbwdgvar.h ===================== /* * Copyright (c) 2007 Jonathan Steel <[EMAIL PROTECTED]> * * 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. */ /* Registers */ #define WBWDG_ADDR 0x00 #define WBWDG_DATA (WBWDG_ADDR + 1) #define WBWDG_LOGICAL_DEVICE 0x07 #define WBWDG_DEVID 0x20 #define WBWDG_DEVREV 0x21 /* Locial device 8 registers */ #define WBWDG_ENABLE 0x30 #define WBWDG_COUNT_METHOD 0xF3 #define WBWDG_MODE 0xF5 #define WBWDG_TIMEOUT 0xF6 /* Magic numbers */ #define WB_DEVID_W83627HF 0x52 #define WBWDG_ADDR_SIZE 0x02 #define WBWDG_ENTER_CONFIG_MODE 0x87 #define WBWDG_EXIT_CONFIG_MODE 0xAA #define WBWDG_DEV_WDG 0x08 #define WBWDG_MODE_MIN (1 << 3) #define WBWDG_MAX_TIMEOUT (0xFF * 60) struct wbwdg_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; /* If the timeout is in minutes or seconds */ int wdg_mode_sec; }; ===================== File: /sys/dev/isa/wbwdg.c ===================== /* * Copyright (c) 2007 Jonathan Steel <[EMAIL PROTECTED]> * * 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. */ /* * Winbond W83627HF watchdog driver. * Datasheet: * www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627HF_HGb.pdf */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <machine/bus.h> #include <sys/sensors.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <dev/isa/wbwdgvar.h> #ifdef WBWDG_DEBUG #define DPRINTF(x) printf x #else #define DPRINTF(x) #endif int winbond_wdg_match(struct device *, void *, void *); void winbond_wdg_attach(struct device *, struct device *, void *); void winbond_wdg_init(struct wbwdg_softc *sc); int winbond_wdg_cb(void *, int); struct cfattach wbwdg_ca = { sizeof(struct wbwdg_softc), winbond_wdg_match, winbond_wdg_attach }; struct cfdriver wbwdg_cd = { NULL, "wbwdg", DV_DULL }; static __inline void winbond_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh) { bus_space_write_1(iot, ioh, WBWDG_ADDR, WBWDG_ENTER_CONFIG_MODE); bus_space_write_1(iot, ioh, WBWDG_ADDR, WBWDG_ENTER_CONFIG_MODE); } static __inline void winbond_conf_disable(bus_space_tag_t iot, bus_space_handle_t ioh) { bus_space_write_1(iot, ioh, WBWDG_ADDR, WBWDG_EXIT_CONFIG_MODE); } static __inline u_int8_t winbond_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index) { bus_space_write_1(iot, ioh, WBWDG_ADDR, index); return (bus_space_read_1(iot, ioh, WBWDG_DATA)); } static __inline void winbond_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index, u_int8_t data) { bus_space_write_1(iot, ioh, WBWDG_ADDR, index); bus_space_write_1(iot, ioh, WBWDG_DATA, data); } int winbond_wdg_match(struct device *parent, void *match, void *aux) { struct isa_attach_args *ia = aux; bus_space_tag_t iot; bus_space_handle_t ioh; u_int8_t device_id; iot = ia->ia_iot; if (bus_space_map(iot, ia->ipa_io[0].base, WBWDG_ADDR_SIZE, 0, &ioh)) return (0); /* See if this machine has a compatible winbond chipset */ winbond_conf_enable(iot, ioh); device_id = winbond_conf_read(iot, ioh, WBWDG_DEVID); DPRINTF(("wbwdg_match: id 0x%02x\n", device_id)); winbond_conf_disable(iot, ioh); bus_space_unmap(iot, ioh, WBWDG_ADDR_SIZE); if (device_id == WB_DEVID_W83627HF) { DPRINTF(("W83627HF Watchdog\n")); } else { return (0); } ia->ipa_nio = 1; ia->ipa_io[0].length = WBWDG_ADDR_SIZE; ia->ipa_nmem = 0; ia->ipa_nirq = 0; ia->ipa_ndrq = 0; return (1); } void winbond_wdg_attach(struct device *parent, struct device *self, void *aux) { struct wbwdg_softc *sc = (void *)self; struct isa_attach_args *ia = aux; u_int8_t buf; sc->sc_iot = ia->ia_iot; if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base, WBWDG_ADDR_SIZE, 0, &sc->sc_ioh)) { printf(": can't map I/O space\n"); return; } /* Enter configuration mode */ winbond_conf_enable(sc->sc_iot, sc->sc_ioh); /* Read device id and revision */ buf = winbond_conf_read(sc->sc_iot, sc->sc_ioh, WBWDG_DEVID); if (buf == WB_DEVID_W83627HF) printf(": W83627HF : "); buf = winbond_conf_read(sc->sc_iot, sc->sc_ioh, WBWDG_DEVREV); printf("rev 0x%02x:", buf); /* Initialize logical devices */ winbond_wdg_init(sc); printf("\n"); /* Escape from configuration mode */ winbond_conf_disable(sc->sc_iot, sc->sc_ioh); return; } void winbond_wdg_init(struct wbwdg_softc *sc) { /* Select WDG logical device */ winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_LOGICAL_DEVICE, WBWDG_DEV_WDG); /* * Enable the timer. The default value of timeout is 0 which * means that the timeout is disabled */ winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_ENABLE, 1); sc->wdg_mode_sec = 0; wdog_register(sc, winbond_wdg_cb); return; } int winbond_wdg_cb(void *arg, int period) { struct wbwdg_softc *sc = arg; int chip_period; u_int8_t mode; if (period < 0) period = 0; else if (period > WBWDG_MAX_TIMEOUT) period = WBWDG_MAX_TIMEOUT; /* Setup the chip to talk to the watchdog device */ winbond_conf_enable(sc->sc_iot, sc->sc_ioh); winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_LOGICAL_DEVICE, WBWDG_DEV_WDG); /* Tell the device to read the timeout as either seconds or minutes */ if (sc->wdg_mode_sec && period > 0xFF) { sc->wdg_mode_sec = 0; mode = winbond_conf_read(sc->sc_iot, sc->sc_ioh, WBWDG_MODE); mode |= WBWDG_MODE_MIN; winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_MODE, mode); } else if (!sc->wdg_mode_sec && period <= 0xFF) { sc->wdg_mode_sec = 1; mode = winbond_conf_read(sc->sc_iot, sc->sc_ioh, WBWDG_MODE); mode &= ~WBWDG_MODE_MIN; winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_MODE, mode); } chip_period = period; /* Convert the period to minutes if necessary */ if (period > 0xFF) chip_period = period / 60; winbond_conf_write(sc->sc_iot, sc->sc_ioh, WBWDG_TIMEOUT, chip_period); winbond_conf_disable(sc->sc_iot, sc->sc_ioh); return (period); } ==================== Additions to GENERIC ==================== - Add the following in the section for the National Semiconductor drivers. wbwdt0 at isa? port 0x2e # Winbond W83627HF watchdog wbwdt1 at isa? port 0x4e ==================== Additions to /sys/dev/isa/lpt_isa ==================== - Again, add the following in the section for the National Semiconductor drivers. # Winbond w83627hf watchdog timer device wbwdg attach wbwdg at isa file dev/isa/wbwdg.c wbwdg