Linux 6.9-rc1
[linux-2.6-microblaze.git] / drivers / watchdog / w83627hf_wdt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *      w83627hf/thf WDT driver
4  *
5  *      (c) Copyright 2013 Guenter Roeck
6  *              converted to watchdog infrastructure
7  *
8  *      (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
9  *              added support for W83627THF.
10  *
11  *      (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
12  *
13  *      Based on advantechwdt.c which is based on wdt.c.
14  *      Original copyright messages:
15  *
16  *      (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
17  *
18  *      (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
19  *                                              All Rights Reserved.
20  *
21  *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
22  *      warranty for any of this software. This material is provided
23  *      "AS-IS" and at no charge.
24  *
25  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
26  */
27
28 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
30 #include <linux/module.h>
31 #include <linux/moduleparam.h>
32 #include <linux/types.h>
33 #include <linux/watchdog.h>
34 #include <linux/ioport.h>
35 #include <linux/init.h>
36 #include <linux/io.h>
37 #include <linux/dmi.h>
38
39 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
40 #define WATCHDOG_TIMEOUT 60             /* 60 sec default timeout */
41
42 static int wdt_io;
43 static int cr_wdt_timeout;      /* WDT timeout register */
44 static int cr_wdt_control;      /* WDT control register */
45 static int cr_wdt_csr;          /* WDT control & status register */
46 static int wdt_cfg_enter = 0x87;/* key to unlock configuration space */
47 static int wdt_cfg_leave = 0xAA;/* key to lock configuration space */
48
49 enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
50              w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p,
51              w83667hg_b, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
52              nct6795, nct6796, nct6102, nct6116 };
53
54 static int timeout;                     /* in seconds */
55 module_param(timeout, int, 0);
56 MODULE_PARM_DESC(timeout,
57                 "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
58                                 __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
59
60 static bool nowayout = WATCHDOG_NOWAYOUT;
61 module_param(nowayout, bool, 0);
62 MODULE_PARM_DESC(nowayout,
63                 "Watchdog cannot be stopped once started (default="
64                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
65
66 static int early_disable;
67 module_param(early_disable, int, 0);
68 MODULE_PARM_DESC(early_disable, "Disable watchdog at boot time (default=0)");
69
70 /*
71  *      Kernel methods.
72  */
73
74 #define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
75 #define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register
76                                                         (same as EFER) */
77 #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
78
79 #define W83627HF_LD_WDT         0x08
80
81 #define W83627HF_ID             0x52
82 #define W83627S_ID              0x59
83 #define W83697HF_ID             0x60
84 #define W83697UG_ID             0x68
85 #define W83637HF_ID             0x70
86 #define W83627THF_ID            0x82
87 #define W83687THF_ID            0x85
88 #define W83627EHF_ID            0x88
89 #define W83627DHG_ID            0xa0
90 #define W83627UHG_ID            0xa2
91 #define W83667HG_ID             0xa5
92 #define W83627DHG_P_ID          0xb0
93 #define W83667HG_B_ID           0xb3
94 #define NCT6775_ID              0xb4
95 #define NCT6776_ID              0xc3
96 #define NCT6102_ID              0xc4
97 #define NCT6116_ID              0xd2
98 #define NCT6779_ID              0xc5
99 #define NCT6791_ID              0xc8
100 #define NCT6792_ID              0xc9
101 #define NCT6793_ID              0xd1
102 #define NCT6795_ID              0xd3
103 #define NCT6796_ID              0xd4    /* also NCT9697D, NCT9698D */
104
105 #define W83627HF_WDT_TIMEOUT    0xf6
106 #define W83697HF_WDT_TIMEOUT    0xf4
107 #define NCT6102D_WDT_TIMEOUT    0xf1
108
109 #define W83627HF_WDT_CONTROL    0xf5
110 #define W83697HF_WDT_CONTROL    0xf3
111 #define NCT6102D_WDT_CONTROL    0xf0
112
113 #define W836X7HF_WDT_CSR        0xf7
114 #define NCT6102D_WDT_CSR        0xf2
115
116 #define WDT_CSR_STATUS          0x10
117 #define WDT_CSR_KBD             0x40
118 #define WDT_CSR_MOUSE           0x80
119
120 static void superio_outb(int reg, int val)
121 {
122         outb(reg, WDT_EFER);
123         outb(val, WDT_EFDR);
124 }
125
126 static inline int superio_inb(int reg)
127 {
128         outb(reg, WDT_EFER);
129         return inb(WDT_EFDR);
130 }
131
132 static int superio_enter(void)
133 {
134         if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME))
135                 return -EBUSY;
136
137         outb_p(wdt_cfg_enter, WDT_EFER); /* Enter extended function mode */
138         outb_p(wdt_cfg_enter, WDT_EFER); /* Again according to manual */
139
140         return 0;
141 }
142
143 static void superio_select(int ld)
144 {
145         superio_outb(0x07, ld);
146 }
147
148 static void superio_exit(void)
149 {
150         outb_p(wdt_cfg_leave, WDT_EFER); /* Leave extended function mode */
151         release_region(wdt_io, 2);
152 }
153
154 static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
155 {
156         int ret;
157         unsigned char t;
158
159         ret = superio_enter();
160         if (ret)
161                 return ret;
162
163         superio_select(W83627HF_LD_WDT);
164
165         /* set CR30 bit 0 to activate GPIO2 */
166         t = superio_inb(0x30);
167         if (!(t & 0x01))
168                 superio_outb(0x30, t | 0x01);
169
170         switch (chip) {
171         case w83627hf:
172         case w83627s:
173                 t = superio_inb(0x2B) & ~0x10;
174                 superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
175                 break;
176         case w83697hf:
177                 /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
178                 t = superio_inb(0x29) & ~0x60;
179                 t |= 0x20;
180                 superio_outb(0x29, t);
181                 break;
182         case w83697ug:
183                 /* Set pin 118 to WDTO# mode */
184                 t = superio_inb(0x2b) & ~0x04;
185                 superio_outb(0x2b, t);
186                 break;
187         case w83627thf:
188                 t = (superio_inb(0x2B) & ~0x08) | 0x04;
189                 superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
190                 break;
191         case w83627dhg:
192         case w83627dhg_p:
193                 t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
194                 superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
195                 t = superio_inb(cr_wdt_control);
196                 t |= 0x02;      /* enable the WDTO# output low pulse
197                                  * to the KBRST# pin */
198                 superio_outb(cr_wdt_control, t);
199                 break;
200         case w83637hf:
201                 break;
202         case w83687thf:
203                 t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */
204                 superio_outb(0x2C, t);
205                 break;
206         case w83627ehf:
207         case w83627uhg:
208         case w83667hg:
209         case w83667hg_b:
210         case nct6775:
211         case nct6776:
212         case nct6779:
213         case nct6791:
214         case nct6792:
215         case nct6793:
216         case nct6795:
217         case nct6796:
218         case nct6102:
219         case nct6116:
220                 /*
221                  * These chips have a fixed WDTO# output pin (W83627UHG),
222                  * or support more than one WDTO# output pin.
223                  * Don't touch its configuration, and hope the BIOS
224                  * does the right thing.
225                  */
226                 t = superio_inb(cr_wdt_control);
227                 t |= 0x02;      /* enable the WDTO# output low pulse
228                                  * to the KBRST# pin */
229                 superio_outb(cr_wdt_control, t);
230                 break;
231         default:
232                 break;
233         }
234
235         t = superio_inb(cr_wdt_timeout);
236         if (t != 0) {
237                 if (early_disable) {
238                         pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
239                         superio_outb(cr_wdt_timeout, 0);
240                 } else {
241                         pr_info("Watchdog already running. Resetting timeout to %d sec\n",
242                                 wdog->timeout);
243                         superio_outb(cr_wdt_timeout, wdog->timeout);
244                 }
245         }
246
247         /* set second mode & disable keyboard turning off watchdog */
248         t = superio_inb(cr_wdt_control) & ~0x0C;
249         superio_outb(cr_wdt_control, t);
250
251         t = superio_inb(cr_wdt_csr);
252         if (t & WDT_CSR_STATUS)
253                 wdog->bootstatus |= WDIOF_CARDRESET;
254
255         /* reset status, disable keyboard & mouse turning off watchdog */
256         t &= ~(WDT_CSR_STATUS | WDT_CSR_KBD | WDT_CSR_MOUSE);
257         superio_outb(cr_wdt_csr, t);
258
259         superio_exit();
260
261         return 0;
262 }
263
264 static int wdt_set_time(unsigned int timeout)
265 {
266         int ret;
267
268         ret = superio_enter();
269         if (ret)
270                 return ret;
271
272         superio_select(W83627HF_LD_WDT);
273         superio_outb(cr_wdt_timeout, timeout);
274         superio_exit();
275
276         return 0;
277 }
278
279 static int wdt_start(struct watchdog_device *wdog)
280 {
281         return wdt_set_time(wdog->timeout);
282 }
283
284 static int wdt_stop(struct watchdog_device *wdog)
285 {
286         return wdt_set_time(0);
287 }
288
289 static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
290 {
291         wdog->timeout = timeout;
292
293         return 0;
294 }
295
296 static unsigned int wdt_get_time(struct watchdog_device *wdog)
297 {
298         unsigned int timeleft;
299         int ret;
300
301         ret = superio_enter();
302         if (ret)
303                 return 0;
304
305         superio_select(W83627HF_LD_WDT);
306         timeleft = superio_inb(cr_wdt_timeout);
307         superio_exit();
308
309         return timeleft;
310 }
311
312 /*
313  *      Kernel Interfaces
314  */
315
316 static const struct watchdog_info wdt_info = {
317         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
318         .identity = "W83627HF Watchdog",
319 };
320
321 static const struct watchdog_ops wdt_ops = {
322         .owner = THIS_MODULE,
323         .start = wdt_start,
324         .stop = wdt_stop,
325         .set_timeout = wdt_set_timeout,
326         .get_timeleft = wdt_get_time,
327 };
328
329 static struct watchdog_device wdt_dev = {
330         .info = &wdt_info,
331         .ops = &wdt_ops,
332         .timeout = WATCHDOG_TIMEOUT,
333         .min_timeout = 1,
334         .max_timeout = 255,
335 };
336
337 /*
338  *      The WDT needs to learn about soft shutdowns in order to
339  *      turn the timebomb registers off.
340  */
341
342 static int wdt_find(int addr)
343 {
344         u8 val;
345         int ret;
346
347         cr_wdt_timeout = W83627HF_WDT_TIMEOUT;
348         cr_wdt_control = W83627HF_WDT_CONTROL;
349         cr_wdt_csr = W836X7HF_WDT_CSR;
350
351         ret = superio_enter();
352         if (ret)
353                 return ret;
354         superio_select(W83627HF_LD_WDT);
355         val = superio_inb(0x20);
356         switch (val) {
357         case W83627HF_ID:
358                 ret = w83627hf;
359                 break;
360         case W83627S_ID:
361                 ret = w83627s;
362                 break;
363         case W83697HF_ID:
364                 ret = w83697hf;
365                 cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
366                 cr_wdt_control = W83697HF_WDT_CONTROL;
367                 break;
368         case W83697UG_ID:
369                 ret = w83697ug;
370                 cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
371                 cr_wdt_control = W83697HF_WDT_CONTROL;
372                 break;
373         case W83637HF_ID:
374                 ret = w83637hf;
375                 break;
376         case W83627THF_ID:
377                 ret = w83627thf;
378                 break;
379         case W83687THF_ID:
380                 ret = w83687thf;
381                 break;
382         case W83627EHF_ID:
383                 ret = w83627ehf;
384                 break;
385         case W83627DHG_ID:
386                 ret = w83627dhg;
387                 break;
388         case W83627DHG_P_ID:
389                 ret = w83627dhg_p;
390                 break;
391         case W83627UHG_ID:
392                 ret = w83627uhg;
393                 break;
394         case W83667HG_ID:
395                 ret = w83667hg;
396                 break;
397         case W83667HG_B_ID:
398                 ret = w83667hg_b;
399                 break;
400         case NCT6775_ID:
401                 ret = nct6775;
402                 break;
403         case NCT6776_ID:
404                 ret = nct6776;
405                 break;
406         case NCT6779_ID:
407                 ret = nct6779;
408                 break;
409         case NCT6791_ID:
410                 ret = nct6791;
411                 break;
412         case NCT6792_ID:
413                 ret = nct6792;
414                 break;
415         case NCT6793_ID:
416                 ret = nct6793;
417                 break;
418         case NCT6795_ID:
419                 ret = nct6795;
420                 break;
421         case NCT6796_ID:
422                 ret = nct6796;
423                 break;
424         case NCT6102_ID:
425                 ret = nct6102;
426                 cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
427                 cr_wdt_control = NCT6102D_WDT_CONTROL;
428                 cr_wdt_csr = NCT6102D_WDT_CSR;
429                 break;
430         case NCT6116_ID:
431                 ret = nct6116;
432                 cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
433                 cr_wdt_control = NCT6102D_WDT_CONTROL;
434                 cr_wdt_csr = NCT6102D_WDT_CSR;
435                 break;
436         case 0xff:
437                 ret = -ENODEV;
438                 break;
439         default:
440                 ret = -ENODEV;
441                 pr_err("Unsupported chip ID: 0x%02x\n", val);
442                 break;
443         }
444         superio_exit();
445         return ret;
446 }
447
448 /*
449  * On some systems, the NCT6791D comes with a companion chip and the
450  * watchdog function is in this companion chip. We must use a different
451  * unlocking sequence to access the companion chip.
452  */
453 static int __init wdt_use_alt_key(const struct dmi_system_id *d)
454 {
455         wdt_cfg_enter = 0x88;
456         wdt_cfg_leave = 0xBB;
457
458         return 0;
459 }
460
461 static const struct dmi_system_id wdt_dmi_table[] __initconst = {
462         {
463                 .matches = {
464                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "INVES"),
465                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CTS"),
466                         DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "INVES"),
467                         DMI_EXACT_MATCH(DMI_BOARD_NAME, "SHARKBAY"),
468                 },
469                 .callback = wdt_use_alt_key,
470         },
471         {}
472 };
473
474 static int __init wdt_init(void)
475 {
476         int ret;
477         int chip;
478         static const char * const chip_name[] = {
479                 "W83627HF",
480                 "W83627S",
481                 "W83697HF",
482                 "W83697UG",
483                 "W83637HF",
484                 "W83627THF",
485                 "W83687THF",
486                 "W83627EHF",
487                 "W83627DHG",
488                 "W83627UHG",
489                 "W83667HG",
490                 "W83667DHG-P",
491                 "W83667HG-B",
492                 "NCT6775",
493                 "NCT6776",
494                 "NCT6779",
495                 "NCT6791",
496                 "NCT6792",
497                 "NCT6793",
498                 "NCT6795",
499                 "NCT6796",
500                 "NCT6102",
501                 "NCT6116",
502         };
503
504         /* Apply system-specific quirks */
505         dmi_check_system(wdt_dmi_table);
506
507         wdt_io = 0x2e;
508         chip = wdt_find(0x2e);
509         if (chip < 0) {
510                 wdt_io = 0x4e;
511                 chip = wdt_find(0x4e);
512                 if (chip < 0)
513                         return chip;
514         }
515
516         pr_info("WDT driver for %s Super I/O chip initialising\n",
517                 chip_name[chip]);
518
519         watchdog_init_timeout(&wdt_dev, timeout, NULL);
520         watchdog_set_nowayout(&wdt_dev, nowayout);
521         watchdog_stop_on_reboot(&wdt_dev);
522
523         ret = w83627hf_init(&wdt_dev, chip);
524         if (ret) {
525                 pr_err("failed to initialize watchdog (err=%d)\n", ret);
526                 return ret;
527         }
528
529         ret = watchdog_register_device(&wdt_dev);
530         if (ret)
531                 return ret;
532
533         pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
534                 wdt_dev.timeout, nowayout);
535
536         return ret;
537 }
538
539 static void __exit wdt_exit(void)
540 {
541         watchdog_unregister_device(&wdt_dev);
542 }
543
544 module_init(wdt_init);
545 module_exit(wdt_exit);
546
547 MODULE_LICENSE("GPL");
548 MODULE_AUTHOR("Pádraig  Brady <P@draigBrady.com>");
549 MODULE_DESCRIPTION("w83627hf/thf WDT driver");