23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/module.h>
27 #include <linux/types.h>
29 #include <linux/watchdog.h>
32 #include <linux/pci.h>
41 #define TCO_VERSION "0.01"
42 #define TCO_MODULE_NAME "SP5100 TCO timer"
43 #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
46 static u32 tcobase_phys;
48 static unsigned int pm_iobase;
50 static unsigned long timer_alive;
51 static char tco_expect_close;
52 static struct pci_dev *sp5100_tco_pci;
59 #define WATCHDOG_HEARTBEAT 60
73 static void tco_timer_start(
void)
82 spin_unlock_irqrestore(&tco_lock, flags);
85 static void tco_timer_stop(
void)
94 spin_unlock_irqrestore(&tco_lock, flags);
97 static void tco_timer_keepalive(
void)
106 spin_unlock_irqrestore(&tco_lock, flags);
109 static int tco_timer_set_heartbeat(
int t)
113 if (t < 0 || t > 0xffff)
119 spin_unlock_irqrestore(&tco_lock, flags);
137 tco_timer_keepalive();
141 static int sp5100_tco_release(
struct inode *inode,
struct file *file)
144 if (tco_expect_close == 42) {
147 pr_crit(
"Unexpected close, not stopping watchdog!\n");
148 tco_timer_keepalive();
151 tco_expect_close = 0;
155 static ssize_t sp5100_tco_write(
struct file *file,
const char __user *
data,
156 size_t len, loff_t *ppos)
165 tco_expect_close = 0;
169 for (i = 0; i != len; i++) {
174 tco_expect_close = 42;
179 tco_timer_keepalive();
184 static long sp5100_tco_ioctl(
struct file *file,
unsigned int cmd,
195 .firmware_version = 0,
202 sizeof(ident)) ? -
EFAULT : 0;
215 tco_timer_keepalive();
220 tco_timer_keepalive();
225 if (tco_timer_set_heartbeat(new_heartbeat))
227 tco_timer_keepalive();
243 .write = sp5100_tco_write,
244 .unlocked_ioctl = sp5100_tco_ioctl,
245 .open = sp5100_tco_open,
246 .release = sp5100_tco_release,
249 static struct miscdevice sp5100_tco_miscdev = {
252 .fops = &sp5100_tco_fops,
274 static unsigned char __devinit sp5100_tco_setupdevice(
void)
282 sp5100_tco_pci =
dev;
293 pr_err(
"I/O address 0x%04x already in use\n", pm_iobase);
310 pr_err(
"mmio address 0x%04x already in use\n", val);
317 pr_err(
"failed to get tcobase address\n");
318 goto unreg_mem_region;
322 pci_read_config_dword(sp5100_tco_pci,
328 pci_write_config_dword(sp5100_tco_pci,
372 if (!sp5100_tco_setupdevice())
376 pr_info(
"Watchdog reboot %sdetected\n",
389 if (tco_timer_set_heartbeat(
heartbeat)) {
396 pr_err(
"cannot register miscdev on minor=%d (err=%d)\n",
403 pr_info(
"initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
415 static void __devexit sp5100_tco_cleanup(
void)
431 sp5100_tco_cleanup();
441 .probe = sp5100_tco_init,
443 .shutdown = sp5100_tco_shutdown,
450 static int __init sp5100_tco_init_module(
void)
460 sp5100_tco_platform_device = platform_device_register_simple(
462 if (IS_ERR(sp5100_tco_platform_device)) {
463 err = PTR_ERR(sp5100_tco_platform_device);
464 goto unreg_platform_driver;
469 unreg_platform_driver:
474 static void __exit sp5100_tco_cleanup_module(
void)
478 pr_info(
"SP5100 TCO Watchdog Module Unloaded\n");