17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 #include <linux/kernel.h>
20 #include <linux/module.h>
22 #include <linux/errno.h>
29 #include <linux/slab.h>
37 #include <asm/watchdog.h>
39 #define DRIVER_NAME "cpwd"
41 #define WD_OBPNAME "watchdog"
42 #define WD_BADMODEL "SUNW,501-5336"
43 #define WD_BTIMEOUT (jiffies + (HZ * 1000))
44 #define WD_BLIMIT 0xFFFF
59 #define WD_STAT_INIT 0x01
60 #define WD_STAT_BSTOP 0x02
61 #define WD_STAT_SVCD 0x04
65 #define WD0_INTR_MASK 0x01
66 #define WD1_INTR_MASK 0x02
67 #define WD2_INTR_MASK 0x04
69 #define WD_S_RUNNING 0x01
70 #define WD_S_EXPIRED 0x02
94 static struct cpwd *cpwd_device;
145 #define WD_TIMER_REGSZ 16
147 #define WD1_OFF (WD_TIMER_REGSZ * 1)
148 #define WD2_OFF (WD_TIMER_REGSZ * 2)
149 #define PLD_OFF (WD_TIMER_REGSZ * 3)
151 #define WD_DCNTR 0x00
152 #define WD_LIMIT 0x04
153 #define WD_STATUS 0x08
155 #define PLD_IMASK (PLD_OFF + 0x00)
156 #define PLD_STATUS (PLD_OFF + 0x04)
160 static int wd0_timeout;
161 static int wd1_timeout;
162 static int wd2_timeout;
187 static void cpwd_writeb(
u8 val,
void __iomem *addr)
207 unsigned char setregs =
223 static void cpwd_resetbrokentimer(
struct cpwd *p,
int index)
234 static void cpwd_brokentimer(
unsigned long data)
236 struct cpwd *p = (
struct cpwd *) data;
242 if (timer_pending(&cpwd_timer))
248 cpwd_resetbrokentimer(p,
id);
262 static void cpwd_pingtimer(
struct cpwd *p,
int index)
272 static void cpwd_stoptimer(
struct cpwd *p,
int index)
279 cpwd_brokentimer((
unsigned long) p);
291 static void cpwd_starttimer(
struct cpwd *p,
int index)
302 static int cpwd_getstatus(
struct cpwd *p,
int index)
315 }
else if (WD_S_RUNNING & stat) {
316 if (intr & p->
devs[index].intr_mask) {
359 spin_lock_irq(&p->
lock);
361 cpwd_stoptimer(p,
WD0_ID);
364 spin_unlock_irq(&p->
lock);
371 struct cpwd *p = cpwd_device;
374 switch (iminor(inode)) {
389 pr_err(
"Cannot register IRQ %d\n", p->
irq);
401 static int cpwd_release(
struct inode *inode,
struct file *
file)
406 static long cpwd_ioctl(
struct file *
file,
unsigned int cmd,
unsigned long arg)
410 .firmware_version = 1,
414 struct inode *inode = file->
f_path.dentry->d_inode;
416 struct cpwd *p = cpwd_device;
428 if (
put_user(0, (
int __user *)argp))
433 cpwd_pingtimer(p, index);
443 cpwd_stoptimer(p, index);
445 cpwd_starttimer(p, index);
453 setopt = cpwd_getstatus(p, index);
459 cpwd_starttimer(p, index);
466 cpwd_stoptimer(p, index);
476 static long cpwd_compat_ioctl(
struct file *file,
unsigned int cmd,
487 rval = cpwd_ioctl(file, cmd, arg);
499 static ssize_t cpwd_write(
struct file *file,
const char __user *
buf,
500 size_t count, loff_t *ppos)
502 struct inode *inode = file->
f_path.dentry->d_inode;
503 struct cpwd *p = cpwd_device;
504 int index = iminor(inode);
507 cpwd_pingtimer(p, index);
514 static ssize_t cpwd_read(
struct file *file,
char __user *
buffer,
515 size_t count, loff_t *ppos)
522 .unlocked_ioctl = cpwd_ioctl,
523 .compat_ioctl = cpwd_compat_ioctl,
527 .release = cpwd_release,
534 const char *str_prop;
535 const void *prop_val;
545 pr_err(
"Unable to allocate struct cpwd\n");
556 pr_err(
"Unable to map registers\n");
563 pr_err(
"Unable to find /options node\n");
568 p->
enabled = (prop_val ?
true :
false);
571 p->
reboot = (prop_val ?
true :
false);
588 static const char *cpwd_names[] = {
"RIC",
"XIR",
"POR" };
589 static int *
parms[] = { &wd0_timeout,
595 mp->
name = cpwd_names[
i];
596 mp->
fops = &cpwd_fops;
604 p->
devs[
i].timeout = *parms[
i];
608 pr_err(
"Could not register misc device for dev %d\n",
616 cpwd_timer.function = cpwd_brokentimer;
617 cpwd_timer.data = (
unsigned long) p;
620 pr_info(
"PLD defect workaround enabled for model %s\n",
632 for (i--; i >= 0; i--)
652 cpwd_stoptimer(p, i);
654 cpwd_resetbrokentimer(p, i);
684 .of_match_table = cpwd_match,