diff options
author | Michael Knudsen <mk@cvs.openbsd.org> | 2009-03-25 20:41:32 +0000 |
---|---|---|
committer | Michael Knudsen <mk@cvs.openbsd.org> | 2009-03-25 20:41:32 +0000 |
commit | 632cb1a265894d5f3dccaa8e80410fde4f33c5a5 (patch) | |
tree | 4d4374b77fde377c10134d68c84e83bd292221ce /sys/dev/isa/sch311x.c | |
parent | efbfaaed2c7070538de119fea25ada30095496f1 (diff) |
Add support for the watchdog timer.
``just have the balls and commit it'' deraadt
Diffstat (limited to 'sys/dev/isa/sch311x.c')
-rw-r--r-- | sys/dev/isa/sch311x.c | 182 |
1 files changed, 135 insertions, 47 deletions
diff --git a/sys/dev/isa/sch311x.c b/sys/dev/isa/sch311x.c index 733d0e62a03..c2ab4c4029a 100644 --- a/sys/dev/isa/sch311x.c +++ b/sys/dev/isa/sch311x.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sch311x.c,v 1.4 2009/01/26 15:07:49 kettenis Exp $ */ +/* $OpenBSD: sch311x.c,v 1.5 2009/03/25 20:41:31 mk Exp $ */ /* * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> * Copyright (c) 2009 Michael Knudsen <mk@openbsd.org> @@ -42,7 +42,7 @@ /* These are used in configuration mode */ #define SCHSIO_PORT_INDEX 0x00 -#define SCHSIO_PORT_DATA 0x01 +#define SCHSIO_PORT_DATA 0x01 #define SCHSIO_CONFIG_ENTER 0x55 #define SCHSIO_CONFIG_LEAVE 0xaa @@ -57,16 +57,16 @@ /* Logical devices */ #define SCHSIO_LDEV_RUNTIME 0x0a /* holds wdog and sensors */ - +#define SCHSIO_LDEV_RUNTIME_SZ 0x100 /* Hardware monitor */ #define SCHSIO_HWM_INTERVAL 5 /* seconds */ /* Register access */ -#define SCHSIO_HWM_IOSIZE 0x02 +#define SCHSIO_HWM_IOSIZE 0x100 #define SCHSIO_HWM_OFFSET 0x70 -#define SCHSIO_HWM_INDEX 0x00 -#define SCHSIO_HWM_DATA 0x01 +#define SCHSIO_HWM_INDEX 0x70 +#define SCHSIO_HWM_DATA 0x71 /* Sensor definitions */ /* Voltage */ @@ -124,11 +124,27 @@ #define SCHSIO_SENSOR_TEMP3 12 -#ifdef SCHSIO_DEBUG -#define DPRINTF(x) printf x -#else -#define DPRINTF(x) -#endif +/* Watchdog */ + +/* Register access */ +#define SCHSIO_WDT_GPIO 0x47 +#define SCHSIO_WDT_TIMEOUT 0x65 +#define SCHSIO_WDT_VAL 0x66 +#define SCHSIO_WDT_CFG 0x67 +#define SCHSIO_WDT_CTRL 0x68 + +/* Bits */ +#define SCHSIO_WDT_GPIO_MASK 0x0f +#define SCHSIO_WDT_GPIO_OUT 0x0e + +#define SCHSIO_WDT_TO_SECONDS (1 << 7) + +#define SCHSIO_WDT_CTRL_TRIGGERED (1 << 0) +#define SCHSIO_WDT_CFG_KBDEN (1 << 1) +#define SCHSIO_WDT_CFG_MSEN (1 << 2) + +/* autoconf(9) flags etc. */ +#define SCHSIO_CFFLAGS_WDTEN (1 << 0) #define DEVNAME(x) ((x)->sc_dev.dv_xname) @@ -138,7 +154,7 @@ struct schsio_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - bus_space_handle_t sc_hwm_ioh; + bus_space_handle_t sc_ioh_rr; struct ksensordev sc_sensordev; struct ksensor sc_sensor[SCHSIO_SENSORS]; @@ -161,9 +177,12 @@ void schsio_config_write(bus_space_tag_t iot, /* HWM prototypes */ void schsio_hwm_init(struct schsio_softc *sc); void schsio_hwm_update(void *arg); - u_int8_t schsio_hwm_read(struct schsio_softc *sc, int reg); +/* Watchdog prototypes */ + +void schsio_wdt_init(struct schsio_softc *sc); +int schsio_wdt_cb(void *arg, int period); struct cfattach schsio_ca = { sizeof(struct schsio_softc), @@ -243,7 +262,8 @@ schsio_attach(struct device *parent, struct device *self, void *aux) { struct schsio_softc *sc = (void *)self; struct isa_attach_args *ia = aux; - u_int8_t reg; + u_int16_t iobase; + u_int8_t reg0, reg1; /* Map ISA I/O space */ sc->sc_iot = ia->ia_iot; @@ -257,8 +277,8 @@ schsio_attach(struct device *parent, struct device *self, void *aux) schsio_config_enable(sc->sc_iot, sc->sc_ioh); /* Read device ID */ - reg = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_DEVICE); - switch (reg) { + reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_DEVICE); + switch (reg0) { case SCHSIO_ID_SCH3112: printf(": SCH3112"); break; @@ -271,9 +291,27 @@ schsio_attach(struct device *parent, struct device *self, void *aux) } /* Read device revision */ - reg = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_REV); - printf(" rev 0x%02x", reg); + reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_REV); + printf(" rev 0x%02x", reg0); + + /* Select runtime registers logical device */ + schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL, + SCHSIO_LDEV_RUNTIME); + + reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, + SCHSIO_IDX_BASE_HI); + reg1 = schsio_config_read(sc->sc_iot, sc->sc_ioh, + SCHSIO_IDX_BASE_LO); + iobase = (reg0 << 8) | reg1; + if (bus_space_map(sc->sc_iot, iobase, SCHSIO_LDEV_RUNTIME_SZ, + 0, &sc->sc_ioh_rr)) { + printf(": can't map I/O space\n"); + return; + } + + + schsio_wdt_init(sc); schsio_hwm_init(sc); printf("\n"); @@ -287,25 +325,6 @@ void schsio_hwm_init(struct schsio_softc *sc) { int i; - u_int16_t iobase; - u_int8_t reg0, reg1; - - /* Select runtime registers logical device */ - schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL, - SCHSIO_LDEV_RUNTIME); - - reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, - SCHSIO_IDX_BASE_HI); - reg1 = schsio_config_read(sc->sc_iot, sc->sc_ioh, - SCHSIO_IDX_BASE_LO); - iobase = ((reg0 << 8) | reg1) + SCHSIO_HWM_OFFSET; - - - if (bus_space_map(sc->sc_iot, iobase, - SCHSIO_HWM_IOSIZE, 0, &sc->sc_hwm_ioh)) { - printf(": can't map I/O space\n"); - return; - } /* Set up sensors */ for (i = SCHSIO_SENSOR_FAN1; i < SCHSIO_SENSOR_FAN3 + 1; i++) @@ -362,12 +381,6 @@ schsio_hwm_update(void *arg) sc = (struct schsio_softc *)arg; - schsio_config_enable(sc->sc_iot, sc->sc_ioh); - - /* Select logical device a */ - schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL, - SCHSIO_LDEV_RUNTIME); - reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_L); reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_U); tach = (reg1 << 8) | reg0; @@ -432,13 +445,88 @@ schsio_hwm_update(void *arg) sc->sc_sensor[SCHSIO_SENSOR_TEMP3].flags = ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0; - schsio_config_disable(sc->sc_iot, sc->sc_ioh); - } u_int8_t schsio_hwm_read(struct schsio_softc *sc, int reg) { - bus_space_write_1(sc->sc_iot, sc->sc_hwm_ioh, SCHSIO_HWM_INDEX, reg); - return (bus_space_read_1(sc->sc_iot, sc->sc_hwm_ioh, SCHSIO_HWM_DATA)); + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_INDEX, reg); + return (bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_DATA)); } + +void +schsio_wdt_init(struct schsio_softc *sc) +{ + u_int8_t reg; + + reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO); + if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) { + if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) { + reg &= ~0x0f; + reg |= SCHSIO_WDT_GPIO_OUT; + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, + SCHSIO_WDT_GPIO, reg); + } + else { + printf(", watchdog disabled"); + return; + } + } + + /* First of all, make sure the wdt is disabled */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0); + + /* Clear triggered status */ + reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, + SCHSIO_WDT_CTRL); + if (reg & SCHSIO_WDT_CTRL_TRIGGERED) { + printf(", warning: watchdog triggered"); + reg &= ~SCHSIO_WDT_CTRL_TRIGGERED; + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, + SCHSIO_WDT_CTRL, reg); + } + + /* Disable wdt reset by mouse and kbd */ + reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG); + reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_MSEN); + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg); + + wdog_register(sc, schsio_wdt_cb); +} + +int +schsio_wdt_cb(void *arg, int period) +{ + struct schsio_softc *sc; + uint8_t val, minute, reg; + + sc = (struct schsio_softc *)arg; + + if (period > 255) { + val = period / 60; + minute = 1; + } else { + val = period; + minute = 0; + } + + /* Set unit */ + reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, + SCHSIO_WDT_TIMEOUT); + if (!minute) + reg |= SCHSIO_WDT_TO_SECONDS; + else + reg &= ~SCHSIO_WDT_TO_SECONDS; + + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_TIMEOUT, + reg); + + /* Set value */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, val); + + if (!minute) + return val; + else + return val * 60; +} + |