diff options
author | gonzo <gonzo@FreeBSD.org> | 2013-10-22 05:19:42 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2013-10-22 05:19:42 +0000 |
commit | 10d2c4a76670d6817f4a18a0f2b36c436fc44c11 (patch) | |
tree | eccb716445ac35d500f4ef0d6c333a96c39461d8 /sys | |
parent | df85c26ef500ddf5fecdf28d80e5d9a7c8b2bd9c (diff) | |
download | FreeBSD-src-10d2c4a76670d6817f4a18a0f2b36c436fc44c11.zip FreeBSD-src-10d2c4a76670d6817f4a18a0f2b36c436fc44c11.tar.gz |
- Implement watchdog function and register it with watchdog list
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arm/broadcom/bcm2835/bcm2835_wdog.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c index c8570cb..fbe3bed 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c @@ -76,11 +76,10 @@ struct bcmwd_softc { int wdog_armed; int wdog_period; char wdog_passwd; + struct mtx mtx; }; -#ifdef notyet static void bcmwd_watchdog_fn(void *private, u_int cmd, int *error); -#endif static int bcmwd_probe(device_t dev) @@ -120,19 +119,59 @@ bcmwd_attach(device_t dev) sc->bsh = rman_get_bushandle(sc->res); bcmwd_lsc = sc; -#ifdef notyet + mtx_init(&sc->mtx, "BCM2835 Watchdog", "bcmwd", MTX_DEF); EVENTHANDLER_REGISTER(watchdog_list, bcmwd_watchdog_fn, sc, 0); -#endif + return (0); } -#ifdef notyet static void bcmwd_watchdog_fn(void *private, u_int cmd, int *error) { - /* XXX: not yet */ + struct bcmwd_softc *sc; + uint64_t sec; + uint32_t ticks, reg; + + sc = private; + mtx_lock(&sc->mtx); + + cmd &= WD_INTERVAL; + + if (cmd > 0) { + sec = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000000; + ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK; + if (ticks == 0) { + /* + * Can't arm + * disable watchdog as watchdog(9) requires + */ + device_printf(sc->dev, + "Can't arm, timeout is less than 1 second\n"); + WRITE(sc, BCM2835_RSTC_REG, + (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) | + BCM2835_RSTC_RESET); + mtx_unlock(&sc->mtx); + return; + } + + reg = (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) | ticks; + WRITE(sc, BCM2835_WDOG_REG, reg); + + reg = READ(sc, BCM2835_RSTC_REG); + reg &= BCM2835_RSTC_WRCFG_CLR; + reg |= BCM2835_RSTC_WRCFG_FULL_RESET; + reg |= (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT); + WRITE(sc, BCM2835_RSTC_REG, reg); + + *error = 0; + } + else + WRITE(sc, BCM2835_RSTC_REG, + (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) | + BCM2835_RSTC_RESET); + + mtx_unlock(&sc->mtx); } -#endif void bcmwd_watchdog_reset() |