aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/cpwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/cpwd.c')
-rw-r--r--drivers/watchdog/cpwd.c63
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
92static DEFINE_MUTEX(cpwd_mutex);
92static struct cpwd *cpwd_device; 93static 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 */
202static void cpwd_toggleintr(struct cpwd *p, int index, int enable) 203static 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
529static int __devinit cpwd_probe(struct platform_device *op, 531static 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};
677MODULE_DEVICE_TABLE(of, cpwd_match); 678MODULE_DEVICE_TABLE(of, cpwd_match);
678 679
679static struct of_platform_driver cpwd_driver = { 680static 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
689static int __init cpwd_init(void) 690static 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
694static void __exit cpwd_exit(void) 695static void __exit cpwd_exit(void)
695{ 696{
696 of_unregister_platform_driver(&cpwd_driver); 697 platform_driver_unregister(&cpwd_driver);
697} 698}
698 699
699module_init(cpwd_init); 700module_init(cpwd_init);