]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/watchdog/f71808e_wdt.c
UBUNTU: Ubuntu-5.15.0-39.42
[mirror_ubuntu-jammy-kernel.git] / drivers / watchdog / f71808e_wdt.c
CommitLineData
1a59d1b8 1// SPDX-License-Identifier: GPL-2.0-or-later
96cb4eb0
GS
2/***************************************************************************
3 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
4 * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> *
5 * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> *
6 * *
96cb4eb0
GS
7 ***************************************************************************/
8
27c766aa
JP
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
96cb4eb0
GS
11#include <linux/err.h>
12#include <linux/fs.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/ioport.h>
16#include <linux/miscdevice.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/notifier.h>
20#include <linux/reboot.h>
21#include <linux/uaccess.h>
22#include <linux/watchdog.h>
23
24#define DRVNAME "f71808e_wdt"
25
26#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */
27#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
85c130a8 28#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
96cb4eb0
GS
29
30#define SIO_REG_LDSEL 0x07 /* Logical device select */
31#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
32#define SIO_REG_DEVREV 0x22 /* Device revision */
33#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
ca2fc5ef 34#define SIO_REG_CLOCK_SEL 0x26 /* Clock select */
7977ff6e 35#define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */
14b24a88 36#define SIO_F81866_REG_PORT_SEL 0x27 /* F81866 Multi-Function Register */
ca2fc5ef 37#define SIO_REG_TSI_LEVEL_SEL 0x28 /* TSI Level select */
f9a9f096
LB
38#define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */
39#define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */
40#define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */
14b24a88 41#define SIO_F81866_REG_GPIO1 0x2c /* F81866 GPIO1 Enable Register */
96cb4eb0
GS
42#define SIO_REG_ENABLE 0x30 /* Logical device enable */
43#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
44
45#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
f9a9f096
LB
46#define SIO_F71808_ID 0x0901 /* Chipset ID */
47#define SIO_F71858_ID 0x0507 /* Chipset ID */
96cb4eb0 48#define SIO_F71862_ID 0x0601 /* Chipset ID */
166fbcf8 49#define SIO_F71868_ID 0x1106 /* Chipset ID */
df278dac 50#define SIO_F71869_ID 0x0814 /* Chipset ID */
3017020d 51#define SIO_F71869A_ID 0x1007 /* Chipset ID */
96cb4eb0
GS
52#define SIO_F71882_ID 0x0541 /* Chipset ID */
53#define SIO_F71889_ID 0x0723 /* Chipset ID */
ca2fc5ef 54#define SIO_F81803_ID 0x1210 /* Chipset ID */
ea0c03e8 55#define SIO_F81865_ID 0x0704 /* Chipset ID */
14b24a88 56#define SIO_F81866_ID 0x1010 /* Chipset ID */
a155cefb 57#define SIO_F81966_ID 0x1502 /* F81804 chipset ID, same for f81966 */
96cb4eb0 58
96cb4eb0
GS
59#define F71808FG_REG_WDO_CONF 0xf0
60#define F71808FG_REG_WDT_CONF 0xf5
61#define F71808FG_REG_WD_TIME 0xf6
62
63#define F71808FG_FLAG_WDOUT_EN 7
64
b97cb21a 65#define F71808FG_FLAG_WDTMOUT_STS 6
96cb4eb0
GS
66#define F71808FG_FLAG_WD_EN 5
67#define F71808FG_FLAG_WD_PULSE 4
68#define F71808FG_FLAG_WD_UNIT 3
69
ea0c03e8
KP
70#define F81865_REG_WDO_CONF 0xfa
71#define F81865_FLAG_WDOUT_EN 0
72
96cb4eb0
GS
73/* Default values */
74#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */
75#define WATCHDOG_MAX_TIMEOUT (60 * 255)
76#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for
77 watchdog signal */
7977ff6e
LB
78#define WATCHDOG_F71862FG_PIN 63 /* default watchdog reset output
79 pin number 63 */
96cb4eb0
GS
80
81static unsigned short force_id;
82module_param(force_id, ushort, 0);
83MODULE_PARM_DESC(force_id, "Override the detected device ID");
84
85static const int max_timeout = WATCHDOG_MAX_TIMEOUT;
f9a9f096 86static int timeout = WATCHDOG_TIMEOUT; /* default timeout in seconds */
96cb4eb0
GS
87module_param(timeout, int, 0);
88MODULE_PARM_DESC(timeout,
89 "Watchdog timeout in seconds. 1<= timeout <="
90 __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default="
91 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
92
93static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH;
94module_param(pulse_width, uint, 0);
95MODULE_PARM_DESC(pulse_width,
166fbcf8 96 "Watchdog signal pulse width. 0(=level), 1, 25, 30, 125, 150, 5000 or 6000 ms"
96cb4eb0
GS
97 " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")");
98
7977ff6e
LB
99static unsigned int f71862fg_pin = WATCHDOG_F71862FG_PIN;
100module_param(f71862fg_pin, uint, 0);
101MODULE_PARM_DESC(f71862fg_pin,
102 "Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63"
103 " (default=" __MODULE_STRING(WATCHDOG_F71862FG_PIN)")");
104
90ab5ee9 105static bool nowayout = WATCHDOG_NOWAYOUT;
96cb4eb0
GS
106module_param(nowayout, bool, 0444);
107MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
108
109static unsigned int start_withtimeout;
110module_param(start_withtimeout, uint, 0);
111MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with"
112 " given initial timeout. Zero (default) disables this feature.");
113
166fbcf8 114enum chips { f71808fg, f71858fg, f71862fg, f71868, f71869, f71882fg, f71889fg,
a155cefb 115 f81803, f81865, f81866, f81966};
96cb4eb0
GS
116
117static const char *f71808e_names[] = {
118 "f71808fg",
119 "f71858fg",
120 "f71862fg",
166fbcf8 121 "f71868",
df278dac 122 "f71869",
96cb4eb0
GS
123 "f71882fg",
124 "f71889fg",
ca2fc5ef 125 "f81803",
ea0c03e8 126 "f81865",
14b24a88 127 "f81866",
a155cefb 128 "f81966"
96cb4eb0
GS
129};
130
131/* Super-I/O Function prototypes */
132static inline int superio_inb(int base, int reg);
133static inline int superio_inw(int base, int reg);
134static inline void superio_outb(int base, int reg, u8 val);
135static inline void superio_set_bit(int base, int reg, int bit);
136static inline void superio_clear_bit(int base, int reg, int bit);
137static inline int superio_enter(int base);
138static inline void superio_select(int base, int ld);
139static inline void superio_exit(int base);
140
141struct watchdog_data {
142 unsigned short sioaddr;
143 enum chips type;
144 unsigned long opened;
145 struct mutex lock;
146 char expect_close;
147 struct watchdog_info ident;
148
149 unsigned short timeout;
150 u8 timer_val; /* content for the wd_time register */
151 char minutes_mode;
152 u8 pulse_val; /* pulse width flag */
153 char pulse_mode; /* enable pulse output mode? */
154 char caused_reboot; /* last reboot was by the watchdog */
155};
156
157static struct watchdog_data watchdog = {
158 .lock = __MUTEX_INITIALIZER(watchdog.lock),
159};
160
161/* Super I/O functions */
162static inline int superio_inb(int base, int reg)
163{
164 outb(reg, base);
165 return inb(base + 1);
166}
167
168static int superio_inw(int base, int reg)
169{
170 int val;
171 val = superio_inb(base, reg) << 8;
172 val |= superio_inb(base, reg + 1);
173 return val;
174}
175
176static inline void superio_outb(int base, int reg, u8 val)
177{
178 outb(reg, base);
179 outb(val, base + 1);
180}
181
182static inline void superio_set_bit(int base, int reg, int bit)
183{
184 unsigned long val = superio_inb(base, reg);
185 __set_bit(bit, &val);
186 superio_outb(base, reg, val);
187}
188
189static inline void superio_clear_bit(int base, int reg, int bit)
190{
191 unsigned long val = superio_inb(base, reg);
192 __clear_bit(bit, &val);
193 superio_outb(base, reg, val);
194}
195
196static inline int superio_enter(int base)
197{
198 /* Don't step on other drivers' I/O space by accident */
199 if (!request_muxed_region(base, 2, DRVNAME)) {
27c766aa 200 pr_err("I/O address 0x%04x already in use\n", (int)base);
96cb4eb0
GS
201 return -EBUSY;
202 }
203
3017020d 204 /* according to the datasheet the key must be sent twice! */
96cb4eb0
GS
205 outb(SIO_UNLOCK_KEY, base);
206 outb(SIO_UNLOCK_KEY, base);
207
208 return 0;
209}
210
211static inline void superio_select(int base, int ld)
212{
213 outb(SIO_REG_LDSEL, base);
214 outb(ld, base + 1);
215}
216
217static inline void superio_exit(int base)
218{
219 outb(SIO_LOCK_KEY, base);
220 release_region(base, 2);
221}
222
223static int watchdog_set_timeout(int timeout)
224{
225 if (timeout <= 0
226 || timeout > max_timeout) {
27c766aa 227 pr_err("watchdog timeout out of range\n");
96cb4eb0
GS
228 return -EINVAL;
229 }
230
231 mutex_lock(&watchdog.lock);
232
96cb4eb0
GS
233 if (timeout > 0xff) {
234 watchdog.timer_val = DIV_ROUND_UP(timeout, 60);
235 watchdog.minutes_mode = true;
26a99ad8 236 timeout = watchdog.timer_val * 60;
96cb4eb0
GS
237 } else {
238 watchdog.timer_val = timeout;
239 watchdog.minutes_mode = false;
240 }
241
26a99ad8
AF
242 watchdog.timeout = timeout;
243
96cb4eb0
GS
244 mutex_unlock(&watchdog.lock);
245
246 return 0;
247}
248
249static int watchdog_set_pulse_width(unsigned int pw)
250{
251 int err = 0;
166fbcf8
MS
252 unsigned int t1 = 25, t2 = 125, t3 = 5000;
253
254 if (watchdog.type == f71868) {
255 t1 = 30;
256 t2 = 150;
257 t3 = 6000;
258 }
96cb4eb0
GS
259
260 mutex_lock(&watchdog.lock);
261
166fbcf8 262 if (pw <= 1) {
96cb4eb0 263 watchdog.pulse_val = 0;
166fbcf8 264 } else if (pw <= t1) {
96cb4eb0 265 watchdog.pulse_val = 1;
166fbcf8 266 } else if (pw <= t2) {
96cb4eb0 267 watchdog.pulse_val = 2;
166fbcf8 268 } else if (pw <= t3) {
96cb4eb0
GS
269 watchdog.pulse_val = 3;
270 } else {
27c766aa 271 pr_err("pulse width out of range\n");
96cb4eb0
GS
272 err = -EINVAL;
273 goto exit_unlock;
274 }
275
276 watchdog.pulse_mode = pw;
277
278exit_unlock:
279 mutex_unlock(&watchdog.lock);
280 return err;
281}
282
283static int watchdog_keepalive(void)
284{
285 int err = 0;
286
287 mutex_lock(&watchdog.lock);
288 err = superio_enter(watchdog.sioaddr);
289 if (err)
290 goto exit_unlock;
291 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
292
293 if (watchdog.minutes_mode)
294 /* select minutes for timer units */
295 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
296 F71808FG_FLAG_WD_UNIT);
297 else
298 /* select seconds for timer units */
299 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
300 F71808FG_FLAG_WD_UNIT);
301
302 /* Set timer value */
303 superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME,
304 watchdog.timer_val);
305
306 superio_exit(watchdog.sioaddr);
307
308exit_unlock:
309 mutex_unlock(&watchdog.lock);
310 return err;
311}
312
313static int watchdog_start(void)
314{
a3f764d2 315 int err;
e347afa5 316 u8 tmp;
a3f764d2 317
96cb4eb0 318 /* Make sure we don't die as soon as the watchdog is enabled below */
a3f764d2 319 err = watchdog_keepalive();
96cb4eb0
GS
320 if (err)
321 return err;
322
323 mutex_lock(&watchdog.lock);
324 err = superio_enter(watchdog.sioaddr);
325 if (err)
326 goto exit_unlock;
327 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
328
329 /* Watchdog pin configuration */
330 switch (watchdog.type) {
331 case f71808fg:
332 /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */
f9a9f096
LB
333 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT2, 3);
334 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 3);
96cb4eb0
GS
335 break;
336
7977ff6e 337 case f71862fg:
5edc8c68
AF
338 if (f71862fg_pin == 63) {
339 /* SPI must be disabled first to use this pin! */
340 superio_clear_bit(watchdog.sioaddr, SIO_REG_ROM_ADDR_SEL, 6);
341 superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 4);
342 } else if (f71862fg_pin == 56) {
343 superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1);
344 }
7977ff6e
LB
345 break;
346
166fbcf8 347 case f71868:
df278dac
MA
348 case f71869:
349 /* GPIO14 --> WDTRST# */
350 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 4);
351 break;
352
96cb4eb0
GS
353 case f71882fg:
354 /* Set pin 56 to WDTRST# */
f9a9f096 355 superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1);
96cb4eb0
GS
356 break;
357
dee00abb
GS
358 case f71889fg:
359 /* set pin 40 to WDTRST# */
f9a9f096
LB
360 superio_outb(watchdog.sioaddr, SIO_REG_MFUNCT3,
361 superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf);
dee00abb
GS
362 break;
363
ca2fc5ef
JC
364 case f81803:
365 /* Enable TSI Level register bank */
366 superio_clear_bit(watchdog.sioaddr, SIO_REG_CLOCK_SEL, 3);
367 /* Set pin 27 to WDTRST# */
368 superio_outb(watchdog.sioaddr, SIO_REG_TSI_LEVEL_SEL, 0x5f &
369 superio_inb(watchdog.sioaddr, SIO_REG_TSI_LEVEL_SEL));
370 break;
371
ea0c03e8
KP
372 case f81865:
373 /* Set pin 70 to WDTRST# */
374 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 5);
375 break;
376
14b24a88 377 case f81866:
a155cefb 378 case f81966:
14b24a88
JZHPH
379 /*
380 * GPIO1 Control Register when 27h BIT3:2 = 01 & BIT0 = 0.
381 * The PIN 70(GPIO15/WDTRST) is controlled by 2Ch:
382 * BIT5: 0 -> WDTRST#
383 * 1 -> GPIO15
384 */
e347afa5
JZHPH
385 tmp = superio_inb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL);
386 tmp &= ~(BIT(3) | BIT(0));
387 tmp |= BIT(2);
388 superio_outb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, tmp);
389
390 superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1, 5);
14b24a88
JZHPH
391 break;
392
96cb4eb0
GS
393 default:
394 /*
395 * 'default' label to shut up the compiler and catch
396 * programmer errors
397 */
398 err = -ENODEV;
399 goto exit_superio;
400 }
401
402 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
403 superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0);
ea0c03e8 404
a155cefb 405 if (watchdog.type == f81865 || watchdog.type == f81866 || watchdog.type == f81966)
ea0c03e8
KP
406 superio_set_bit(watchdog.sioaddr, F81865_REG_WDO_CONF,
407 F81865_FLAG_WDOUT_EN);
408 else
409 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF,
410 F71808FG_FLAG_WDOUT_EN);
96cb4eb0
GS
411
412 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
413 F71808FG_FLAG_WD_EN);
414
415 if (watchdog.pulse_mode) {
416 /* Select "pulse" output mode with given duration */
417 u8 wdt_conf = superio_inb(watchdog.sioaddr,
418 F71808FG_REG_WDT_CONF);
419
420 /* Set WD_PSWIDTH bits (1:0) */
421 wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03);
422 /* Set WD_PULSE to "pulse" mode */
423 wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE);
424
425 superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
426 wdt_conf);
427 } else {
428 /* Select "level" output mode */
429 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
430 F71808FG_FLAG_WD_PULSE);
431 }
432
433exit_superio:
434 superio_exit(watchdog.sioaddr);
435exit_unlock:
436 mutex_unlock(&watchdog.lock);
437
438 return err;
439}
440
441static int watchdog_stop(void)
442{
443 int err = 0;
444
445 mutex_lock(&watchdog.lock);
446 err = superio_enter(watchdog.sioaddr);
447 if (err)
448 goto exit_unlock;
449 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
450
451 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
452 F71808FG_FLAG_WD_EN);
453
454 superio_exit(watchdog.sioaddr);
455
456exit_unlock:
457 mutex_unlock(&watchdog.lock);
458
459 return err;
460}
461
462static int watchdog_get_status(void)
463{
464 int status = 0;
465
466 mutex_lock(&watchdog.lock);
467 status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0;
468 mutex_unlock(&watchdog.lock);
469
470 return status;
471}
472
473static bool watchdog_is_running(void)
474{
475 /*
476 * if we fail to determine the watchdog's status assume it to be
477 * running to be on the safe side
478 */
479 bool is_running = true;
480
481 mutex_lock(&watchdog.lock);
482 if (superio_enter(watchdog.sioaddr))
483 goto exit_unlock;
484 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
485
486 is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0))
487 && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF)
977f6f68 488 & BIT(F71808FG_FLAG_WD_EN));
96cb4eb0
GS
489
490 superio_exit(watchdog.sioaddr);
491
492exit_unlock:
493 mutex_unlock(&watchdog.lock);
494 return is_running;
495}
496
497/* /dev/watchdog api */
498
499static int watchdog_open(struct inode *inode, struct file *file)
500{
501 int err;
502
503 /* If the watchdog is alive we don't need to start it again */
504 if (test_and_set_bit(0, &watchdog.opened))
505 return -EBUSY;
506
507 err = watchdog_start();
508 if (err) {
509 clear_bit(0, &watchdog.opened);
510 return err;
511 }
512
513 if (nowayout)
514 __module_get(THIS_MODULE);
515
516 watchdog.expect_close = 0;
c5bf68fe 517 return stream_open(inode, file);
96cb4eb0
GS
518}
519
520static int watchdog_release(struct inode *inode, struct file *file)
521{
522 clear_bit(0, &watchdog.opened);
523
524 if (!watchdog.expect_close) {
525 watchdog_keepalive();
27c766aa 526 pr_crit("Unexpected close, not stopping watchdog!\n");
96cb4eb0
GS
527 } else if (!nowayout) {
528 watchdog_stop();
529 }
530 return 0;
531}
532
533/*
534 * watchdog_write:
535 * @file: file handle to the watchdog
536 * @buf: buffer to write
537 * @count: count of bytes
538 * @ppos: pointer to the position to write. No seeks allowed
539 *
540 * A write to a watchdog device is defined as a keepalive signal. Any
541 * write of data will do, as we we don't define content meaning.
542 */
543
544static ssize_t watchdog_write(struct file *file, const char __user *buf,
545 size_t count, loff_t *ppos)
546{
547 if (count) {
548 if (!nowayout) {
549 size_t i;
550
551 /* In case it was set long ago */
552 bool expect_close = false;
553
554 for (i = 0; i != count; i++) {
555 char c;
556 if (get_user(c, buf + i))
557 return -EFAULT;
7bd3e7b7
IP
558 if (c == 'V')
559 expect_close = true;
96cb4eb0
GS
560 }
561
562 /* Properly order writes across fork()ed processes */
563 mutex_lock(&watchdog.lock);
564 watchdog.expect_close = expect_close;
565 mutex_unlock(&watchdog.lock);
566 }
567
568 /* someone wrote to us, we should restart timer */
569 watchdog_keepalive();
570 }
571 return count;
572}
573
574/*
575 * watchdog_ioctl:
576 * @inode: inode of the device
577 * @file: file handle to the device
578 * @cmd: watchdog command
579 * @arg: argument pointer
580 *
581 * The watchdog API defines a common set of functions for all watchdogs
582 * according to their available features.
583 */
584static long watchdog_ioctl(struct file *file, unsigned int cmd,
585 unsigned long arg)
586{
587 int status;
588 int new_options;
589 int new_timeout;
590 union {
591 struct watchdog_info __user *ident;
592 int __user *i;
593 } uarg;
594
595 uarg.i = (int __user *)arg;
596
597 switch (cmd) {
598 case WDIOC_GETSUPPORT:
599 return copy_to_user(uarg.ident, &watchdog.ident,
600 sizeof(watchdog.ident)) ? -EFAULT : 0;
601
602 case WDIOC_GETSTATUS:
603 status = watchdog_get_status();
604 if (status < 0)
605 return status;
606 return put_user(status, uarg.i);
607
608 case WDIOC_GETBOOTSTATUS:
609 return put_user(0, uarg.i);
610
611 case WDIOC_SETOPTIONS:
612 if (get_user(new_options, uarg.i))
613 return -EFAULT;
614
615 if (new_options & WDIOS_DISABLECARD)
616 watchdog_stop();
617
618 if (new_options & WDIOS_ENABLECARD)
619 return watchdog_start();
bd490f82 620 fallthrough;
96cb4eb0
GS
621
622 case WDIOC_KEEPALIVE:
623 watchdog_keepalive();
624 return 0;
625
626 case WDIOC_SETTIMEOUT:
627 if (get_user(new_timeout, uarg.i))
628 return -EFAULT;
629
630 if (watchdog_set_timeout(new_timeout))
631 return -EINVAL;
632
633 watchdog_keepalive();
bd490f82 634 fallthrough;
96cb4eb0
GS
635
636 case WDIOC_GETTIMEOUT:
637 return put_user(watchdog.timeout, uarg.i);
638
639 default:
640 return -ENOTTY;
641
642 }
643}
644
645static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
646 void *unused)
647{
648 if (code == SYS_DOWN || code == SYS_HALT)
649 watchdog_stop();
650 return NOTIFY_DONE;
651}
652
653static const struct file_operations watchdog_fops = {
654 .owner = THIS_MODULE,
655 .llseek = no_llseek,
656 .open = watchdog_open,
657 .release = watchdog_release,
658 .write = watchdog_write,
659 .unlocked_ioctl = watchdog_ioctl,
b6dfb247 660 .compat_ioctl = compat_ptr_ioctl,
96cb4eb0
GS
661};
662
663static struct miscdevice watchdog_miscdev = {
664 .minor = WATCHDOG_MINOR,
665 .name = "watchdog",
666 .fops = &watchdog_fops,
667};
668
669static struct notifier_block watchdog_notifier = {
670 .notifier_call = watchdog_notify_sys,
671};
672
673static int __init watchdog_init(int sioaddr)
674{
675 int wdt_conf, err = 0;
676
677 /* No need to lock watchdog.lock here because no entry points
678 * into the module have been registered yet.
679 */
680 watchdog.sioaddr = sioaddr;
80214146 681 watchdog.ident.options = WDIOF_MAGICCLOSE
e871e93f
AF
682 | WDIOF_KEEPALIVEPING
683 | WDIOF_CARDRESET;
96cb4eb0
GS
684
685 snprintf(watchdog.ident.identity,
686 sizeof(watchdog.ident.identity), "%s watchdog",
687 f71808e_names[watchdog.type]);
688
689 err = superio_enter(sioaddr);
690 if (err)
691 return err;
692 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
693
694 wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF);
b97cb21a 695 watchdog.caused_reboot = wdt_conf & BIT(F71808FG_FLAG_WDTMOUT_STS);
96cb4eb0 696
4f39d575
AF
697 /*
698 * We don't want WDTMOUT_STS to stick around till regular reboot.
699 * Write 1 to the bit to clear it to zero.
700 */
701 superio_outb(sioaddr, F71808FG_REG_WDT_CONF,
702 wdt_conf | BIT(F71808FG_FLAG_WDTMOUT_STS));
703
96cb4eb0
GS
704 superio_exit(sioaddr);
705
706 err = watchdog_set_timeout(timeout);
707 if (err)
708 return err;
709 err = watchdog_set_pulse_width(pulse_width);
710 if (err)
711 return err;
712
713 err = register_reboot_notifier(&watchdog_notifier);
714 if (err)
715 return err;
716
717 err = misc_register(&watchdog_miscdev);
718 if (err) {
27c766aa
JP
719 pr_err("cannot register miscdev on minor=%d\n",
720 watchdog_miscdev.minor);
96cb4eb0
GS
721 goto exit_reboot;
722 }
723
724 if (start_withtimeout) {
725 if (start_withtimeout <= 0
726 || start_withtimeout > max_timeout) {
27c766aa 727 pr_err("starting timeout out of range\n");
96cb4eb0
GS
728 err = -EINVAL;
729 goto exit_miscdev;
730 }
731
732 err = watchdog_start();
733 if (err) {
27c766aa 734 pr_err("cannot start watchdog timer\n");
96cb4eb0
GS
735 goto exit_miscdev;
736 }
737
738 mutex_lock(&watchdog.lock);
739 err = superio_enter(sioaddr);
740 if (err)
741 goto exit_unlock;
742 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
743
744 if (start_withtimeout > 0xff) {
745 /* select minutes for timer units */
746 superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF,
747 F71808FG_FLAG_WD_UNIT);
748 superio_outb(sioaddr, F71808FG_REG_WD_TIME,
749 DIV_ROUND_UP(start_withtimeout, 60));
750 } else {
751 /* select seconds for timer units */
752 superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF,
753 F71808FG_FLAG_WD_UNIT);
754 superio_outb(sioaddr, F71808FG_REG_WD_TIME,
755 start_withtimeout);
756 }
757
758 superio_exit(sioaddr);
759 mutex_unlock(&watchdog.lock);
760
761 if (nowayout)
762 __module_get(THIS_MODULE);
763
27c766aa 764 pr_info("watchdog started with initial timeout of %u sec\n",
96cb4eb0
GS
765 start_withtimeout);
766 }
767
768 return 0;
769
770exit_unlock:
771 mutex_unlock(&watchdog.lock);
772exit_miscdev:
773 misc_deregister(&watchdog_miscdev);
774exit_reboot:
775 unregister_reboot_notifier(&watchdog_notifier);
776
777 return err;
778}
779
780static int __init f71808e_find(int sioaddr)
781{
782 u16 devid;
783 int err = superio_enter(sioaddr);
784 if (err)
785 return err;
786
787 devid = superio_inw(sioaddr, SIO_REG_MANID);
788 if (devid != SIO_FINTEK_ID) {
27c766aa 789 pr_debug("Not a Fintek device\n");
96cb4eb0
GS
790 err = -ENODEV;
791 goto exit;
792 }
793
794 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
795 switch (devid) {
796 case SIO_F71808_ID:
797 watchdog.type = f71808fg;
798 break;
7977ff6e
LB
799 case SIO_F71862_ID:
800 watchdog.type = f71862fg;
7977ff6e 801 break;
166fbcf8
MS
802 case SIO_F71868_ID:
803 watchdog.type = f71868;
804 break;
df278dac 805 case SIO_F71869_ID:
3017020d 806 case SIO_F71869A_ID:
df278dac
MA
807 watchdog.type = f71869;
808 break;
96cb4eb0
GS
809 case SIO_F71882_ID:
810 watchdog.type = f71882fg;
811 break;
96cb4eb0 812 case SIO_F71889_ID:
dee00abb
GS
813 watchdog.type = f71889fg;
814 break;
96cb4eb0
GS
815 case SIO_F71858_ID:
816 /* Confirmed (by datasheet) not to have a watchdog. */
817 err = -ENODEV;
818 goto exit;
ca2fc5ef
JC
819 case SIO_F81803_ID:
820 watchdog.type = f81803;
821 break;
ea0c03e8
KP
822 case SIO_F81865_ID:
823 watchdog.type = f81865;
14b24a88
JZHPH
824 break;
825 case SIO_F81866_ID:
826 watchdog.type = f81866;
ea0c03e8 827 break;
a155cefb
A
828 case SIO_F81966_ID:
829 watchdog.type = f81966;
830 break;
96cb4eb0 831 default:
27c766aa
JP
832 pr_info("Unrecognized Fintek device: %04x\n",
833 (unsigned int)devid);
96cb4eb0
GS
834 err = -ENODEV;
835 goto exit;
836 }
837
27c766aa 838 pr_info("Found %s watchdog chip, revision %d\n",
96cb4eb0
GS
839 f71808e_names[watchdog.type],
840 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
841exit:
842 superio_exit(sioaddr);
843 return err;
844}
845
846static int __init f71808e_init(void)
847{
848 static const unsigned short addrs[] = { 0x2e, 0x4e };
849 int err = -ENODEV;
850 int i;
851
5edc8c68
AF
852 if (f71862fg_pin != 63 && f71862fg_pin != 56) {
853 pr_err("Invalid argument f71862fg_pin=%d\n", f71862fg_pin);
854 return -EINVAL;
855 }
856
96cb4eb0
GS
857 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
858 err = f71808e_find(addrs[i]);
859 if (err == 0)
860 break;
861 }
862 if (i == ARRAY_SIZE(addrs))
863 return err;
864
865 return watchdog_init(addrs[i]);
866}
867
868static void __exit f71808e_exit(void)
869{
870 if (watchdog_is_running()) {
27c766aa 871 pr_warn("Watchdog timer still running, stopping it\n");
96cb4eb0
GS
872 watchdog_stop();
873 }
874 misc_deregister(&watchdog_miscdev);
875 unregister_reboot_notifier(&watchdog_notifier);
876}
877
878MODULE_DESCRIPTION("F71808E Watchdog Driver");
879MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>");
880MODULE_LICENSE("GPL");
881
882module_init(f71808e_init);
883module_exit(f71808e_exit);