1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011 Sandvine Incorporated ULC. 5 * Copyright (c) 2012 iXsystems, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 /* 30 * Support for Winbond watchdog. 31 * 32 * With minor abstractions it might be possible to add support for other 33 * different Winbond Super I/O chips as well. Winbond seems to have four 34 * different types of chips, four different ways to get into extended config 35 * mode. 36 * 37 * Note: there is no serialization between the debugging sysctl handlers and 38 * the watchdog functions and possibly others poking the registers at the same 39 * time. For that at least possibly interfering sysctls are hidden by default. 40 */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include <sys/param.h> 46 #include <sys/kernel.h> 47 #include <sys/systm.h> 48 #include <sys/bus.h> 49 #include <sys/eventhandler.h> 50 #include <sys/lock.h> 51 #include <sys/module.h> 52 #include <sys/rman.h> 53 #include <sys/sbuf.h> 54 #include <sys/sysctl.h> 55 #include <sys/watchdog.h> 56 57 #include <isa/isavar.h> 58 59 #include <machine/bus.h> 60 #include <machine/resource.h> 61 62 /* 63 * Global registers. 64 */ 65 #define WB_DEVICE_ID_REG 0x20 /* Device ID */ 66 #define WB_DEVICE_REV_REG 0x21 /* Device revision */ 67 #define WB_CR26 0x26 /* Bit6: HEFRAS (base port selector) */ 68 69 /* LDN selection. */ 70 #define WB_LDN_REG 0x07 71 #define WB_LDN_REG_LDN8 0x08 /* GPIO 2, Watchdog */ 72 73 /* 74 * LDN8 (GPIO 2, Watchdog) specific registers and options. 75 */ 76 /* CR30: LDN8 activation control. */ 77 #define WB_LDN8_CR30 0x30 78 #define WB_LDN8_CR30_ACTIVE 0x01 /* 1: LD active */ 79 80 /* CRF5: Watchdog scale, P20. Mapped to reg_1. */ 81 #define WB_LDN8_CRF5 0xF5 82 #define WB_LDN8_CRF5_SCALE 0x08 /* 0: 1s, 1: 60s */ 83 #define WB_LDN8_CRF5_KEYB_P20 0x04 /* 1: keyb P20 forces timeout */ 84 #define WB_LDN8_CRF5_KBRST 0x02 /* 1: timeout causes pin60 kbd reset */ 85 86 /* CRF6: Watchdog Timeout (0 == off). Mapped to reg_timeout. */ 87 #define WB_LDN8_CRF6 0xF6 88 89 /* CRF7: Watchdog mouse, keyb, force, .. Mapped to reg_2. */ 90 #define WB_LDN8_CRF7 0xF7 91 #define WB_LDN8_CRF7_MOUSE 0x80 /* 1: mouse irq resets wd timer */ 92 #define WB_LDN8_CRF7_KEYB 0x40 /* 1: keyb irq resets wd timer */ 93 #define WB_LDN8_CRF7_FORCE 0x20 /* 1: force timeout (self-clear) */ 94 #define WB_LDN8_CRF7_TS 0x10 /* 0: counting, 1: fired */ 95 #define WB_LDN8_CRF7_IRQS 0x0f /* irq source for watchdog, 2 == SMI */ 96 97 enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf, 98 w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, 99 w83627dhg_p, w83667hg_b, nct6775, nct6776, nct6779, nct6791, 100 nct6792, nct6793, nct6795, nct6102 }; 101 102 struct wb_softc { 103 device_t dev; 104 struct resource *portres; 105 bus_space_tag_t bst; 106 bus_space_handle_t bsh; 107 int rid; 108 eventhandler_tag ev_tag; 109 int (*ext_cfg_enter_f)(struct wb_softc *, u_short); 110 void (*ext_cfg_exit_f)(struct wb_softc *, u_short); 111 enum chips chip; 112 uint8_t ctl_reg; 113 uint8_t time_reg; 114 uint8_t csr_reg; 115 int debug_verbose; 116 117 /* 118 * Special feature to let the watchdog fire at a different 119 * timeout as set by watchdog(4) but still use that API to 120 * re-load it periodically. 121 */ 122 unsigned int timeout_override; 123 124 /* 125 * Space to save current state temporary and for sysctls. 126 * We want to know the timeout value and usually need two 127 * additional registers for options. Do not name them by 128 * register as these might be different by chip. 129 */ 130 uint8_t reg_timeout; 131 uint8_t reg_1; 132 uint8_t reg_2; 133 }; 134 135 static int ext_cfg_enter_0x87_0x87(struct wb_softc *, u_short); 136 static void ext_cfg_exit_0xaa(struct wb_softc *, u_short); 137 138 struct winbond_superio_cfg { 139 uint8_t efer; /* and efir */ 140 int (*ext_cfg_enter_f)(struct wb_softc *, u_short); 141 void (*ext_cfg_exit_f)(struct wb_softc *, u_short); 142 } probe_addrs[] = { 143 { 144 .efer = 0x2e, 145 .ext_cfg_enter_f = ext_cfg_enter_0x87_0x87, 146 .ext_cfg_exit_f = ext_cfg_exit_0xaa, 147 }, 148 { 149 .efer = 0x4e, 150 .ext_cfg_enter_f = ext_cfg_enter_0x87_0x87, 151 .ext_cfg_exit_f = ext_cfg_exit_0xaa, 152 }, 153 }; 154 155 struct winbond_vendor_device_id { 156 uint8_t device_id; 157 enum chips chip; 158 const char * descr; 159 } wb_devs[] = { 160 { 161 .device_id = 0x52, 162 .chip = w83627hf, 163 .descr = "Winbond 83627HF/F/HG/G", 164 }, 165 { 166 .device_id = 0x59, 167 .chip = w83627s, 168 .descr = "Winbond 83627S", 169 }, 170 { 171 .device_id = 0x60, 172 .chip = w83697hf, 173 .descr = "Winbond 83697HF", 174 }, 175 { 176 .device_id = 0x68, 177 .chip = w83697ug, 178 .descr = "Winbond 83697UG", 179 }, 180 { 181 .device_id = 0x70, 182 .chip = w83637hf, 183 .descr = "Winbond 83637HF", 184 }, 185 { 186 .device_id = 0x82, 187 .chip = w83627thf, 188 .descr = "Winbond 83627THF", 189 }, 190 { 191 .device_id = 0x85, 192 .chip = w83687thf, 193 .descr = "Winbond 83687THF", 194 }, 195 { 196 .device_id = 0x88, 197 .chip = w83627ehf, 198 .descr = "Winbond 83627EHF", 199 }, 200 { 201 .device_id = 0xa0, 202 .chip = w83627dhg, 203 .descr = "Winbond 83627DHG", 204 }, 205 { 206 .device_id = 0xa2, 207 .chip = w83627uhg, 208 .descr = "Winbond 83627UHG", 209 }, 210 { 211 .device_id = 0xa5, 212 .chip = w83667hg, 213 .descr = "Winbond 83667HG", 214 }, 215 { 216 .device_id = 0xb0, 217 .chip = w83627dhg_p, 218 .descr = "Winbond 83627DHG-P", 219 }, 220 { 221 .device_id = 0xb3, 222 .chip = w83667hg_b, 223 .descr = "Winbond 83667HG-B", 224 }, 225 { 226 .device_id = 0xb4, 227 .chip = nct6775, 228 .descr = "Nuvoton NCT6775", 229 }, 230 { 231 .device_id = 0xc3, 232 .chip = nct6776, 233 .descr = "Nuvoton NCT6776", 234 }, 235 { 236 .device_id = 0xc4, 237 .chip = nct6102, 238 .descr = "Nuvoton NCT6102", 239 }, 240 { 241 .device_id = 0xc5, 242 .chip = nct6779, 243 .descr = "Nuvoton NCT6779", 244 }, 245 { 246 .device_id = 0xc8, 247 .chip = nct6791, 248 .descr = "Nuvoton NCT6791", 249 }, 250 { 251 .device_id = 0xc9, 252 .chip = nct6792, 253 .descr = "Nuvoton NCT6792", 254 }, 255 { 256 .device_id = 0xd1, 257 .chip = nct6793, 258 .descr = "Nuvoton NCT6793", 259 }, 260 { 261 .device_id = 0xd3, 262 .chip = nct6795, 263 .descr = "Nuvoton NCT6795", 264 }, 265 }; 266 267 static void 268 write_efir_1(struct wb_softc *sc, u_short baseport, uint8_t value) 269 { 270 271 MPASS(sc != NULL || baseport != 0); 272 if (sc != NULL) 273 bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value)); 274 else 275 outb(baseport, value); 276 } 277 278 static uint8_t __unused 279 read_efir_1(struct wb_softc *sc, u_short baseport) 280 { 281 282 MPASS(sc != NULL || baseport != 0); 283 if (sc != NULL) 284 return (bus_space_read_1((sc)->bst, (sc)->bsh, 0)); 285 else 286 return (inb(baseport)); 287 } 288 289 static void 290 write_efdr_1(struct wb_softc *sc, u_short baseport, uint8_t value) 291 { 292 293 MPASS(sc != NULL || baseport != 0); 294 if (sc != NULL) 295 bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value)); 296 else 297 outb(baseport + 1, value); 298 } 299 300 static uint8_t 301 read_efdr_1(struct wb_softc *sc, u_short baseport) 302 { 303 304 MPASS(sc != NULL || baseport != 0); 305 if (sc != NULL) 306 return (bus_space_read_1((sc)->bst, (sc)->bsh, 1)); 307 else 308 return (inb(baseport + 1)); 309 } 310 311 static void 312 write_reg(struct wb_softc *sc, uint8_t reg, uint8_t value) 313 { 314 315 write_efir_1(sc, 0, reg); 316 write_efdr_1(sc, 0, value); 317 } 318 319 static uint8_t 320 read_reg(struct wb_softc *sc, uint8_t reg) 321 { 322 323 write_efir_1(sc, 0, reg); 324 return (read_efdr_1(sc, 0)); 325 } 326 327 /* 328 * Return the watchdog related registers as we last read them. This will 329 * usually not give the current timeout or state on whether the watchdog 330 * fired. 331 */ 332 static int 333 sysctl_wb_debug(SYSCTL_HANDLER_ARGS) 334 { 335 struct wb_softc *sc; 336 struct sbuf sb; 337 int error; 338 339 sc = arg1; 340 341 sbuf_new_for_sysctl(&sb, NULL, 64, req); 342 343 sbuf_printf(&sb, "LDN8 (GPIO2, Watchdog): "); 344 sbuf_printf(&sb, "CR%02X 0x%02x ", sc->ctl_reg, sc->reg_1); 345 sbuf_printf(&sb, "CR%02X 0x%02x ", sc->time_reg, sc->reg_timeout); 346 sbuf_printf(&sb, "CR%02X 0x%02x", sc->csr_reg, sc->reg_2); 347 348 error = sbuf_finish(&sb); 349 sbuf_delete(&sb); 350 return (error); 351 } 352 353 /* 354 * Read the current values before returning them. Given this might poke 355 * the registers the same time as the watchdog, this sysctl handler should 356 * be marked CTLFLAG_SKIP to not show up by default. 357 */ 358 static int 359 sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS) 360 { 361 struct wb_softc *sc; 362 363 sc = arg1; 364 365 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 366 return (ENXIO); 367 368 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 369 write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8); 370 371 sc->reg_1 = read_reg(sc, sc->ctl_reg); 372 sc->reg_timeout = read_reg(sc, sc->time_reg); 373 sc->reg_2 = read_reg(sc, sc->csr_reg); 374 375 (*sc->ext_cfg_exit_f)(sc, 0); 376 377 return (sysctl_wb_debug(oidp, arg1, arg2, req)); 378 } 379 380 /* 381 * Sysctl handlers to force a watchdog timeout or to test the NMI functionality 382 * works as expetced. 383 * For testing we could set a test_nmi flag in the softc that, in case of NMI, a 384 * callback function from trap.c could check whether we fired and not report the 385 * timeout but clear the flag for the sysctl again. This is interesting given a 386 * lot of boards have jumpers to change the action on watchdog timeout or 387 * disable the watchdog completely. 388 * XXX-BZ notyet: currently no general infrastructure exists to do this. 389 */ 390 static int 391 sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS) 392 { 393 struct wb_softc *sc; 394 int error, test, val; 395 396 sc = arg1; 397 test = arg2; 398 399 #ifdef notyet 400 val = sc->test_nmi; 401 #else 402 val = 0; 403 #endif 404 error = sysctl_handle_int(oidp, &val, 0, req); 405 if (error || !req->newptr) 406 return (error); 407 408 #ifdef notyet 409 /* Manually clear the test for a value of 0 and do nothing else. */ 410 if (test && val == 0) { 411 sc->test_nmi = 0; 412 return (0); 413 } 414 #endif 415 416 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 417 return (ENXIO); 418 419 #ifdef notyet 420 /* 421 * If we are testing the NMI functionality, set the flag before 422 * forcing the timeout. 423 */ 424 if (test) 425 sc->test_nmi = 1; 426 #endif 427 428 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 429 write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8); 430 431 /* Force watchdog to fire. */ 432 sc->reg_2 = read_reg(sc, sc->csr_reg); 433 sc->reg_2 |= WB_LDN8_CRF7_FORCE; 434 write_reg(sc, sc->csr_reg, sc->reg_2); 435 436 (*sc->ext_cfg_exit_f)(sc, 0); 437 438 return (0); 439 } 440 441 /* 442 * Print current watchdog state. 443 * 444 * Note: it is the responsibility of the caller to update the registers 445 * upfront. 446 */ 447 static void 448 wb_print_state(struct wb_softc *sc, const char *msg) 449 { 450 451 device_printf(sc->dev, "%s%sWatchdog %sabled. %s" 452 "Scaling by %ds, timer at %d (%s=%ds%s). " 453 "CRF5 0x%02x CRF7 0x%02x\n", 454 (msg != NULL) ? msg : "", (msg != NULL) ? ": " : "", 455 (sc->reg_timeout > 0x00) ? "en" : "dis", 456 (sc->reg_2 & WB_LDN8_CRF7_TS) ? "Watchdog fired. " : "", 457 (sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1, 458 sc->reg_timeout, 459 (sc->reg_timeout > 0x00) ? "<" : "", 460 sc->reg_timeout * ((sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1), 461 (sc->reg_timeout > 0x00) ? " left" : "", 462 sc->reg_1, sc->reg_2); 463 } 464 465 /* 466 * Functions to enter and exit extended function mode. Possibly shared 467 * between different chips. 468 */ 469 static int 470 ext_cfg_enter_0x87_0x87(struct wb_softc *sc, u_short baseport) 471 { 472 473 /* 474 * Enable extended function mode. 475 * Winbond does not allow us to validate so always return success. 476 */ 477 write_efir_1(sc, baseport, 0x87); 478 write_efir_1(sc, baseport, 0x87); 479 480 return (0); 481 } 482 483 static void 484 ext_cfg_exit_0xaa(struct wb_softc *sc, u_short baseport) 485 { 486 487 write_efir_1(sc, baseport, 0xaa); 488 } 489 490 /* 491 * (Re)load the watchdog counter depending on timeout. A timeout of 0 will 492 * disable the watchdog. 493 */ 494 static int 495 wb_set_watchdog(struct wb_softc *sc, unsigned int timeout) 496 { 497 498 if (timeout != 0) { 499 /* 500 * In case an override is set, let it override. It may lead 501 * to strange results as we do not check the input of the sysctl. 502 */ 503 if (sc->timeout_override > 0) 504 timeout = sc->timeout_override; 505 506 /* Make sure we support the requested timeout. */ 507 if (timeout > 255 * 60) 508 return (EINVAL); 509 } 510 511 if (sc->debug_verbose) 512 wb_print_state(sc, "Before watchdog counter (re)load"); 513 514 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 515 return (ENXIO); 516 517 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */ 518 write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8); 519 520 if (timeout == 0) { 521 /* Disable watchdog. */ 522 sc->reg_timeout = 0; 523 write_reg(sc, sc->time_reg, sc->reg_timeout); 524 525 } else { 526 /* Read current scaling factor. */ 527 sc->reg_1 = read_reg(sc, sc->ctl_reg); 528 529 if (timeout > 255) { 530 /* Set scaling factor to 60s. */ 531 sc->reg_1 |= WB_LDN8_CRF5_SCALE; 532 sc->reg_timeout = (timeout / 60); 533 if (timeout % 60) 534 sc->reg_timeout++; 535 } else { 536 /* Set scaling factor to 1s. */ 537 sc->reg_1 &= ~WB_LDN8_CRF5_SCALE; 538 sc->reg_timeout = timeout; 539 } 540 541 /* In case we fired before we need to clear to fire again. */ 542 sc->reg_2 = read_reg(sc, sc->csr_reg); 543 if (sc->reg_2 & WB_LDN8_CRF7_TS) { 544 sc->reg_2 &= ~WB_LDN8_CRF7_TS; 545 write_reg(sc, sc->csr_reg, sc->reg_2); 546 } 547 548 /* Write back scaling factor. */ 549 write_reg(sc, sc->ctl_reg, sc->reg_1); 550 551 /* Set timer and arm/reset the watchdog. */ 552 write_reg(sc, sc->time_reg, sc->reg_timeout); 553 } 554 555 (*sc->ext_cfg_exit_f)(sc, 0); 556 557 if (sc->debug_verbose) 558 wb_print_state(sc, "After watchdog counter (re)load"); 559 return (0); 560 } 561 562 /* 563 * watchdog(9) EVENTHANDLER function implementation to (re)load the counter 564 * with the given timeout or disable the watchdog. 565 */ 566 static void 567 wb_watchdog_fn(void *private, u_int cmd, int *error) 568 { 569 struct wb_softc *sc; 570 unsigned int timeout; 571 int e; 572 573 sc = private; 574 KASSERT(sc != NULL, ("%s: watchdog handler function called without " 575 "softc.", __func__)); 576 577 cmd &= WD_INTERVAL; 578 if (cmd > 0 && cmd <= 63) { 579 /* Reset (and arm) watchdog. */ 580 timeout = ((uint64_t)1 << cmd) / 1000000000; 581 if (timeout == 0) 582 timeout = 1; 583 e = wb_set_watchdog(sc, timeout); 584 if (e == 0) { 585 if (error != NULL) 586 *error = 0; 587 } else { 588 /* On error, try to make sure the WD is disabled. */ 589 wb_set_watchdog(sc, 0); 590 } 591 592 } else { 593 /* Disable watchdog. */ 594 e = wb_set_watchdog(sc, 0); 595 if (e != 0 && cmd == 0 && error != NULL) { 596 /* Failed to disable watchdog. */ 597 *error = EOPNOTSUPP; 598 } 599 } 600 } 601 602 /* 603 * Probe/attach the Winbond Super I/O chip. 604 * 605 * Initial abstraction to possibly support more chips: 606 * - Iterate over the well known base ports, try to enable extended function 607 * mode and read and match the device ID and device revision. Unfortunately 608 * the Vendor ID is in the hardware monitoring section accessible by different 609 * base ports only. 610 * - Also HEFRAS, which would tell use the base port, is only accessible after 611 * entering extended function mode, for which the base port is needed. 612 * At least check HEFRAS to match the current base port we are probing. 613 * - On match set the description, remember functions to enter/exit extended 614 * function mode as well as the base port. 615 */ 616 static int 617 wb_probe_enable(device_t dev, int probe) 618 { 619 struct wb_softc *sc; 620 int error, found, i, j; 621 uint8_t dev_id, dev_rev, cr26; 622 char buf[128]; 623 624 if (dev == NULL) 625 sc = NULL; 626 else { 627 sc = device_get_softc(dev); 628 bzero(sc, sizeof(*sc)); 629 sc->dev = dev; 630 } 631 632 error = ENXIO; 633 found = 0; 634 for (i = 0; i < nitems(probe_addrs); i++) { 635 636 if (sc != NULL) { 637 /* Allocate bus resources for IO index/data register access. */ 638 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 639 probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE); 640 if (sc->portres == NULL) 641 continue; 642 sc->bst = rman_get_bustag(sc->portres); 643 sc->bsh = rman_get_bushandle(sc->portres); 644 } 645 646 error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer); 647 if (error != 0) 648 goto cleanup; 649 650 /* Identify the SuperIO chip. */ 651 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_ID_REG); 652 dev_id = read_efdr_1(sc, probe_addrs[i].efer); 653 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_REV_REG); 654 dev_rev = read_efdr_1(sc, probe_addrs[i].efer); 655 write_efir_1(sc, probe_addrs[i].efer, WB_CR26); 656 cr26 = read_efdr_1(sc, probe_addrs[i].efer); 657 658 if (dev_id == 0xff && dev_rev == 0xff) 659 goto cleanup; 660 661 /* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */ 662 if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) || 663 ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) { 664 if (dev != NULL) 665 device_printf(dev, "HEFRAS and EFER do not " 666 "align: EFER 0x%02x DevID 0x%02x DevRev " 667 "0x%02x CR26 0x%02x\n", 668 probe_addrs[i].efer, dev_id, dev_rev, cr26); 669 goto cleanup; 670 } 671 672 for (j = 0; j < nitems(wb_devs); j++) { 673 if (wb_devs[j].device_id == dev_id) { 674 found = 1; 675 break; 676 } 677 } 678 679 if (probe && dev != NULL) { 680 snprintf(buf, sizeof(buf), 681 "%s (0x%02x/0x%02x) Watchdog Timer", 682 found ? wb_devs[j].descr : 683 "Unknown Winbond/Nuvoton", dev_id, dev_rev); 684 device_set_desc_copy(dev, buf); 685 } 686 687 /* If this is hinted attach, try to guess the model. */ 688 if (dev != NULL && !found) { 689 found = 1; 690 j = 0; 691 } 692 693 cleanup: 694 if (probe || !found) { 695 (*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer); 696 if (sc != NULL) 697 (void) bus_release_resource(dev, SYS_RES_IOPORT, 698 sc->rid, sc->portres); 699 } 700 701 /* 702 * Stop probing if have successfully identified the SuperIO. 703 * Remember the extended function mode enter/exit functions 704 * for operations. 705 */ 706 if (found) { 707 if (sc != NULL) { 708 sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f; 709 sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f; 710 sc->chip = wb_devs[j].chip; 711 sc->ctl_reg = 0xf5; 712 sc->time_reg = 0xf6; 713 sc->csr_reg = 0xf7; 714 if (sc->chip == w83697hf || 715 sc->chip == w83697ug) { 716 sc->ctl_reg = 0xf3; 717 sc->time_reg = 0xf4; 718 } else if (sc->chip == nct6102) { 719 sc->ctl_reg = 0xf0; 720 sc->time_reg = 0xf1; 721 sc->csr_reg = 0xf2; 722 } 723 } 724 return (BUS_PROBE_SPECIFIC); 725 } else 726 error = ENXIO; 727 } 728 729 return (error); 730 } 731 732 static void 733 wb_identify(driver_t *driver, device_t parent) 734 { 735 736 if (device_find_child(parent, driver->name, 0) == NULL) { 737 if (wb_probe_enable(NULL, 1) <= 0) 738 BUS_ADD_CHILD(parent, 0, driver->name, 0); 739 } 740 } 741 742 static int 743 wb_probe(device_t dev) 744 { 745 746 /* Make sure we do not claim some ISA PNP device. */ 747 if (isa_get_logicalid(dev) != 0) 748 return (ENXIO); 749 750 return (wb_probe_enable(dev, 1)); 751 } 752 753 static int 754 wb_attach(device_t dev) 755 { 756 struct wb_softc *sc; 757 struct sysctl_ctx_list *sctx; 758 struct sysctl_oid *soid; 759 unsigned long timeout; 760 int error; 761 uint8_t t; 762 763 error = wb_probe_enable(dev, 0); 764 if (error > 0) 765 return (ENXIO); 766 767 sc = device_get_softc(dev); 768 KASSERT(sc->ext_cfg_enter_f != NULL && sc->ext_cfg_exit_f != NULL, 769 ("%s: successful probe result but not setup correctly", __func__)); 770 771 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 772 write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8); 773 774 /* Make sure WDT is enabled. */ 775 write_reg(sc, WB_LDN8_CR30, 776 read_reg(sc, WB_LDN8_CR30) | WB_LDN8_CR30_ACTIVE); 777 778 switch (sc->chip) { 779 case w83627hf: 780 case w83627s: 781 t = read_reg(sc, 0x2B) & ~0x10; 782 write_reg(sc, 0x2B, t); /* set GPIO24 to WDT0 */ 783 break; 784 case w83697hf: 785 /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ 786 t = read_reg(sc, 0x29) & ~0x60; 787 t |= 0x20; 788 write_reg(sc, 0x29, t); 789 break; 790 case w83697ug: 791 /* Set pin 118 to WDTO# mode */ 792 t = read_reg(sc, 0x2b) & ~0x04; 793 write_reg(sc, 0x2b, t); 794 break; 795 case w83627thf: 796 t = (read_reg(sc, 0x2B) & ~0x08) | 0x04; 797 write_reg(sc, 0x2B, t); /* set GPIO3 to WDT0 */ 798 break; 799 case w83627dhg: 800 case w83627dhg_p: 801 t = read_reg(sc, 0x2D) & ~0x01; /* PIN77 -> WDT0# */ 802 write_reg(sc, 0x2D, t); /* set GPIO5 to WDT0 */ 803 t = read_reg(sc, sc->ctl_reg); 804 t |= 0x02; /* enable the WDTO# output low pulse 805 * to the KBRST# pin */ 806 write_reg(sc, sc->ctl_reg, t); 807 break; 808 case w83637hf: 809 break; 810 case w83687thf: 811 t = read_reg(sc, 0x2C) & ~0x80; /* PIN47 -> WDT0# */ 812 write_reg(sc, 0x2C, t); 813 break; 814 case w83627ehf: 815 case w83627uhg: 816 case w83667hg: 817 case w83667hg_b: 818 case nct6775: 819 case nct6776: 820 case nct6779: 821 case nct6791: 822 case nct6792: 823 case nct6793: 824 case nct6795: 825 case nct6102: 826 /* 827 * These chips have a fixed WDTO# output pin (W83627UHG), 828 * or support more than one WDTO# output pin. 829 * Don't touch its configuration, and hope the BIOS 830 * does the right thing. 831 */ 832 t = read_reg(sc, sc->ctl_reg); 833 t |= 0x02; /* enable the WDTO# output low pulse 834 * to the KBRST# pin */ 835 write_reg(sc, sc->ctl_reg, t); 836 break; 837 default: 838 break; 839 } 840 841 /* Read the current watchdog configuration. */ 842 sc->reg_1 = read_reg(sc, sc->ctl_reg); 843 sc->reg_timeout = read_reg(sc, sc->time_reg); 844 sc->reg_2 = read_reg(sc, sc->csr_reg); 845 846 /* Print current state if bootverbose or watchdog already enabled. */ 847 if (bootverbose || (sc->reg_timeout > 0x00)) 848 wb_print_state(sc, "Before watchdog attach"); 849 850 sc->reg_1 &= ~WB_LDN8_CRF5_KEYB_P20; 851 sc->reg_1 |= WB_LDN8_CRF5_KBRST; 852 write_reg(sc, sc->ctl_reg, sc->reg_1); 853 854 /* 855 * Clear a previous watchdog timeout event (if still set). 856 * Disable timer reset on mouse interrupts. Leave reset on keyboard, 857 * since one of my boards is getting stuck in reboot without it. 858 */ 859 sc->reg_2 &= ~(WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_TS); 860 write_reg(sc, sc->csr_reg, sc->reg_2); 861 862 (*sc->ext_cfg_exit_f)(sc, 0); 863 864 /* Read global timeout override tunable, Add per device sysctls. */ 865 if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) { 866 if (timeout > 0) 867 sc->timeout_override = timeout; 868 } 869 sctx = device_get_sysctl_ctx(dev); 870 soid = device_get_sysctl_tree(dev); 871 SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 872 "timeout_override", CTLFLAG_RW, &sc->timeout_override, 0, 873 "Timeout in seconds overriding default watchdog timeout"); 874 SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 875 "debug_verbose", CTLFLAG_RW, &sc->debug_verbose, 0, 876 "Enables extra debugging information"); 877 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", 878 CTLTYPE_STRING|CTLFLAG_RD, sc, 0, sysctl_wb_debug, "A", 879 "Selected register information from last change by driver"); 880 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug_current", 881 CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_SKIP, sc, 0, 882 sysctl_wb_debug_current, "A", 883 "Selected register information (may interfere)"); 884 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "force_timeout", 885 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_SKIP, sc, 0, 886 sysctl_wb_force_test_nmi, "I", "Enable to force watchdog to fire."); 887 888 /* Register watchdog. */ 889 sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, wb_watchdog_fn, sc, 890 0); 891 892 if (bootverbose) 893 wb_print_state(sc, "After watchdog attach"); 894 895 return (0); 896 } 897 898 static int 899 wb_detach(device_t dev) 900 { 901 struct wb_softc *sc; 902 903 sc = device_get_softc(dev); 904 905 /* Unregister and stop the watchdog if running. */ 906 if (sc->ev_tag) 907 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag); 908 wb_set_watchdog(sc, 0); 909 910 /* Disable extended function mode. */ 911 (*sc->ext_cfg_exit_f)(sc, 0); 912 913 /* Cleanup resources. */ 914 (void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 915 916 /* Bus subroutines take care of sysctls already. */ 917 918 return (0); 919 } 920 921 static device_method_t wb_methods[] = { 922 /* Device interface */ 923 DEVMETHOD(device_identify, wb_identify), 924 DEVMETHOD(device_probe, wb_probe), 925 DEVMETHOD(device_attach, wb_attach), 926 DEVMETHOD(device_detach, wb_detach), 927 928 DEVMETHOD_END 929 }; 930 931 static driver_t wb_isa_driver = { 932 "wbwd", 933 wb_methods, 934 sizeof(struct wb_softc) 935 }; 936 937 static devclass_t wb_devclass; 938 939 DRIVER_MODULE(wb, isa, wb_isa_driver, wb_devclass, NULL, NULL); 940