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