summaryrefslogtreecommitdiff
path: root/sys/dev/isa
diff options
context:
space:
mode:
authorMichael Knudsen <mk@cvs.openbsd.org>2009-03-25 20:41:32 +0000
committerMichael Knudsen <mk@cvs.openbsd.org>2009-03-25 20:41:32 +0000
commit632cb1a265894d5f3dccaa8e80410fde4f33c5a5 (patch)
tree4d4374b77fde377c10134d68c84e83bd292221ce /sys/dev/isa
parentefbfaaed2c7070538de119fea25ada30095496f1 (diff)
Add support for the watchdog timer.
``just have the balls and commit it'' deraadt
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/sch311x.c182
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;
+}
+