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.c78
1 files changed, 40 insertions, 38 deletions
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 261790afd65b..0c14586f58d4 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -1,13 +1,13 @@
1/* cpwd.c - driver implementation for hardware watchdog 1/* cpwd.c - driver implementation for hardware watchdog
2 * timers found on Sun Microsystems CP1400 and CP1500 boards. 2 * timers found on Sun Microsystems CP1400 and CP1500 boards.
3 * 3 *
4 * This device supports both the generic Linux watchdog 4 * This device supports both the generic Linux watchdog
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)
@@ -43,8 +43,8 @@
43#define WD_BLIMIT 0xFFFF 43#define WD_BLIMIT 0xFFFF
44 44
45#define WD0_MINOR 212 45#define WD0_MINOR 212
46#define WD1_MINOR 213 46#define WD1_MINOR 213
47#define WD2_MINOR 214 47#define WD2_MINOR 214
48 48
49/* Internal driver definitions. */ 49/* Internal driver definitions. */
50#define WD0_ID 0 50#define WD0_ID 0
@@ -91,16 +91,16 @@ struct cpwd {
91 91
92static struct cpwd *cpwd_device; 92static struct cpwd *cpwd_device;
93 93
94/* Sun uses Altera PLD EPF8820ATC144-4 94/* Sun uses Altera PLD EPF8820ATC144-4
95 * providing three hardware watchdogs: 95 * providing three hardware watchdogs:
96 * 96 *
97 * 1) RIC - sends an interrupt when triggered 97 * 1) RIC - sends an interrupt when triggered
98 * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU 98 * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU
99 * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board 99 * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
100 * 100 *
101 *** Timer register block definition (struct wd_timer_regblk) 101 *** Timer register block definition (struct wd_timer_regblk)
102 * 102 *
103 * dcntr and limit registers (halfword access): 103 * dcntr and limit registers (halfword access):
104 * ------------------- 104 * -------------------
105 * | 15 | ...| 1 | 0 | 105 * | 15 | ...| 1 | 0 |
106 * ------------------- 106 * -------------------
@@ -108,7 +108,8 @@ static struct cpwd *cpwd_device;
108 * ------------------- 108 * -------------------
109 * dcntr - Current 16-bit downcounter value. 109 * dcntr - Current 16-bit downcounter value.
110 * When downcounter reaches '0' watchdog expires. 110 * When downcounter reaches '0' watchdog expires.
111 * Reading this register resets downcounter with 'limit' value. 111 * Reading this register resets downcounter with
112 * 'limit' value.
112 * limit - 16-bit countdown value in 1/10th second increments. 113 * limit - 16-bit countdown value in 1/10th second increments.
113 * Writing this register begins countdown with input value. 114 * Writing this register begins countdown with input value.
114 * Reading from this register does not affect counter. 115 * Reading from this register does not affect counter.
@@ -158,11 +159,11 @@ static int wd0_timeout = 0;
158static int wd1_timeout = 0; 159static int wd1_timeout = 0;
159static int wd2_timeout = 0; 160static int wd2_timeout = 0;
160 161
161module_param (wd0_timeout, int, 0); 162module_param(wd0_timeout, int, 0);
162MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); 163MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
163module_param (wd1_timeout, int, 0); 164module_param(wd1_timeout, int, 0);
164MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); 165MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
165module_param (wd2_timeout, int, 0); 166module_param(wd2_timeout, int, 0);
166MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); 167MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
167 168
168MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); 169MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
@@ -201,9 +202,9 @@ static u8 cpwd_readb(void __iomem *addr)
201static void cpwd_toggleintr(struct cpwd *p, int index, int enable) 202static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
202{ 203{
203 unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK); 204 unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK);
204 unsigned char setregs = 205 unsigned char setregs =
205 (index == -1) ? 206 (index == -1) ?
206 (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : 207 (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) :
207 (p->devs[index].intr_mask); 208 (p->devs[index].intr_mask);
208 209
209 if (enable == WD_INTR_ON) 210 if (enable == WD_INTR_ON)
@@ -303,24 +304,24 @@ static int cpwd_getstatus(struct cpwd *p, int index)
303 unsigned char ret = WD_STOPPED; 304 unsigned char ret = WD_STOPPED;
304 305
305 /* determine STOPPED */ 306 /* determine STOPPED */
306 if (!stat) 307 if (!stat)
307 return ret; 308 return ret;
308 309
309 /* determine EXPIRED vs FREERUN vs RUNNING */ 310 /* determine EXPIRED vs FREERUN vs RUNNING */
310 else if (WD_S_EXPIRED & stat) { 311 else if (WD_S_EXPIRED & stat) {
311 ret = WD_EXPIRED; 312 ret = WD_EXPIRED;
312 } else if(WD_S_RUNNING & stat) { 313 } else if (WD_S_RUNNING & stat) {
313 if (intr & p->devs[index].intr_mask) { 314 if (intr & p->devs[index].intr_mask) {
314 ret = WD_FREERUN; 315 ret = WD_FREERUN;
315 } else { 316 } else {
316 /* Fudge WD_EXPIRED status for defective CP1400-- 317 /* Fudge WD_EXPIRED status for defective CP1400--
317 * IF timer is running 318 * IF timer is running
318 * AND brokenstop is set 319 * AND brokenstop is set
319 * AND an interrupt has been serviced 320 * AND an interrupt has been serviced
320 * we are WD_EXPIRED. 321 * we are WD_EXPIRED.
321 * 322 *
322 * IF timer is running 323 * IF timer is running
323 * AND brokenstop is set 324 * AND brokenstop is set
324 * AND no interrupt has been serviced 325 * AND no interrupt has been serviced
325 * we are WD_FREERUN. 326 * we are WD_FREERUN.
326 */ 327 */
@@ -329,7 +330,8 @@ static int cpwd_getstatus(struct cpwd *p, int index)
329 if (p->devs[index].runstatus & WD_STAT_SVCD) { 330 if (p->devs[index].runstatus & WD_STAT_SVCD) {
330 ret = WD_EXPIRED; 331 ret = WD_EXPIRED;
331 } else { 332 } else {
332 /* we could as well pretend we are expired */ 333 /* we could as well pretend
334 * we are expired */
333 ret = WD_FREERUN; 335 ret = WD_FREERUN;
334 } 336 }
335 } else { 337 } else {
@@ -342,7 +344,7 @@ static int cpwd_getstatus(struct cpwd *p, int index)
342 if (p->devs[index].runstatus & WD_STAT_SVCD) 344 if (p->devs[index].runstatus & WD_STAT_SVCD)
343 ret |= WD_SERVICED; 345 ret |= WD_SERVICED;
344 346
345 return(ret); 347 return ret;
346} 348}
347 349
348static irqreturn_t cpwd_interrupt(int irq, void *dev_id) 350static irqreturn_t cpwd_interrupt(int irq, void *dev_id)
@@ -367,22 +369,22 @@ static int cpwd_open(struct inode *inode, struct file *f)
367 struct cpwd *p = cpwd_device; 369 struct cpwd *p = cpwd_device;
368 370
369 lock_kernel(); 371 lock_kernel();
370 switch(iminor(inode)) { 372 switch (iminor(inode)) {
371 case WD0_MINOR: 373 case WD0_MINOR:
372 case WD1_MINOR: 374 case WD1_MINOR:
373 case WD2_MINOR: 375 case WD2_MINOR:
374 break; 376 break;
375 377
376 default: 378 default:
377 unlock_kernel(); 379 unlock_kernel();
378 return -ENODEV; 380 return -ENODEV;
379 } 381 }
380 382
381 /* Register IRQ on first open of device */ 383 /* Register IRQ on first open of device */
382 if (!p->initialized) { 384 if (!p->initialized) {
383 if (request_irq(p->irq, &cpwd_interrupt, 385 if (request_irq(p->irq, &cpwd_interrupt,
384 IRQF_SHARED, DRIVER_NAME, p)) { 386 IRQF_SHARED, DRIVER_NAME, p)) {
385 printk(KERN_ERR PFX "Cannot register IRQ %d\n", 387 printk(KERN_ERR PFX "Cannot register IRQ %d\n",
386 p->irq); 388 p->irq);
387 unlock_kernel(); 389 unlock_kernel();
388 return -EBUSY; 390 return -EBUSY;
@@ -442,7 +444,7 @@ static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
442 cpwd_starttimer(p, index); 444 cpwd_starttimer(p, index);
443 } else { 445 } else {
444 return -EINVAL; 446 return -EINVAL;
445 } 447 }
446 break; 448 break;
447 449
448 /* Solaris-compatible IOCTLs */ 450 /* Solaris-compatible IOCTLs */
@@ -458,7 +460,7 @@ static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
458 460
459 case WIOCSTOP: 461 case WIOCSTOP:
460 if (p->enabled) 462 if (p->enabled)
461 return(-EINVAL); 463 return -EINVAL;
462 464
463 cpwd_stoptimer(p, index); 465 cpwd_stoptimer(p, index);
464 break; 466 break;
@@ -493,7 +495,7 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd,
493 return rval; 495 return rval;
494} 496}
495 497
496static ssize_t cpwd_write(struct file *file, const char __user *buf, 498static ssize_t cpwd_write(struct file *file, const char __user *buf,
497 size_t count, loff_t *ppos) 499 size_t count, loff_t *ppos)
498{ 500{
499 struct inode *inode = file->f_path.dentry->d_inode; 501 struct inode *inode = file->f_path.dentry->d_inode;
@@ -508,7 +510,7 @@ static ssize_t cpwd_write(struct file *file, const char __user *buf,
508 return 0; 510 return 0;
509} 511}
510 512
511static ssize_t cpwd_read(struct file * file, char __user *buffer, 513static ssize_t cpwd_read(struct file *file, char __user *buffer,
512 size_t count, loff_t *ppos) 514 size_t count, loff_t *ppos)
513{ 515{
514 return -EINVAL; 516 return -EINVAL;