summaryrefslogtreecommitdiff
path: root/sys/arch/armv7/omap
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2013-11-01 12:15:16 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2013-11-01 12:15:16 +0000
commit780fae83f03e4c455691569099ffe05323f736f5 (patch)
tree51a8aefca620bacde30ec0d5cbdcf82bb9862403 /sys/arch/armv7/omap
parent718d72f40072cf944a13aec1040f917a66b4c72c (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.c134
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);
}