diff options
Diffstat (limited to 'drivers/watchdog/cpwd.c')
-rw-r--r-- | drivers/watchdog/cpwd.c | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 566343b3c131..1e013e8457b7 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c | |||
@@ -5,10 +5,10 @@ | |||
5 | * interface and Solaris-compatible ioctls as best it is | 5 | * interface and Solaris-compatible ioctls as best it is |
6 | * able. | 6 | * able. |
7 | * | 7 | * |
8 | * NOTE: CP1400 systems appear to have a defective intr_mask | 8 | * NOTE: CP1400 systems appear to have a defective intr_mask |
9 | * register on the PLD, preventing the disabling of | 9 | * register on the PLD, preventing the disabling of |
10 | * timer interrupts. We use a timer to periodically | 10 | * timer interrupts. We use a timer to periodically |
11 | * reset 'stopped' watchdogs on affected platforms. | 11 | * reset 'stopped' watchdogs on affected platforms. |
12 | * | 12 | * |
13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | 13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) |
14 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | 14 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> |
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/smp_lock.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
@@ -89,6 +89,7 @@ struct cpwd { | |||
89 | } devs[WD_NUMDEVS]; | 89 | } devs[WD_NUMDEVS]; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static DEFINE_MUTEX(cpwd_mutex); | ||
92 | static struct cpwd *cpwd_device; | 93 | static struct cpwd *cpwd_device; |
93 | 94 | ||
94 | /* Sun uses Altera PLD EPF8820ATC144-4 | 95 | /* Sun uses Altera PLD EPF8820ATC144-4 |
@@ -106,13 +107,13 @@ static struct cpwd *cpwd_device; | |||
106 | * ------------------- | 107 | * ------------------- |
107 | * |- counter val -| | 108 | * |- counter val -| |
108 | * ------------------- | 109 | * ------------------- |
109 | * dcntr - Current 16-bit downcounter value. | 110 | * dcntr - Current 16-bit downcounter value. |
110 | * When downcounter reaches '0' watchdog expires. | 111 | * When downcounter reaches '0' watchdog expires. |
111 | * Reading this register resets downcounter with | 112 | * Reading this register resets downcounter with |
112 | * 'limit' value. | 113 | * 'limit' value. |
113 | * limit - 16-bit countdown value in 1/10th second increments. | 114 | * limit - 16-bit countdown value in 1/10th second increments. |
114 | * Writing this register begins countdown with input value. | 115 | * Writing this register begins countdown with input value. |
115 | * Reading from this register does not affect counter. | 116 | * Reading from this register does not affect counter. |
116 | * NOTES: After watchdog reset, dcntr and limit contain '1' | 117 | * NOTES: After watchdog reset, dcntr and limit contain '1' |
117 | * | 118 | * |
118 | * status register (byte access): | 119 | * status register (byte access): |
@@ -122,7 +123,7 @@ static struct cpwd *cpwd_device; | |||
122 | * |- UNUSED -| EXP | RUN | | 123 | * |- UNUSED -| EXP | RUN | |
123 | * --------------------------- | 124 | * --------------------------- |
124 | * status- Bit 0 - Watchdog is running | 125 | * status- Bit 0 - Watchdog is running |
125 | * Bit 1 - Watchdog has expired | 126 | * Bit 1 - Watchdog has expired |
126 | * | 127 | * |
127 | *** PLD register block definition (struct wd_pld_regblk) | 128 | *** PLD register block definition (struct wd_pld_regblk) |
128 | * | 129 | * |
@@ -196,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr) | |||
196 | * Because of the CP1400 defect this should only be | 197 | * Because of the CP1400 defect this should only be |
197 | * called during initialzation or by wd_[start|stop]timer() | 198 | * called during initialzation or by wd_[start|stop]timer() |
198 | * | 199 | * |
199 | * index - sub-device index, or -1 for 'all' | 200 | * index - sub-device index, or -1 for 'all' |
200 | * enable - non-zero to enable interrupts, zero to disable | 201 | * enable - non-zero to enable interrupts, zero to disable |
201 | */ | 202 | */ |
202 | static void cpwd_toggleintr(struct cpwd *p, int index, int enable) | 203 | static void cpwd_toggleintr(struct cpwd *p, int index, int enable) |
@@ -316,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index) | |||
316 | } else { | 317 | } else { |
317 | /* Fudge WD_EXPIRED status for defective CP1400-- | 318 | /* Fudge WD_EXPIRED status for defective CP1400-- |
318 | * IF timer is running | 319 | * IF timer is running |
319 | * AND brokenstop is set | 320 | * AND brokenstop is set |
320 | * AND an interrupt has been serviced | 321 | * AND an interrupt has been serviced |
321 | * we are WD_EXPIRED. | 322 | * we are WD_EXPIRED. |
322 | * | 323 | * |
323 | * IF timer is running | 324 | * IF timer is running |
324 | * AND brokenstop is set | 325 | * AND brokenstop is set |
325 | * AND no interrupt has been serviced | 326 | * AND no interrupt has been serviced |
326 | * we are WD_FREERUN. | 327 | * we are WD_FREERUN. |
327 | */ | 328 | */ |
328 | if (p->broken && | 329 | if (p->broken && |
@@ -368,7 +369,7 @@ static int cpwd_open(struct inode *inode, struct file *f) | |||
368 | { | 369 | { |
369 | struct cpwd *p = cpwd_device; | 370 | struct cpwd *p = cpwd_device; |
370 | 371 | ||
371 | lock_kernel(); | 372 | mutex_lock(&cpwd_mutex); |
372 | switch (iminor(inode)) { | 373 | switch (iminor(inode)) { |
373 | case WD0_MINOR: | 374 | case WD0_MINOR: |
374 | case WD1_MINOR: | 375 | case WD1_MINOR: |
@@ -376,7 +377,7 @@ static int cpwd_open(struct inode *inode, struct file *f) | |||
376 | break; | 377 | break; |
377 | 378 | ||
378 | default: | 379 | default: |
379 | unlock_kernel(); | 380 | mutex_unlock(&cpwd_mutex); |
380 | return -ENODEV; | 381 | return -ENODEV; |
381 | } | 382 | } |
382 | 383 | ||
@@ -386,13 +387,13 @@ static int cpwd_open(struct inode *inode, struct file *f) | |||
386 | IRQF_SHARED, DRIVER_NAME, p)) { | 387 | IRQF_SHARED, DRIVER_NAME, p)) { |
387 | printk(KERN_ERR PFX "Cannot register IRQ %d\n", | 388 | printk(KERN_ERR PFX "Cannot register IRQ %d\n", |
388 | p->irq); | 389 | p->irq); |
389 | unlock_kernel(); | 390 | mutex_unlock(&cpwd_mutex); |
390 | return -EBUSY; | 391 | return -EBUSY; |
391 | } | 392 | } |
392 | p->initialized = true; | 393 | p->initialized = true; |
393 | } | 394 | } |
394 | 395 | ||
395 | unlock_kernel(); | 396 | mutex_unlock(&cpwd_mutex); |
396 | 397 | ||
397 | return nonseekable_open(inode, f); | 398 | return nonseekable_open(inode, f); |
398 | } | 399 | } |
@@ -482,9 +483,9 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, | |||
482 | case WIOCSTART: | 483 | case WIOCSTART: |
483 | case WIOCSTOP: | 484 | case WIOCSTOP: |
484 | case WIOCGSTAT: | 485 | case WIOCGSTAT: |
485 | lock_kernel(); | 486 | mutex_lock(&cpwd_mutex); |
486 | rval = cpwd_ioctl(file, cmd, arg); | 487 | rval = cpwd_ioctl(file, cmd, arg); |
487 | unlock_kernel(); | 488 | mutex_unlock(&cpwd_mutex); |
488 | break; | 489 | break; |
489 | 490 | ||
490 | /* everything else is handled by the generic compat layer */ | 491 | /* everything else is handled by the generic compat layer */ |
@@ -524,10 +525,10 @@ static const struct file_operations cpwd_fops = { | |||
524 | .write = cpwd_write, | 525 | .write = cpwd_write, |
525 | .read = cpwd_read, | 526 | .read = cpwd_read, |
526 | .release = cpwd_release, | 527 | .release = cpwd_release, |
528 | .llseek = no_llseek, | ||
527 | }; | 529 | }; |
528 | 530 | ||
529 | static int __devinit cpwd_probe(struct platform_device *op, | 531 | static int __devinit cpwd_probe(struct platform_device *op) |
530 | const struct of_device_id *match) | ||
531 | { | 532 | { |
532 | struct device_node *options; | 533 | struct device_node *options; |
533 | const char *str_prop; | 534 | const char *str_prop; |
@@ -612,7 +613,7 @@ static int __devinit cpwd_probe(struct platform_device *op, | |||
612 | 613 | ||
613 | if (p->broken) { | 614 | if (p->broken) { |
614 | init_timer(&cpwd_timer); | 615 | init_timer(&cpwd_timer); |
615 | cpwd_timer.function = cpwd_brokentimer; | 616 | cpwd_timer.function = cpwd_brokentimer; |
616 | cpwd_timer.data = (unsigned long) p; | 617 | cpwd_timer.data = (unsigned long) p; |
617 | cpwd_timer.expires = WD_BTIMEOUT; | 618 | cpwd_timer.expires = WD_BTIMEOUT; |
618 | 619 | ||
@@ -644,7 +645,7 @@ static int __devexit cpwd_remove(struct platform_device *op) | |||
644 | struct cpwd *p = dev_get_drvdata(&op->dev); | 645 | struct cpwd *p = dev_get_drvdata(&op->dev); |
645 | int i; | 646 | int i; |
646 | 647 | ||
647 | for (i = 0; i < 4; i++) { | 648 | for (i = 0; i < WD_NUMDEVS; i++) { |
648 | misc_deregister(&p->devs[i].misc); | 649 | misc_deregister(&p->devs[i].misc); |
649 | 650 | ||
650 | if (!p->enabled) { | 651 | if (!p->enabled) { |
@@ -676,7 +677,7 @@ static const struct of_device_id cpwd_match[] = { | |||
676 | }; | 677 | }; |
677 | MODULE_DEVICE_TABLE(of, cpwd_match); | 678 | MODULE_DEVICE_TABLE(of, cpwd_match); |
678 | 679 | ||
679 | static struct of_platform_driver cpwd_driver = { | 680 | static struct platform_driver cpwd_driver = { |
680 | .driver = { | 681 | .driver = { |
681 | .name = DRIVER_NAME, | 682 | .name = DRIVER_NAME, |
682 | .owner = THIS_MODULE, | 683 | .owner = THIS_MODULE, |
@@ -688,12 +689,12 @@ static struct of_platform_driver cpwd_driver = { | |||
688 | 689 | ||
689 | static int __init cpwd_init(void) | 690 | static int __init cpwd_init(void) |
690 | { | 691 | { |
691 | return of_register_platform_driver(&cpwd_driver); | 692 | return platform_driver_register(&cpwd_driver); |
692 | } | 693 | } |
693 | 694 | ||
694 | static void __exit cpwd_exit(void) | 695 | static void __exit cpwd_exit(void) |
695 | { | 696 | { |
696 | of_unregister_platform_driver(&cpwd_driver); | 697 | platform_driver_unregister(&cpwd_driver); |
697 | } | 698 | } |
698 | 699 | ||
699 | module_init(cpwd_init); | 700 | module_init(cpwd_init); |