hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/watchdog/w83627hf_wdt.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * w83627hf/thf WDT driver
34 *
....@@ -17,11 +18,6 @@
1718 * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
1819 * All Rights Reserved.
1920 *
20
- * This program is free software; you can redistribute it and/or
21
- * modify it under the terms of the GNU General Public License
22
- * as published by the Free Software Foundation; either version
23
- * 2 of the License, or (at your option) any later version.
24
- *
2521 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
2622 * warranty for any of this software. This material is provided
2723 * "AS-IS" and at no charge.
....@@ -38,6 +34,7 @@
3834 #include <linux/ioport.h>
3935 #include <linux/init.h>
4036 #include <linux/io.h>
37
+#include <linux/dmi.h>
4138
4239 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
4340 #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
....@@ -46,11 +43,13 @@
4643 static int cr_wdt_timeout; /* WDT timeout register */
4744 static int cr_wdt_control; /* WDT control register */
4845 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 */
4948
5049 enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
5150 w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p,
5251 w83667hg_b, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
53
- nct6795, nct6796, nct6102 };
52
+ nct6795, nct6796, nct6102, nct6116 };
5453
5554 static int timeout; /* in seconds */
5655 module_param(timeout, int, 0);
....@@ -95,6 +94,7 @@
9594 #define NCT6775_ID 0xb4
9695 #define NCT6776_ID 0xc3
9796 #define NCT6102_ID 0xc4
97
+#define NCT6116_ID 0xd2
9898 #define NCT6779_ID 0xc5
9999 #define NCT6791_ID 0xc8
100100 #define NCT6792_ID 0xc9
....@@ -130,8 +130,8 @@
130130 if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME))
131131 return -EBUSY;
132132
133
- outb_p(0x87, WDT_EFER); /* Enter extended function mode */
134
- outb_p(0x87, WDT_EFER); /* Again according to manual */
133
+ outb_p(wdt_cfg_enter, WDT_EFER); /* Enter extended function mode */
134
+ outb_p(wdt_cfg_enter, WDT_EFER); /* Again according to manual */
135135
136136 return 0;
137137 }
....@@ -143,7 +143,7 @@
143143
144144 static void superio_exit(void)
145145 {
146
- outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
146
+ outb_p(wdt_cfg_leave, WDT_EFER); /* Leave extended function mode */
147147 release_region(wdt_io, 2);
148148 }
149149
....@@ -212,6 +212,7 @@
212212 case nct6795:
213213 case nct6796:
214214 case nct6102:
215
+ case nct6116:
215216 /*
216217 * These chips have a fixed WDTO# output pin (W83627UHG),
217218 * or support more than one WDTO# output pin.
....@@ -418,6 +419,12 @@
418419 cr_wdt_control = NCT6102D_WDT_CONTROL;
419420 cr_wdt_csr = NCT6102D_WDT_CSR;
420421 break;
422
+ case NCT6116_ID:
423
+ ret = nct6116;
424
+ cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
425
+ cr_wdt_control = NCT6102D_WDT_CONTROL;
426
+ cr_wdt_csr = NCT6102D_WDT_CSR;
427
+ break;
421428 case 0xff:
422429 ret = -ENODEV;
423430 break;
....@@ -429,6 +436,32 @@
429436 superio_exit();
430437 return ret;
431438 }
439
+
440
+/*
441
+ * On some systems, the NCT6791D comes with a companion chip and the
442
+ * watchdog function is in this companion chip. We must use a different
443
+ * unlocking sequence to access the companion chip.
444
+ */
445
+static int __init wdt_use_alt_key(const struct dmi_system_id *d)
446
+{
447
+ wdt_cfg_enter = 0x88;
448
+ wdt_cfg_leave = 0xBB;
449
+
450
+ return 0;
451
+}
452
+
453
+static const struct dmi_system_id wdt_dmi_table[] __initconst = {
454
+ {
455
+ .matches = {
456
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "INVES"),
457
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CTS"),
458
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "INVES"),
459
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SHARKBAY"),
460
+ },
461
+ .callback = wdt_use_alt_key,
462
+ },
463
+ {}
464
+};
432465
433466 static int __init wdt_init(void)
434467 {
....@@ -457,8 +490,12 @@
457490 "NCT6795",
458491 "NCT6796",
459492 "NCT6102",
493
+ "NCT6116",
460494 };
461495
496
+ /* Apply system-specific quirks */
497
+ dmi_check_system(wdt_dmi_table);
498
+
462499 wdt_io = 0x2e;
463500 chip = wdt_find(0x2e);
464501 if (chip < 0) {