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