22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30 #include <linux/module.h>
33 #include <linux/reboot.h>
35 #include <linux/watchdog.h>
37 #define DRVNAME "f71808e_wdt"
39 #define SIO_F71808FG_LD_WDT 0x07
40 #define SIO_UNLOCK_KEY 0x87
41 #define SIO_LOCK_KEY 0xAA
43 #define SIO_REG_LDSEL 0x07
44 #define SIO_REG_DEVID 0x20
45 #define SIO_REG_DEVREV 0x22
46 #define SIO_REG_MANID 0x23
47 #define SIO_REG_ROM_ADDR_SEL 0x27
48 #define SIO_REG_MFUNCT1 0x29
49 #define SIO_REG_MFUNCT2 0x2a
50 #define SIO_REG_MFUNCT3 0x2b
51 #define SIO_REG_ENABLE 0x30
52 #define SIO_REG_ADDR 0x60
54 #define SIO_FINTEK_ID 0x1934
55 #define SIO_F71808_ID 0x0901
56 #define SIO_F71858_ID 0x0507
57 #define SIO_F71862_ID 0x0601
58 #define SIO_F71869_ID 0x0814
59 #define SIO_F71869A_ID 0x1007
60 #define SIO_F71882_ID 0x0541
61 #define SIO_F71889_ID 0x0723
63 #define F71808FG_REG_WDO_CONF 0xf0
64 #define F71808FG_REG_WDT_CONF 0xf5
65 #define F71808FG_REG_WD_TIME 0xf6
67 #define F71808FG_FLAG_WDOUT_EN 7
69 #define F71808FG_FLAG_WDTMOUT_STS 5
70 #define F71808FG_FLAG_WD_EN 5
71 #define F71808FG_FLAG_WD_PULSE 4
72 #define F71808FG_FLAG_WD_UNIT 3
75 #define WATCHDOG_TIMEOUT 60
76 #define WATCHDOG_MAX_TIMEOUT (60 * 255)
77 #define WATCHDOG_PULSE_WIDTH 125
79 #define WATCHDOG_F71862FG_PIN 63
82 static unsigned short force_id;
90 "Watchdog timeout in seconds. 1<= timeout <="
97 "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms"
103 "Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63"
110 static unsigned int start_withtimeout;
112 MODULE_PARM_DESC(start_withtimeout,
"Start watchdog timer on module load with"
113 " given initial timeout. Zero (default) disables this feature.");
117 static const char *f71808e_names[] = {
127 static inline int superio_inb(
int base,
int reg);
128 static inline int superio_inw(
int base,
int reg);
129 static inline void superio_outb(
int base,
int reg,
u8 val);
130 static inline void superio_set_bit(
int base,
int reg,
int bit);
131 static inline void superio_clear_bit(
int base,
int reg,
int bit);
132 static inline int superio_enter(
int base);
134 static inline void superio_exit(
int base);
157 static inline int superio_inb(
int base,
int reg)
160 return inb(base + 1);
163 static int superio_inw(
int base,
int reg)
166 val = superio_inb(base, reg) << 8;
167 val |= superio_inb(base, reg + 1);
171 static inline void superio_outb(
int base,
int reg,
u8 val)
177 static inline void superio_set_bit(
int base,
int reg,
int bit)
179 unsigned long val = superio_inb(base, reg);
181 superio_outb(base, reg, val);
184 static inline void superio_clear_bit(
int base,
int reg,
int bit)
186 unsigned long val = superio_inb(base, reg);
188 superio_outb(base, reg, val);
191 static inline int superio_enter(
int base)
195 pr_err(
"I/O address 0x%04x already in use\n", (
int)base);
212 static inline void superio_exit(
int base)
218 static int watchdog_set_timeout(
int timeout)
221 || timeout > max_timeout) {
222 pr_err(
"watchdog timeout out of range\n");
229 if (timeout > 0xff) {
242 static int watchdog_set_pulse_width(
unsigned int pw)
250 }
else if (pw <= 25) {
252 }
else if (pw <= 125) {
254 }
else if (pw <= 5000) {
257 pr_err(
"pulse width out of range\n");
269 static int watchdog_keepalive(
void)
274 err = superio_enter(watchdog.
sioaddr);
292 superio_exit(watchdog.
sioaddr);
299 static int f71862fg_pin_configure(
unsigned short ioaddr)
304 if (f71862fg_pin == 63) {
310 }
else if (f71862fg_pin == 56) {
314 pr_err(
"Invalid argument f71862fg_pin=%d\n", f71862fg_pin);
320 static int watchdog_start(
void)
323 int err = watchdog_keepalive();
328 err = superio_enter(watchdog.
sioaddr);
334 switch (watchdog.
type) {
342 err = f71862fg_pin_configure(watchdog.
sioaddr);
382 u8 wdt_conf = superio_inb(watchdog.
sioaddr,
386 wdt_conf = (wdt_conf & 0xfc) | (watchdog.
pulse_val & 0x03);
399 superio_exit(watchdog.
sioaddr);
406 static int watchdog_stop(
void)
411 err = superio_enter(watchdog.
sioaddr);
419 superio_exit(watchdog.
sioaddr);
427 static int watchdog_get_status(
void)
438 static bool watchdog_is_running(
void)
444 bool is_running =
true;
447 if (superio_enter(watchdog.
sioaddr))
455 superio_exit(watchdog.
sioaddr);
472 err = watchdog_start();
485 static int watchdog_release(
struct inode *inode,
struct file *file)
490 watchdog_keepalive();
491 pr_crit(
"Unexpected close, not stopping watchdog!\n");
492 }
else if (!nowayout) {
509 static ssize_t watchdog_write(
struct file *file,
const char __user *
buf,
510 size_t count, loff_t *ppos)
519 for (i = 0; i !=
count; i++) {
523 expect_close = (c ==
'V');
533 watchdog_keepalive();
548 static long watchdog_ioctl(
struct file *file,
unsigned int cmd,
559 uarg.i = (
int __user *)arg;
567 status = watchdog_get_status();
583 return watchdog_start();
587 watchdog_keepalive();
594 if (watchdog_set_timeout(new_timeout))
597 watchdog_keepalive();
620 .open = watchdog_open,
621 .release = watchdog_release,
622 .write = watchdog_write,
623 .unlocked_ioctl = watchdog_ioctl,
629 .fops = &watchdog_fops,
633 .notifier_call = watchdog_notify_sys,
636 static int __init watchdog_init(
int sioaddr)
638 int wdt_conf, err = 0;
649 sizeof(watchdog.
ident.identity),
"%s watchdog",
650 f71808e_names[watchdog.
type]);
652 err = superio_enter(sioaddr);
660 superio_exit(sioaddr);
662 err = watchdog_set_timeout(timeout);
665 err = watchdog_set_pulse_width(pulse_width);
675 pr_err(
"cannot register miscdev on minor=%d\n",
676 watchdog_miscdev.
minor);
680 if (start_withtimeout) {
681 if (start_withtimeout <= 0
682 || start_withtimeout > max_timeout) {
683 pr_err(
"starting timeout out of range\n");
688 err = watchdog_start();
690 pr_err(
"cannot start watchdog timer\n");
695 err = superio_enter(sioaddr);
700 if (start_withtimeout > 0xff) {
714 superio_exit(sioaddr);
720 pr_info(
"watchdog started with initial timeout of %u sec\n",
736 static int __init f71808e_find(
int sioaddr)
739 int err = superio_enter(sioaddr);
750 devid = force_id ? force_id : superio_inw(sioaddr,
SIO_REG_DEVID);
757 err = f71862fg_pin_configure(0);
774 pr_info(
"Unrecognized Fintek device: %04x\n",
775 (
unsigned int)devid);
780 pr_info(
"Found %s watchdog chip, revision %d\n",
781 f71808e_names[watchdog.
type],
784 superio_exit(sioaddr);
788 static int __init f71808e_init(
void)
790 static const unsigned short addrs[] = { 0x2e, 0x4e };
795 err = f71808e_find(addrs[i]);
802 return watchdog_init(addrs[i]);
805 static void __exit f71808e_exit(
void)
807 if (watchdog_is_running()) {
808 pr_warn(
"Watchdog timer still running, stopping it\n");