diff options
Diffstat (limited to 'drivers/watchdog/ar7_wdt.c')
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 107 |
1 files changed, 54 insertions, 53 deletions
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2f8643efe92c..2e94b71b20d9 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
@@ -28,9 +28,8 @@ | |||
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
31 | #include <linux/platform_device.h> | ||
31 | #include <linux/watchdog.h> | 32 | #include <linux/watchdog.h> |
32 | #include <linux/notifier.h> | ||
33 | #include <linux/reboot.h> | ||
34 | #include <linux/fs.h> | 33 | #include <linux/fs.h> |
35 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
36 | #include <linux/io.h> | 35 | #include <linux/io.h> |
@@ -76,24 +75,10 @@ static unsigned expect_close; | |||
76 | /* XXX currently fixed, allows max margin ~68.72 secs */ | 75 | /* XXX currently fixed, allows max margin ~68.72 secs */ |
77 | #define prescale_value 0xffff | 76 | #define prescale_value 0xffff |
78 | 77 | ||
79 | /* Offset of the WDT registers */ | 78 | /* Resource of the WDT registers */ |
80 | static unsigned long ar7_regs_wdt; | 79 | static struct resource *ar7_regs_wdt; |
81 | /* Pointer to the remapped WDT IO space */ | 80 | /* Pointer to the remapped WDT IO space */ |
82 | static struct ar7_wdt *ar7_wdt; | 81 | static struct ar7_wdt *ar7_wdt; |
83 | static void ar7_wdt_get_regs(void) | ||
84 | { | ||
85 | u16 chip_id = ar7_chip_id(); | ||
86 | switch (chip_id) { | ||
87 | case AR7_CHIP_7100: | ||
88 | case AR7_CHIP_7200: | ||
89 | ar7_regs_wdt = AR7_REGS_WDT; | ||
90 | break; | ||
91 | default: | ||
92 | ar7_regs_wdt = UR8_REGS_WDT; | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | 82 | ||
98 | static void ar7_wdt_kick(u32 value) | 83 | static void ar7_wdt_kick(u32 value) |
99 | { | 84 | { |
@@ -202,20 +187,6 @@ static int ar7_wdt_release(struct inode *inode, struct file *file) | |||
202 | return 0; | 187 | return 0; |
203 | } | 188 | } |
204 | 189 | ||
205 | static int ar7_wdt_notify_sys(struct notifier_block *this, | ||
206 | unsigned long code, void *unused) | ||
207 | { | ||
208 | if (code == SYS_HALT || code == SYS_POWER_OFF) | ||
209 | if (!nowayout) | ||
210 | ar7_wdt_disable_wdt(); | ||
211 | |||
212 | return NOTIFY_DONE; | ||
213 | } | ||
214 | |||
215 | static struct notifier_block ar7_wdt_notifier = { | ||
216 | .notifier_call = ar7_wdt_notify_sys, | ||
217 | }; | ||
218 | |||
219 | static ssize_t ar7_wdt_write(struct file *file, const char *data, | 190 | static ssize_t ar7_wdt_write(struct file *file, const char *data, |
220 | size_t len, loff_t *ppos) | 191 | size_t len, loff_t *ppos) |
221 | { | 192 | { |
@@ -299,56 +270,86 @@ static struct miscdevice ar7_wdt_miscdev = { | |||
299 | .fops = &ar7_wdt_fops, | 270 | .fops = &ar7_wdt_fops, |
300 | }; | 271 | }; |
301 | 272 | ||
302 | static int __init ar7_wdt_init(void) | 273 | static int __devinit ar7_wdt_probe(struct platform_device *pdev) |
303 | { | 274 | { |
304 | int rc; | 275 | int rc; |
305 | 276 | ||
306 | spin_lock_init(&wdt_lock); | 277 | spin_lock_init(&wdt_lock); |
307 | 278 | ||
308 | ar7_wdt_get_regs(); | 279 | ar7_regs_wdt = |
280 | platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | ||
281 | if (!ar7_regs_wdt) { | ||
282 | printk(KERN_ERR DRVNAME ": could not get registers resource\n"); | ||
283 | rc = -ENODEV; | ||
284 | goto out; | ||
285 | } | ||
309 | 286 | ||
310 | if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt), | 287 | if (!request_mem_region(ar7_regs_wdt->start, |
311 | LONGNAME)) { | 288 | resource_size(ar7_regs_wdt), LONGNAME)) { |
312 | printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n"); | 289 | printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n"); |
313 | return -EBUSY; | 290 | rc = -EBUSY; |
291 | goto out; | ||
314 | } | 292 | } |
315 | 293 | ||
316 | ar7_wdt = (struct ar7_wdt *) | 294 | ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); |
317 | ioremap(ar7_regs_wdt, sizeof(struct ar7_wdt)); | 295 | if (!ar7_wdt) { |
296 | printk(KERN_ERR DRVNAME ": could not ioremap registers\n"); | ||
297 | rc = -ENXIO; | ||
298 | goto out_mem_region; | ||
299 | } | ||
318 | 300 | ||
319 | ar7_wdt_disable_wdt(); | 301 | ar7_wdt_disable_wdt(); |
320 | ar7_wdt_prescale(prescale_value); | 302 | ar7_wdt_prescale(prescale_value); |
321 | ar7_wdt_update_margin(margin); | 303 | ar7_wdt_update_margin(margin); |
322 | 304 | ||
323 | rc = register_reboot_notifier(&ar7_wdt_notifier); | ||
324 | if (rc) { | ||
325 | printk(KERN_ERR DRVNAME | ||
326 | ": unable to register reboot notifier\n"); | ||
327 | goto out_alloc; | ||
328 | } | ||
329 | |||
330 | rc = misc_register(&ar7_wdt_miscdev); | 305 | rc = misc_register(&ar7_wdt_miscdev); |
331 | if (rc) { | 306 | if (rc) { |
332 | printk(KERN_ERR DRVNAME ": unable to register misc device\n"); | 307 | printk(KERN_ERR DRVNAME ": unable to register misc device\n"); |
333 | goto out_register; | 308 | goto out_alloc; |
334 | } | 309 | } |
335 | goto out; | 310 | goto out; |
336 | 311 | ||
337 | out_register: | ||
338 | unregister_reboot_notifier(&ar7_wdt_notifier); | ||
339 | out_alloc: | 312 | out_alloc: |
340 | iounmap(ar7_wdt); | 313 | iounmap(ar7_wdt); |
341 | release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt)); | 314 | out_mem_region: |
315 | release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); | ||
342 | out: | 316 | out: |
343 | return rc; | 317 | return rc; |
344 | } | 318 | } |
345 | 319 | ||
346 | static void __exit ar7_wdt_cleanup(void) | 320 | static int __devexit ar7_wdt_remove(struct platform_device *pdev) |
347 | { | 321 | { |
348 | misc_deregister(&ar7_wdt_miscdev); | 322 | misc_deregister(&ar7_wdt_miscdev); |
349 | unregister_reboot_notifier(&ar7_wdt_notifier); | ||
350 | iounmap(ar7_wdt); | 323 | iounmap(ar7_wdt); |
351 | release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt)); | 324 | release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); |
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void ar7_wdt_shutdown(struct platform_device *pdev) | ||
330 | { | ||
331 | if (!nowayout) | ||
332 | ar7_wdt_disable_wdt(); | ||
333 | } | ||
334 | |||
335 | static struct platform_driver ar7_wdt_driver = { | ||
336 | .probe = ar7_wdt_probe, | ||
337 | .remove = __devexit_p(ar7_wdt_remove), | ||
338 | .shutdown = ar7_wdt_shutdown, | ||
339 | .driver = { | ||
340 | .owner = THIS_MODULE, | ||
341 | .name = "ar7_wdt", | ||
342 | }, | ||
343 | }; | ||
344 | |||
345 | static int __init ar7_wdt_init(void) | ||
346 | { | ||
347 | return platform_driver_register(&ar7_wdt_driver); | ||
348 | } | ||
349 | |||
350 | static void __exit ar7_wdt_cleanup(void) | ||
351 | { | ||
352 | platform_driver_unregister(&ar7_wdt_driver); | ||
352 | } | 353 | } |
353 | 354 | ||
354 | module_init(ar7_wdt_init); | 355 | module_init(ar7_wdt_init); |