diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-02-28 22:33:28 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-02-28 22:33:28 +0000 |
commit | 961af6677bda00818b01a9facec086b5c07e8af6 (patch) | |
tree | 2b8983be56ed8514c852e4e993f0d81519db45f1 /sys/i386/i386/geode.c | |
parent | 3d6e5ccb062a34f83ec0883e510bf6cef349fe82 (diff) | |
download | src-961af6677bda00818b01a9facec086b5c07e8af6.tar.gz src-961af6677bda00818b01a9facec086b5c07e8af6.zip |
Add support for the watchdog in Geode SC1100 which is used in embedded
systems like the Soekris NET4801
Notes
Notes:
svn path=/head/; revision=126387
Diffstat (limited to 'sys/i386/i386/geode.c')
-rw-r--r-- | sys/i386/i386/geode.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/sys/i386/i386/geode.c b/sys/i386/i386/geode.c index e6b571151a9c..eb6a037de8b0 100644 --- a/sys/i386/i386/geode.c +++ b/sys/i386/i386/geode.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/timetc.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/watchdog.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -77,6 +78,39 @@ static struct timecounter geode_timecounter = { 1000 }; +/* + * The GEODE watchdog runs from a 32kHz frequency. One period of that is + * 31250 nanoseconds which we round down to 2^14 nanoseconds. The watchdog + * consists of a power-of-two prescaler and a 16 bit counter, so the math + * is quite simple. The max timeout is 14 + 16 + 13 = 2^43 nsec ~= 2h26m. + */ +static void +geode_watchdog(void *foo __unused, u_int cmd, int *error) +{ + u_int u, p, r; + + u = cmd & WD_INTERVAL; + if (cmd && u >= 14 && u <= 43) { + u -= 14; + if (u > 16) { + p = u - 16; + u -= p; + } else { + p = 0; + } + if (u == 16) + u = (1 << u) - 1; + else + u = 1 << u; + r = inw(cba + 2) & 0xff00; + outw(cba + 2, p | 0xf0 | r); + outw(cba, u); + *error = 0; + } else { + outw(cba, 0); + } +} + static int geode_probe(device_t self) { @@ -94,6 +128,8 @@ geode_probe(device_t self) printf("Geode rev: %02x %02x\n", inb(cba + 0x3c), inb(cba + 0x3d)); tc_init(&geode_timecounter); + EVENTHANDLER_REGISTER(watchdog_list, geode_watchdog, + NULL, 0); } } else if (pci_get_devid(self) == 0x0510100b) { gpio = pci_read_config(self, PCIR_BAR(0), 4); |