#include #include #include #include #include #include #include #include #include #include extern unsigned long mips_machtype; static unsigned long wdt_is_open; static struct timer_list wdt_timer; static void wdt_merlot_refresh(void) { volatile __u32 *wdt; switch (mips_machtype) { case MACH_ARUBA_AP70: wdt = (__u32 *) 0xb8030034; *wdt = 0x10000000; break; default: wdt = (__u32 *) 0xbc00300c; *wdt = 0x40000000; break; } } static void wdt_merlot_timer_fn(unsigned long data) { wdt_merlot_refresh(); if (!test_bit(1, &wdt_is_open)) mod_timer(&wdt_timer, jiffies + HZ); } static int wdt_merlot_setup_timer(void) { init_timer(&wdt_timer); wdt_timer.function = wdt_merlot_timer_fn; wdt_timer.data = 0; wdt_timer.expires = jiffies + HZ; add_timer(&wdt_timer); return 0; } static int wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &wdt_is_open)) return -EBUSY; set_bit(1, &wdt_is_open); return nonseekable_open(inode, file); } static ssize_t wdt_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos) { if (count) /* something was written */ wdt_merlot_refresh(); return count; } static int wdt_release(struct inode *inode, struct file *file) { clear_bit(0, &wdt_is_open); return 0; } static struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wdt_write, .open = wdt_open, .release = wdt_release, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static void __exit wdt_exit(void) { misc_deregister(&wdt_miscdev); } static int __init wdt_init(void) { int ret; ret = misc_register(&wdt_miscdev); if (ret) { printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); misc_deregister(&wdt_miscdev); goto out; } printk("wdt: registered with refresh\n"); wdt_merlot_refresh(); wdt_merlot_setup_timer(); out: return ret; } module_init(wdt_init); module_exit(wdt_exit);