Lines Matching +full:watchdog +full:- +full:enable
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* cpwd.c - driver implementation for hardware watchdog
5 * This device supports both the generic Linux watchdog
6 * interface and Solaris-compatible ioctls as best it is
38 #include <asm/watchdog.h>
42 #define WD_OBPNAME "watchdog"
43 #define WD_BADMODEL "SUNW,501-5336"
60 #define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */
61 #define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */
62 #define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */
66 #define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */
70 #define WD_S_RUNNING 0x01 /* Watchdog device status running */
71 #define WD_S_EXPIRED 0x02 /* Watchdog device status expired */
97 /* Sun uses Altera PLD EPF8820ATC144-4
100 * 1) RIC - sends an interrupt when triggered
101 * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU
102 * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
107 * -------------------
109 * -------------------
110 * |- counter val -|
111 * -------------------
112 * dcntr - Current 16-bit downcounter value.
113 * When downcounter reaches '0' watchdog expires.
116 * limit - 16-bit countdown value in 1/10th second increments.
119 * NOTES: After watchdog reset, dcntr and limit contain '1'
122 * ---------------------------
124 * --------------+------------
125 * |- UNUSED -| EXP | RUN |
126 * ---------------------------
127 * status- Bit 0 - Watchdog is running
128 * Bit 1 - Watchdog has expired
133 * ---------------------------------
135 * +-------------+------------------
136 * |- UNUSED -| WD3 | WD2 | WD1 |
137 * ---------------------------------
138 * WD3 - 1 == Interrupt disabled for watchdog 3
139 * WD2 - 1 == Interrupt disabled for watchdog 2
140 * WD1 - 1 == Interrupt disabled for watchdog 1
173 MODULE_DESCRIPTION("Hardware watchdog driver for Sun Microsystems CP1400/1500");
197 /* Enable or disable watchdog interrupts
201 * index - sub-device index, or -1 for 'all'
202 * enable - non-zero to enable interrupts, zero to disable
204 static void cpwd_toggleintr(struct cpwd *p, int index, int enable) in cpwd_toggleintr() argument
206 unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK); in cpwd_toggleintr()
208 (index == -1) ? in cpwd_toggleintr()
210 (p->devs[index].intr_mask); in cpwd_toggleintr()
212 if (enable == WD_INTR_ON) in cpwd_toggleintr()
217 cpwd_writeb(curregs, p->regs + PLD_IMASK); in cpwd_toggleintr()
226 cpwd_writew(WD_BLIMIT, p->devs[index].regs + WD_LIMIT); in cpwd_resetbrokentimer()
229 /* Timer method called to reset stopped watchdogs--
246 if (p->devs[id].runstatus & WD_STAT_BSTOP) { in cpwd_brokentimer()
253 /* there is at least one timer brokenstopped-- reschedule */ in cpwd_brokentimer()
264 if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) in cpwd_pingtimer()
265 cpwd_readw(p->devs[index].regs + WD_DCNTR); in cpwd_pingtimer()
268 /* Stop a running watchdog timer-- the timer actually keeps
274 if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) { in cpwd_stoptimer()
277 if (p->broken) { in cpwd_stoptimer()
278 p->devs[index].runstatus |= WD_STAT_BSTOP; in cpwd_stoptimer()
284 /* Start a watchdog timer with the specified limit value
285 * If the watchdog is running, it will be restarted with
288 * This function will enable interrupts on the specified
289 * watchdog.
293 if (p->broken) in cpwd_starttimer()
294 p->devs[index].runstatus &= ~WD_STAT_BSTOP; in cpwd_starttimer()
296 p->devs[index].runstatus &= ~WD_STAT_SVCD; in cpwd_starttimer()
298 cpwd_writew(p->devs[index].timeout, p->devs[index].regs + WD_LIMIT); in cpwd_starttimer()
304 unsigned char stat = cpwd_readb(p->devs[index].regs + WD_STATUS); in cpwd_getstatus()
305 unsigned char intr = cpwd_readb(p->devs[index].regs + PLD_IMASK); in cpwd_getstatus()
316 if (intr & p->devs[index].intr_mask) { in cpwd_getstatus()
319 /* Fudge WD_EXPIRED status for defective CP1400-- in cpwd_getstatus()
330 if (p->broken && in cpwd_getstatus()
331 (p->devs[index].runstatus & WD_STAT_BSTOP)) { in cpwd_getstatus()
332 if (p->devs[index].runstatus & WD_STAT_SVCD) { in cpwd_getstatus()
346 if (p->devs[index].runstatus & WD_STAT_SVCD) in cpwd_getstatus()
356 /* Only WD0 will interrupt-- others are NMI and we won't in cpwd_interrupt()
359 spin_lock_irq(&p->lock); in cpwd_interrupt()
362 p->devs[WD0_ID].runstatus |= WD_STAT_SVCD; in cpwd_interrupt()
364 spin_unlock_irq(&p->lock); in cpwd_interrupt()
382 return -ENODEV; in cpwd_open()
386 if (!p->initialized) { in cpwd_open()
387 if (request_irq(p->irq, &cpwd_interrupt, in cpwd_open()
389 pr_err("Cannot register IRQ %d\n", p->irq); in cpwd_open()
391 return -EBUSY; in cpwd_open()
393 p->initialized = true; in cpwd_open()
415 int index = iminor(inode) - WD0_MINOR; in cpwd_ioctl()
423 return -EFAULT; in cpwd_ioctl()
429 return -EFAULT; in cpwd_ioctl()
438 return -EFAULT; in cpwd_ioctl()
441 if (p->enabled) in cpwd_ioctl()
442 return -EINVAL; in cpwd_ioctl()
447 return -EINVAL; in cpwd_ioctl()
451 /* Solaris-compatible IOCTLs */ in cpwd_ioctl()
455 return -EFAULT; in cpwd_ioctl()
463 if (p->enabled) in cpwd_ioctl()
464 return -EINVAL; in cpwd_ioctl()
470 return -EINVAL; in cpwd_ioctl()
499 return -EINVAL; in cpwd_read()
517 int i, err = -EINVAL; in cpwd_probe()
521 return -EINVAL; in cpwd_probe()
523 p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL); in cpwd_probe()
525 return -ENOMEM; in cpwd_probe()
527 p->irq = op->archdata.irqs[0]; in cpwd_probe()
529 spin_lock_init(&p->lock); in cpwd_probe()
531 p->regs = of_ioremap(&op->resource[0], 0, in cpwd_probe()
533 if (!p->regs) { in cpwd_probe()
535 return -ENOMEM; in cpwd_probe()
540 err = -ENODEV; in cpwd_probe()
545 prop_val = of_get_property(options, "watchdog-enable?", NULL); in cpwd_probe()
546 p->enabled = (prop_val ? true : false); in cpwd_probe()
548 prop_val = of_get_property(options, "watchdog-reboot?", NULL); in cpwd_probe()
549 p->reboot = (prop_val ? true : false); in cpwd_probe()
551 str_prop = of_get_property(options, "watchdog-timeout", NULL); in cpwd_probe()
553 p->timeout = simple_strtoul(str_prop, NULL, 10); in cpwd_probe()
557 /* CP1400s seem to have broken PLD implementations-- the in cpwd_probe()
561 str_prop = of_get_property(op->dev.of_node, "model", NULL); in cpwd_probe()
562 p->broken = (str_prop && !strcmp(str_prop, WD_BADMODEL)); in cpwd_probe()
564 if (!p->enabled) in cpwd_probe()
565 cpwd_toggleintr(p, -1, WD_INTR_OFF); in cpwd_probe()
572 struct miscdevice *mp = &p->devs[i].misc; in cpwd_probe()
574 mp->minor = WD0_MINOR + i; in cpwd_probe()
575 mp->name = cpwd_names[i]; in cpwd_probe()
576 mp->fops = &cpwd_fops; in cpwd_probe()
578 p->devs[i].regs = p->regs + (i * WD_TIMER_REGSZ); in cpwd_probe()
579 p->devs[i].intr_mask = (WD0_INTR_MASK << i); in cpwd_probe()
580 p->devs[i].runstatus &= ~WD_STAT_BSTOP; in cpwd_probe()
581 p->devs[i].runstatus |= WD_STAT_INIT; in cpwd_probe()
582 p->devs[i].timeout = p->timeout; in cpwd_probe()
584 p->devs[i].timeout = *parms[i]; in cpwd_probe()
586 err = misc_register(&p->devs[i].misc); in cpwd_probe()
594 if (p->broken) { in cpwd_probe()
607 for (i--; i >= 0; i--) in cpwd_probe()
608 misc_deregister(&p->devs[i].misc); in cpwd_probe()
611 of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); in cpwd_probe()
622 misc_deregister(&p->devs[i].misc); in cpwd_remove()
624 if (!p->enabled) { in cpwd_remove()
626 if (p->devs[i].runstatus & WD_STAT_BSTOP) in cpwd_remove()
631 if (p->broken) in cpwd_remove()
634 if (p->initialized) in cpwd_remove()
635 free_irq(p->irq, p); in cpwd_remove()
637 of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); in cpwd_remove()
644 .name = "watchdog",