summaryrefslogtreecommitdiffstats
path: root/target/linux/aruba-2.6/files/drivers/char/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/aruba-2.6/files/drivers/char/watchdog')
-rw-r--r--target/linux/aruba-2.6/files/drivers/char/watchdog/wdt_merlot.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/target/linux/aruba-2.6/files/drivers/char/watchdog/wdt_merlot.c b/target/linux/aruba-2.6/files/drivers/char/watchdog/wdt_merlot.c
new file mode 100644
index 000000000..de966c869
--- /dev/null
+++ b/target/linux/aruba-2.6/files/drivers/char/watchdog/wdt_merlot.c
@@ -0,0 +1,110 @@
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+
+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);