Date: Mon, 7 Aug 2006 19:54:06 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 103394 for review Message-ID: <200608071954.k77Js6aS057291@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103394 Change 103394 by imp@imp_bugs on 2006/08/07 19:53:09 implement actual watchdog device, when present. This implementation stretches the spec a little to match the #defines in sys/watchdog.h. I think this is acceptible given the size constraints of the kernel and how watchdogs are generally used. Likely not a big deal either way... Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_st.c#12 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_st.c#12 (text+ko) ==== @@ -34,6 +34,7 @@ #include <sys/resource.h> #include <sys/rman.h> #include <sys/timetc.h> +#include <sys/watchdog.h> #include <machine/bus.h> #include <machine/cpu.h> @@ -48,7 +49,8 @@ static struct at91st_softc { bus_space_tag_t sc_st; bus_space_handle_t sc_sh; - device_t dev; + device_t sc_dev; + eventhandler_tag sc_wet; /* watchdog event handler tag */ } *timer_softc; #define RD4(off) \ @@ -56,6 +58,8 @@ #define WR4(off, val) \ bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, (off), (val)) +static watchdog_fn at91st_watchdog; + static inline int st_crtr(void) { @@ -97,7 +101,7 @@ timer_softc = device_get_softc(dev); timer_softc->sc_st = sc->sc_st; - timer_softc->dev = dev; + timer_softc->sc_dev = dev; if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_ST_BASE, AT91RM92_ST_SIZE, &timer_softc->sc_sh) != 0) panic("couldn't subregion timer registers"); @@ -110,6 +114,11 @@ WR4(ST_IDR, 0xffffffff); /* disable watchdog timer */ WR4(ST_WDMR, 0); + + timer_softc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list, + at91st_watchdog, dev, 0); + device_printf(dev, + "watchdog registered, timeout intervall max. 64 sec\n"); return (0); } @@ -142,7 +151,34 @@ #endif } +/* + * t below is in a weird unit. The watchdog is set to 2^t + * nanoseconds. Since our watchdog timer can't really do that too + * well, we approximate it by assuming that the timeout interval for + * the lsb is 2^22 ns, which is 4.194ms. This is an overestimation of + * the actual time (3.906ms), but close enough for watchdogging. + * These approximations, though a violation of the spec, improve the + * performance of the application which typically specifies things as + * WD_TO_32SEC. In that last case, we'd wait 32s before the wdog + * reset. The spec says we should wait closer to 34s, but given how + * it is likely to be used, and the extremely coarse nature time + * interval, I think this is the best solution. + */ static void +at91st_watchdog(void *argp, u_int cmd, int *error) +{ + uint32_t wdog; + int t; + + wdog = 0; + t = cmd & WD_INTERVAL; + if (cmd != 0 && t >= 22 && t <= 37) + wdog = (1 << (t - 22)) | ST_WDMR_RSTEN; + WR4(ST_WDMR, wdog); + WR4(ST_CR, ST_CR_WDRST); +} + +static void clock_intr(void *arg) { struct trapframe *fp = arg; @@ -163,7 +199,7 @@ struct resource *irq; int rid = 0; void *ih; - device_t dev = timer_softc->dev; + device_t dev = timer_softc->sc_dev; if (32768 % hz) { printf("Cannot get %d Hz clock; using 128Hz\n", hz); @@ -231,4 +267,3 @@ cpu_stopprofclock(void) { } -
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608071954.k77Js6aS057291>