Source
x
/*
* VIA Chipset Watchdog Driver
*
* Copyright (C) 2011 Sigfox
* License terms: GNU General Public License (GPL) version 2
* Author: Marc Vertes <marc.vertes@sigfox.com>
* Based on a preliminary version from Harald Welte <HaraldWelte@viatech.com>
* Timer code by Wim Van Sebroeck <wim@iguana.be>
*
* Caveat: PnP must be enabled in BIOS to allow full access to watchdog
* control registers. If not, the watchdog must be configured in BIOS manually.
*/
/* Configuration registers relative to the pci device */
/* MMIO region base address */
/* watchdog enable state */
/* Relevant bits for the VIA_WDT_CONF register */
/* 1: enable watchdog */
/* 1: enable watchdog MMIO */
/*
* The MMIO region contains the watchdog control register and the
* hardware timer counter.
*/
/* MMIO region length in bytes */
/* MMIO addr+0: state/control reg. */
/* MMIO addr+4: timer counter reg. */
/* Bits for the VIA_WDT_CTL register */
/* 0: stop, 1: running */
/* 1: restarted by expired watchdog */
/* 0: reset, 1: poweroff */
/* 1: timer is disabled */
/* 1: start a new countdown */
/* Hardware heartbeat in seconds */
/* Timer heartbeat (500ms) */
/* should be <= ((WDT_HW_HEARTBEAT*HZ)/2) */
/* User space timeout in seconds */
/* approx. 17 min. */
static int timeout = WDT_TIMEOUT;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, between 1 and 1023 "
"(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
"(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static struct watchdog_device wdt_dev;
static struct resource wdt_res;
static void __iomem *wdt_mem;
static unsigned int mmio;
static void wdt_timer_tick(struct timer_list *unused);
static DEFINE_TIMER(timer, wdt_timer_tick);
/* The timer that pings the watchdog */
static unsigned long next_heartbeat; /* the next_heartbeat for the timer */
static inline void wdt_reset(void)
{
unsigned int ctl = readl(wdt_mem);
writel(ctl | VIA_WDT_TRIGGER, wdt_mem);
}
/*
* Timer tick: the timer will make sure that the watchdog timer hardware
* is being reset in time. The conditions to do this are:
* 1) the watchdog timer has been started and /dev/watchdog is open
* and there is still time left before userspace should send the
* next heartbeat/ping. (note: the internal heartbeat is much smaller
* then the external/userspace heartbeat).
* 2) the watchdog timer has been stopped by userspace.
*/
static void wdt_timer_tick(struct timer_list *unused)
{