Author: gonzo
Date: Tue Oct 22 05:19:42 2013
New Revision: 256871
URL: http://svnweb.freebsd.org/changeset/base/256871

Log:
  - Implement watchdog function and register it with watchdog list

Modified:
  head/sys/arm/broadcom/bcm2835/bcm2835_wdog.c

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_wdog.c        Tue Oct 22 02:39:56 
2013        (r256870)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_wdog.c        Tue Oct 22 05:19:42 
2013        (r256871)
@@ -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()
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to