aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/watchdog/sa1100_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/watchdog/sa1100_wdt.c')
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c53
1 files changed, 10 insertions, 43 deletions
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 34e8f7b15e30..fb88b4041dca 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -36,17 +36,10 @@
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37 37
38#define OSCR_FREQ CLOCK_TICK_RATE 38#define OSCR_FREQ CLOCK_TICK_RATE
39#define SA1100_CLOSE_MAGIC (0x5afc4453)
40 39
41static unsigned long sa1100wdt_users; 40static unsigned long sa1100wdt_users;
42static int expect_close;
43static int pre_margin; 41static int pre_margin;
44static int boot_status; 42static int boot_status;
45#ifdef CONFIG_WATCHDOG_NOWAYOUT
46static int nowayout = 1;
47#else
48static int nowayout = 0;
49#endif
50 43
51/* 44/*
52 * Allow only one person to hold it open 45 * Allow only one person to hold it open
@@ -66,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
66} 59}
67 60
68/* 61/*
69 * Shut off the timer. 62 * The watchdog cannot be disabled.
70 * Lock it in if it's a module and we defined ...NOWAYOUT 63 *
71 * Oddly, the watchdog can only be enabled, but we can turn off 64 * Previous comments suggested that turning off the interrupt by
72 * the interrupt, which appears to prevent the watchdog timing out. 65 * clearing OIER[E3] would prevent the watchdog timing out but this
66 * does not appear to be true (at least on the PXA255).
73 */ 67 */
74static int sa1100dog_release(struct inode *inode, struct file *file) 68static int sa1100dog_release(struct inode *inode, struct file *file)
75{ 69{
76 OSMR3 = OSCR + pre_margin; 70 printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
77
78 if (expect_close == SA1100_CLOSE_MAGIC) {
79 OIER &= ~OIER_E3;
80 } else {
81 printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n");
82 }
83 71
84 clear_bit(1, &sa1100wdt_users); 72 clear_bit(1, &sa1100wdt_users);
85 expect_close = 0;
86 73
87 return 0; 74 return 0;
88} 75}
89 76
90static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) 77static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
91{ 78{
92 if (len) { 79 if (len)
93 if (!nowayout) {
94 size_t i;
95
96 expect_close = 0;
97
98 for (i = 0; i != len; i++) {
99 char c;
100
101 if (get_user(c, data + i))
102 return -EFAULT;
103 if (c == 'V')
104 expect_close = SA1100_CLOSE_MAGIC;
105 }
106 }
107 /* Refresh OSMR3 timer. */ 80 /* Refresh OSMR3 timer. */
108 OSMR3 = OSCR + pre_margin; 81 OSMR3 = OSCR + pre_margin;
109 }
110 82
111 return len; 83 return len;
112} 84}
113 85
114static struct watchdog_info ident = { 86static struct watchdog_info ident = {
115 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | 87 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
116 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 88 .identity = "SA1100/PXA255 Watchdog",
117 .identity = "SA1100 Watchdog",
118}; 89};
119 90
120static int sa1100dog_ioctl(struct inode *inode, struct file *file, 91static int sa1100dog_ioctl(struct inode *inode, struct file *file,
@@ -176,7 +147,7 @@ static struct file_operations sa1100dog_fops =
176static struct miscdevice sa1100dog_miscdev = 147static struct miscdevice sa1100dog_miscdev =
177{ 148{
178 .minor = WATCHDOG_MINOR, 149 .minor = WATCHDOG_MINOR,
179 .name = "SA1100/PXA2xx watchdog", 150 .name = "watchdog",
180 .fops = &sa1100dog_fops, 151 .fops = &sa1100dog_fops,
181}; 152};
182 153
@@ -198,7 +169,6 @@ static int __init sa1100dog_init(void)
198 if (ret == 0) 169 if (ret == 0)
199 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", 170 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
200 margin); 171 margin);
201
202 return ret; 172 return ret;
203} 173}
204 174
@@ -216,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
216module_param(margin, int, 0); 186module_param(margin, int, 0);
217MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); 187MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
218 188
219module_param(nowayout, int, 0);
220MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
221
222MODULE_LICENSE("GPL"); 189MODULE_LICENSE("GPL");
223MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 190MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);