de966c86996069304325d112eab9c51094dffbf0
[openwrt.git] / target / linux / aruba-2.6 / files / drivers / char / watchdog / wdt_merlot.c
1 #include <linux/autoconf.h>
2 #include <linux/module.h>
3 #include <linux/types.h>
4 #include <linux/miscdevice.h>
5 #include <linux/watchdog.h>
6 #include <linux/fs.h>
7
8 #include <asm/io.h>
9 #include <asm/uaccess.h>
10 #include <asm/system.h>
11 #include <asm/bootinfo.h>
12
13 extern unsigned long mips_machtype;
14
15 static unsigned long wdt_is_open;
16 static struct timer_list wdt_timer;
17
18 static void wdt_merlot_refresh(void)
19 {
20     volatile __u32 *wdt;
21     switch (mips_machtype) {
22     case MACH_ARUBA_AP70:
23         wdt = (__u32 *) 0xb8030034;
24         *wdt = 0x10000000;
25         break;
26     default:
27         wdt = (__u32 *) 0xbc00300c;
28         *wdt = 0x40000000;
29         break;
30     }
31 }
32
33 static void wdt_merlot_timer_fn(unsigned long data)
34 {
35     wdt_merlot_refresh();
36     if (!test_bit(1, &wdt_is_open))
37         mod_timer(&wdt_timer, jiffies + HZ);
38 }
39
40 static int wdt_merlot_setup_timer(void)
41 {
42
43     init_timer(&wdt_timer);
44     wdt_timer.function = wdt_merlot_timer_fn;
45     wdt_timer.data = 0;
46     wdt_timer.expires = jiffies + HZ;
47     add_timer(&wdt_timer);
48     return 0;
49 }
50
51 static int wdt_open(struct inode *inode, struct file *file)
52 {
53     if (test_and_set_bit(0, &wdt_is_open))
54         return -EBUSY;
55     set_bit(1, &wdt_is_open);
56     return nonseekable_open(inode, file);
57 }
58
59 static ssize_t wdt_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos)
60 {
61     if (count)  /* something was written */
62         wdt_merlot_refresh();
63     return count;
64 }
65
66 static int wdt_release(struct inode *inode, struct file *file)
67 {
68     clear_bit(0, &wdt_is_open);
69     return 0;
70 }
71
72 static struct file_operations wdt_fops = {
73     .owner = THIS_MODULE,
74     .llseek = no_llseek,
75     .write = wdt_write,
76     .open = wdt_open,
77     .release = wdt_release,
78 };
79
80 static struct miscdevice wdt_miscdev = {
81     .minor = WATCHDOG_MINOR,
82     .name = "watchdog",
83     .fops = &wdt_fops,
84 };
85
86 static void __exit wdt_exit(void)
87 {
88     misc_deregister(&wdt_miscdev);
89 }
90
91 static int __init wdt_init(void)
92 {
93     int ret;
94     ret = misc_register(&wdt_miscdev);
95     if (ret) {
96         printk(KERN_ERR
97                "wdt: cannot register miscdev on minor=%d (err=%d)\n",
98                WATCHDOG_MINOR, ret);
99         misc_deregister(&wdt_miscdev);
100         goto out;
101     }
102     printk("wdt: registered with refresh\n");
103     wdt_merlot_refresh();
104     wdt_merlot_setup_timer();
105   out:
106     return ret;
107 }
108
109 module_init(wdt_init);
110 module_exit(wdt_exit);