diff options
Diffstat (limited to 'drivers/char/watchdog/at91_wdt.c')
-rw-r--r-- | drivers/char/watchdog/at91_wdt.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c index ac83bc4b019a..cc266715ea32 100644 --- a/drivers/char/watchdog/at91_wdt.c +++ b/drivers/char/watchdog/at91_wdt.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
14 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
@@ -17,14 +16,15 @@ | |||
17 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
22 | #include <asm/bitops.h> | 22 | #include <asm/bitops.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | 24 | ||
25 | 25 | ||
26 | #define WDT_DEFAULT_TIME 5 /* 5 seconds */ | 26 | #define WDT_DEFAULT_TIME 5 /* seconds */ |
27 | #define WDT_MAX_TIME 256 /* 256 seconds */ | 27 | #define WDT_MAX_TIME 256 /* seconds */ |
28 | 28 | ||
29 | static int wdt_time = WDT_DEFAULT_TIME; | 29 | static int wdt_time = WDT_DEFAULT_TIME; |
30 | static int nowayout = WATCHDOG_NOWAYOUT; | 30 | static int nowayout = WATCHDOG_NOWAYOUT; |
@@ -32,8 +32,10 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
32 | module_param(wdt_time, int, 0); | 32 | module_param(wdt_time, int, 0); |
33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | 33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); |
34 | 34 | ||
35 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
35 | module_param(nowayout, int, 0); | 36 | module_param(nowayout, int, 0); |
36 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 37 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
38 | #endif | ||
37 | 39 | ||
38 | 40 | ||
39 | static unsigned long at91wdt_busy; | 41 | static unsigned long at91wdt_busy; |
@@ -138,7 +140,7 @@ static int at91_wdt_ioctl(struct inode *inode, struct file *file, | |||
138 | case WDIOC_SETTIMEOUT: | 140 | case WDIOC_SETTIMEOUT: |
139 | if (get_user(new_value, p)) | 141 | if (get_user(new_value, p)) |
140 | return -EFAULT; | 142 | return -EFAULT; |
141 | 143 | ||
142 | if (at91_wdt_settimeout(new_value)) | 144 | if (at91_wdt_settimeout(new_value)) |
143 | return -EINVAL; | 145 | return -EINVAL; |
144 | 146 | ||
@@ -181,7 +183,7 @@ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, l | |||
181 | 183 | ||
182 | /* ......................................................................... */ | 184 | /* ......................................................................... */ |
183 | 185 | ||
184 | static struct file_operations at91wdt_fops = { | 186 | static const struct file_operations at91wdt_fops = { |
185 | .owner = THIS_MODULE, | 187 | .owner = THIS_MODULE, |
186 | .llseek = no_llseek, | 188 | .llseek = no_llseek, |
187 | .ioctl = at91_wdt_ioctl, | 189 | .ioctl = at91_wdt_ioctl, |
@@ -196,27 +198,84 @@ static struct miscdevice at91wdt_miscdev = { | |||
196 | .fops = &at91wdt_fops, | 198 | .fops = &at91wdt_fops, |
197 | }; | 199 | }; |
198 | 200 | ||
199 | static int __init at91_wdt_init(void) | 201 | static int __init at91wdt_probe(struct platform_device *pdev) |
200 | { | 202 | { |
201 | int res; | 203 | int res; |
202 | 204 | ||
203 | /* Check that the heartbeat value is within range; if not reset to the default */ | 205 | if (at91wdt_miscdev.dev) |
204 | if (at91_wdt_settimeout(wdt_time)) { | 206 | return -EBUSY; |
205 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | 207 | at91wdt_miscdev.dev = &pdev->dev; |
206 | printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
207 | } | ||
208 | 208 | ||
209 | res = misc_register(&at91wdt_miscdev); | 209 | res = misc_register(&at91wdt_miscdev); |
210 | if (res) | 210 | if (res) |
211 | return res; | 211 | return res; |
212 | 212 | ||
213 | printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout); | 213 | printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); |
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | static int __exit at91wdt_remove(struct platform_device *pdev) | ||
218 | { | ||
219 | int res; | ||
220 | |||
221 | res = misc_deregister(&at91wdt_miscdev); | ||
222 | if (!res) | ||
223 | at91wdt_miscdev.dev = NULL; | ||
224 | |||
225 | return res; | ||
226 | } | ||
227 | |||
228 | static void at91wdt_shutdown(struct platform_device *pdev) | ||
229 | { | ||
230 | at91_wdt_stop(); | ||
231 | } | ||
232 | |||
233 | #ifdef CONFIG_PM | ||
234 | |||
235 | static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) | ||
236 | { | ||
237 | at91_wdt_stop(); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int at91wdt_resume(struct platform_device *pdev) | ||
242 | { | ||
243 | if (at91wdt_busy) | ||
244 | at91_wdt_start(); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | #else | ||
249 | #define at91wdt_suspend NULL | ||
250 | #define at91wdt_resume NULL | ||
251 | #endif | ||
252 | |||
253 | static struct platform_driver at91wdt_driver = { | ||
254 | .probe = at91wdt_probe, | ||
255 | .remove = __exit_p(at91wdt_remove), | ||
256 | .shutdown = at91wdt_shutdown, | ||
257 | .suspend = at91wdt_suspend, | ||
258 | .resume = at91wdt_resume, | ||
259 | .driver = { | ||
260 | .name = "at91_wdt", | ||
261 | .owner = THIS_MODULE, | ||
262 | }, | ||
263 | }; | ||
264 | |||
265 | static int __init at91_wdt_init(void) | ||
266 | { | ||
267 | /* Check that the heartbeat value is within range; if not reset to the default */ | ||
268 | if (at91_wdt_settimeout(wdt_time)) { | ||
269 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | ||
270 | pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
271 | } | ||
272 | |||
273 | return platform_driver_register(&at91wdt_driver); | ||
274 | } | ||
275 | |||
217 | static void __exit at91_wdt_exit(void) | 276 | static void __exit at91_wdt_exit(void) |
218 | { | 277 | { |
219 | misc_deregister(&at91wdt_miscdev); | 278 | platform_driver_unregister(&at91wdt_driver); |
220 | } | 279 | } |
221 | 280 | ||
222 | module_init(at91_wdt_init); | 281 | module_init(at91_wdt_init); |