diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2013-11-01 12:15:16 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2013-11-01 12:15:16 +0000 |
commit | 780fae83f03e4c455691569099ffe05323f736f5 (patch) | |
tree | 51a8aefca620bacde30ec0d5cbdcf82bb9862403 /sys/arch/armv7/omap | |
parent | 718d72f40072cf944a13aec1040f917a66b4c72c (diff) |
rewrite omdog somewhat and hook it into the watchdog framework.
tested by syl@ and myself. syl@ ok.
Diffstat (limited to 'sys/arch/armv7/omap')
-rw-r--r-- | sys/arch/armv7/omap/omdog.c | 134 |
1 files changed, 97 insertions, 37 deletions
diff --git a/sys/arch/armv7/omap/omdog.c b/sys/arch/armv7/omap/omdog.c index 73bbc73391a..f84be92a334 100644 --- a/sys/arch/armv7/omap/omdog.c +++ b/sys/arch/armv7/omap/omdog.c @@ -1,5 +1,6 @@ -/* $OpenBSD: omdog.c,v 1.1 2013/09/04 14:38:31 patrick Exp $ */ +/* $OpenBSD: omdog.c,v 1.2 2013/11/01 12:15:15 fgsch Exp $ */ /* + * Copyright (c) 2013 Federico G. Schwindt <fgsch@openbsd.org> * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any @@ -26,38 +27,41 @@ #include <machine/intr.h> #include <machine/bus.h> #include <armv7/omap/omapvar.h> -#include <armv7/omap/omgpiovar.h> - -/* registers */ -#define WIDR 0x00 -#define WD_SYSCONFIG 0x10 -#define WD_SYSSTATUS 0x14 -#define WISR 0x18 -#define WIER 0x1C -#define WCLR 0x24 -#define WCRR 0x28 -#define WLDR 0x2C -#define WTGR 0x30 -#define WWPS 0x34 -#define WWPS_PEND_ALL 0x1f -#define WSPR 0x48 + +#define WIDR 0x00 /* Identification Register */ +#define WCLR 0x24 /* Control Register */ +#define WCLR_PRE (1 << 5) +#define WCLR_PTV (0 << 2) +#define WCRR 0x28 /* Counter Register */ +#define WLDR 0x2c /* Load Register */ +#define WTGR 0x30 /* Trigger Register */ +#define WWPS 0x34 /* Write Posting Bits Reg. */ +#define WWPS_WSPR (1 << 4) +#define WWPS_WTGR (1 << 3) +#define WWPS_WLDR (1 << 2) +#define WWPS_WCRR (1 << 1) +#define WWPS_WCLR (1 << 0) +#define WSPR 0x48 /* Start/Stop Register */ + +#define OMDOG_VAL(secs) (0xffffffff - ((secs) * (32768 / (1 << 0))) + 1) struct omdog_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + + int sc_period; }; struct omdog_softc *omdog_sc; -/* - * to enable the watchdog, write 0xXXXXbbbb then 0xXXXX4444 to WSPR - * to disable the watchdog, write 0xXXXXaaaa then 0xXXXX5555 to WSPR - */ - -void omdog_attach(struct device *parent, struct device *self, void *args); -void omdog_wpending(int flags); +void omdog_attach(struct device *, struct device *, void *); +void omdog_start(struct omdog_softc *); +void omdog_stop(struct omdog_softc *); +void omdog_sync(struct omdog_softc *); +int omdog_cb(void *, int); +void omdog_reset(void); struct cfattach omdog_ca = { sizeof (struct omdog_softc), NULL, omdog_attach @@ -77,37 +81,93 @@ omdog_attach(struct device *parent, struct device *self, void *args) sc->sc_iot = oa->oa_iot; if (bus_space_map(sc->sc_iot, oa->oa_dev->mem[0].addr, oa->oa_dev->mem[0].size, 0, &sc->sc_ioh)) - panic("gptimer_attach: bus_space_map failed!"); + panic("%s: bus_space_map failed!", __func__); rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR); printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf); omdog_sc = sc; + + omdog_stop(sc); + + wdog_register(omdog_cb, sc); } void -omdog_wpending(int flags) +omdog_start(struct omdog_softc *sc) { - struct omdog_softc *sc = omdog_sc; - while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, WWPS) & flags) - ; + /* Write the enable sequence data BBBBh followed by 4444h */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xbbbb); + omdog_sync(sc); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x4444); + omdog_sync(sc); } -void omdog_reset(void); /* XXX */ +void +omdog_stop(struct omdog_softc *sc) +{ + /* Write the disable sequence data AAAAh followed by 5555h */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xaaaa); + omdog_sync(sc); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x5555); + omdog_sync(sc); +} void -omdog_reset() +omdog_sync(struct omdog_softc *sc) +{ + while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, WWPS) & + (WWPS_WSPR|WWPS_WTGR|WWPS_WLDR|WWPS_WCRR|WWPS_WCLR)) + delay(10); +} + +int +omdog_cb(void *self, int period) +{ + struct omdog_softc *sc = self; + + if (sc->sc_period != 0 && sc->sc_period != period) + omdog_stop(sc); + + if (period != 0) { + if (sc->sc_period != period) { + /* Set the prescaler */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WCLR, + (WCLR_PRE|WCLR_PTV)); + + /* Set the reload counter */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WLDR, + OMDOG_VAL(period)); + } + + omdog_sync(sc); + + /* Trigger the reload */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, WTGR, + ~bus_space_read_4(sc->sc_iot, sc->sc_ioh, WTGR)); + + if (sc->sc_period != period) + omdog_start(sc); + } + + sc->sc_period = period; + + return (period); +} + +void +omdog_reset(void) { if (omdog_sc == NULL) return; - bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WCRR, 0xffffff80); - omdog_wpending(WWPS_PEND_ALL); + if (omdog_sc->sc_period != 0) + omdog_stop(omdog_sc); + + bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WCRR, + 0xffffff80); + + omdog_start(omdog_sc); - /* this sequence will start the watchdog. */ - bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WSPR, 0xbbbb); - omdog_wpending(WWPS_PEND_ALL); - bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WSPR, 0x4444); - omdog_wpending(WWPS_PEND_ALL); delay(100000); } |