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 sbuf_putc(&sb, 0); /* nullterm */ 256 error = sbuf_finish(&sb); 257 sbuf_delete(&sb); 258 return (error); 259 } 260 261 /* 262 * Read the current values before returning them. Given this might poke 263 * the registers the same time as the watchdog, this sysctl handler should 264 * be marked CTLFLAG_SKIP to not show up by default. 265 */ 266 static int 267 sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS) 268 { 269 struct wb_softc *sc; 270 271 sc = arg1; 272 273 /* 274 * Enter extended function mode in case someone else has been 275 * poking on the registers. We will not leave it though. 276 */ 277 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 278 return (ENXIO); 279 280 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 281 write_efir_1(sc, 0, WB_LDN_REG); 282 write_efdr_1(sc, 0, WB_LDN_REG_LDN8); 283 284 write_efir_1(sc, 0, WB_LDN8_CRF5); 285 sc->reg_1 = read_efdr_1(sc, 0); 286 write_efir_1(sc, 0, WB_LDN8_CRF6); 287 sc->reg_timeout = read_efdr_1(sc, 0); 288 write_efir_1(sc, 0, WB_LDN8_CRF7); 289 sc->reg_2 = read_efdr_1(sc, 0); 290 291 return (sysctl_wb_debug(oidp, arg1, arg2, req)); 292 } 293 294 /* 295 * Sysctl handlers to force a watchdog timeout or to test the NMI functionality 296 * works as expetced. 297 * For testing we could set a test_nmi flag in the softc that, in case of NMI, a 298 * callback function from trap.c could check whether we fired and not report the 299 * timeout but clear the flag for the sysctl again. This is interesting given a 300 * lot of boards have jumpers to change the action on watchdog timeout or 301 * disable the watchdog completely. 302 * XXX-BZ notyet: currently no general infrastructure exists to do this. 303 */ 304 static int 305 sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS) 306 { 307 struct wb_softc *sc; 308 int error, test, val; 309 310 sc = arg1; 311 test = arg2; 312 313 #ifdef notyet 314 val = sc->test_nmi; 315 #else 316 val = 0; 317 #endif 318 error = sysctl_handle_int(oidp, &val, 0, req); 319 if (error || !req->newptr) 320 return (error); 321 322 #ifdef notyet 323 /* Manually clear the test for a value of 0 and do nothing else. */ 324 if (test && val == 0) { 325 sc->test_nmi = 0; 326 return (0); 327 } 328 #endif 329 330 /* 331 * Enter extended function mode in case someone else has been 332 * poking on the registers. We will not leave it though. 333 */ 334 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 335 return (ENXIO); 336 337 #ifdef notyet 338 /* 339 * If we are testing the NMI functionality, set the flag before 340 * forcing the timeout. 341 */ 342 if (test) 343 sc->test_nmi = 1; 344 #endif 345 346 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 347 write_efir_1(sc, 0, WB_LDN_REG); 348 write_efdr_1(sc, 0, WB_LDN_REG_LDN8); 349 350 /* Force watchdog to fire. */ 351 write_efir_1(sc, 0, WB_LDN8_CRF7); 352 sc->reg_2 = read_efdr_1(sc, 0); 353 sc->reg_2 |= WB_LDN8_CRF7_FORCE; 354 355 write_efir_1(sc, 0, WB_LDN8_CRF7); 356 write_efdr_1(sc, 0, sc->reg_2); 357 358 return (0); 359 } 360 361 /* 362 * Print current watchdog state. 363 * 364 * Note: it is the responsibility of the caller to update the registers 365 * upfront. 366 */ 367 static void 368 wb_print_state(struct wb_softc *sc, const char *msg) 369 { 370 371 device_printf(sc->dev, "%s%sWatchdog %sabled. %s" 372 "Scaling by %ds, timer at %d (%s=%ds%s). " 373 "CRF5 0x%02x CRF7 0x%02x\n", 374 (msg != NULL) ? msg : "", (msg != NULL) ? ": " : "", 375 (sc->reg_timeout > 0x00) ? "en" : "dis", 376 (sc->reg_2 & WB_LDN8_CRF7_TS) ? "Watchdog fired. " : "", 377 (sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1, 378 sc->reg_timeout, 379 (sc->reg_timeout > 0x00) ? "<" : "", 380 sc->reg_timeout * ((sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1), 381 (sc->reg_timeout > 0x00) ? " left" : "", 382 sc->reg_1, sc->reg_2); 383 } 384 385 /* 386 * Functions to enter and exit extended function mode. Possibly shared 387 * between different chips. 388 */ 389 static int 390 ext_cfg_enter_0x87_0x87(struct wb_softc *sc, u_short baseport) 391 { 392 393 /* 394 * Enable extended function mode. 395 * Winbond does not allow us to validate so always return success. 396 */ 397 write_efir_1(sc, baseport, 0x87); 398 write_efir_1(sc, baseport, 0x87); 399 400 return (0); 401 } 402 403 static void 404 ext_cfg_exit_0xaa(struct wb_softc *sc, u_short baseport) 405 { 406 407 write_efir_1(sc, baseport, 0xaa); 408 } 409 410 /* 411 * (Re)load the watchdog counter depending on timeout. A timeout of 0 will 412 * disable the watchdog. 413 */ 414 static int 415 wb_set_watchdog(struct wb_softc *sc, unsigned int timeout) 416 { 417 418 if (sc->debug_verbose) 419 wb_print_state(sc, "Before watchdog counter (re)load"); 420 421 /* 422 * Enter extended function mode in case someone else has been 423 * poking on the registers. We will not leave it though. 424 */ 425 if ((*sc->ext_cfg_enter_f)(sc, 0) != 0) 426 return (ENXIO); 427 428 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */ 429 write_efir_1(sc, 0, WB_LDN_REG); 430 write_efdr_1(sc, 0, WB_LDN_REG_LDN8); 431 432 /* Disable and validate or arm/reset watchdog. */ 433 if (timeout == 0) { 434 /* Disable watchdog. */ 435 write_efir_1(sc, 0, WB_LDN8_CRF6); 436 write_efdr_1(sc, 0, 0x00); 437 438 /* Re-check. */ 439 write_efir_1(sc, 0, WB_LDN8_CRF6); 440 sc->reg_timeout = read_efdr_1(sc, 0); 441 442 if (sc->reg_timeout != 0x00) { 443 device_printf(sc->dev, "Failed to disable watchdog: " 444 "0x%02x.\n", sc->reg_timeout); 445 return (EIO); 446 } 447 448 } else { 449 /* 450 * In case an override is set, let it override. It may lead 451 * to strange results as we do not check the input of the sysctl. 452 */ 453 if (sc->timeout_override > 0) 454 timeout = sc->timeout_override; 455 456 /* Make sure we support the requested timeout. */ 457 if (timeout > 255 * 60) 458 return (EINVAL); 459 460 /* Read current scaling factor. */ 461 write_efir_1(sc, 0, WB_LDN8_CRF5); 462 sc->reg_1 = read_efdr_1(sc, 0); 463 464 if (timeout > 255) { 465 /* Set scaling factor to 60s. */ 466 sc->reg_1 |= WB_LDN8_CRF5_SCALE; 467 sc->reg_timeout = (timeout / 60); 468 if (timeout % 60) 469 sc->reg_timeout++; 470 } else { 471 /* Set scaling factor to 1s. */ 472 sc->reg_1 &= ~WB_LDN8_CRF5_SCALE; 473 sc->reg_timeout = timeout; 474 } 475 476 /* In case we fired before we need to clear to fire again. */ 477 write_efir_1(sc, 0, WB_LDN8_CRF7); 478 sc->reg_2 = read_efdr_1(sc, 0); 479 if (sc->reg_2 & WB_LDN8_CRF7_TS) { 480 sc->reg_2 &= ~WB_LDN8_CRF7_TS; 481 write_efir_1(sc, 0, WB_LDN8_CRF7); 482 write_efdr_1(sc, 0, sc->reg_2); 483 } 484 485 /* Write back scaling factor. */ 486 write_efir_1(sc, 0, WB_LDN8_CRF5); 487 write_efdr_1(sc, 0, sc->reg_1); 488 489 /* Set timer and arm/reset the watchdog. */ 490 write_efir_1(sc, 0, WB_LDN8_CRF6); 491 write_efdr_1(sc, 0, sc->reg_timeout); 492 } 493 494 if (sc->debug_verbose) 495 wb_print_state(sc, "After watchdog counter (re)load"); 496 497 return (0); 498 } 499 500 /* 501 * watchdog(9) EVENTHANDLER function implementation to (re)load the counter 502 * with the given timeout or disable the watchdog. 503 */ 504 static void 505 wb_watchdog_fn(void *private, u_int cmd, int *error) 506 { 507 struct wb_softc *sc; 508 unsigned int timeout; 509 int e; 510 511 sc = private; 512 KASSERT(sc != NULL, ("%s: watchdog handler function called without " 513 "softc.", __func__)); 514 515 cmd &= WD_INTERVAL; 516 if (cmd > 0 && cmd <= 63) { 517 /* Reset (and arm) watchdog. */ 518 timeout = ((uint64_t)1 << cmd) / 1000000000; 519 if (timeout == 0) 520 timeout = 1; 521 e = wb_set_watchdog(sc, timeout); 522 if (e == 0) { 523 if (error != NULL) 524 *error = 0; 525 } else { 526 /* On error, try to make sure the WD is disabled. */ 527 wb_set_watchdog(sc, 0); 528 } 529 530 } else { 531 /* Disable watchdog. */ 532 e = wb_set_watchdog(sc, 0); 533 if (e != 0 && cmd == 0 && error != NULL) { 534 /* Failed to disable watchdog. */ 535 *error = EOPNOTSUPP; 536 } 537 } 538 } 539 540 /* 541 * Probe/attach the Winbond Super I/O chip. 542 * 543 * Initial abstraction to possibly support more chips: 544 * - Iterate over the well known base ports, try to enable extended function 545 * mode and read and match the device ID and device revision. Unfortunately 546 * the Vendor ID is in the hardware monitoring section accessible by different 547 * base ports only. 548 * - Also HEFRAS, which would tell use the base port, is only accessible after 549 * entering extended function mode, for which the base port is needed. 550 * At least check HEFRAS to match the current base port we are probing. 551 * - On match set the description, remember functions to enter/exit extended 552 * function mode as well as the base port. 553 */ 554 static int 555 wb_probe_enable(device_t dev, int probe) 556 { 557 struct wb_softc *sc; 558 int error, found, i, j; 559 uint8_t dev_id, dev_rev, cr26; 560 561 if (dev == NULL) 562 sc = NULL; 563 else { 564 sc = device_get_softc(dev); 565 bzero(sc, sizeof(*sc)); 566 sc->dev = dev; 567 } 568 569 error = ENXIO; 570 for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) { 571 572 if (sc != NULL) { 573 /* Allocate bus resources for IO index/data register access. */ 574 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 575 probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE); 576 if (sc->portres == NULL) 577 continue; 578 sc->bst = rman_get_bustag(sc->portres); 579 sc->bsh = rman_get_bushandle(sc->portres); 580 } 581 582 found = 0; 583 error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer); 584 if (error != 0) 585 goto cleanup; 586 587 /* Identify the SuperIO chip. */ 588 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_ID_REG); 589 dev_id = read_efdr_1(sc, probe_addrs[i].efer); 590 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_REV_REG); 591 dev_rev = read_efdr_1(sc, probe_addrs[i].efer); 592 write_efir_1(sc, probe_addrs[i].efer, WB_CR26); 593 cr26 = read_efdr_1(sc, probe_addrs[i].efer); 594 595 /* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */ 596 if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) || 597 ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) { 598 if (dev != NULL) 599 device_printf(dev, "HEFRAS and EFER do not " 600 "align: EFER 0x%02x DevID 0x%02x DevRev " 601 "0x%02x CR26 0x%02x\n", 602 probe_addrs[i].efer, dev_id, dev_rev, cr26); 603 goto cleanup; 604 } 605 606 if (dev_id == 0xff && dev_rev == 0xff) 607 goto cleanup; 608 609 for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) { 610 if (wb_devs[j].device_id == dev_id && 611 wb_devs[j].device_rev == dev_rev) { 612 if (probe && dev != NULL) 613 device_set_desc(dev, wb_devs[j].descr); 614 found++; 615 break; 616 } 617 } 618 619 if (!found) { 620 if (probe && dev != NULL) { 621 device_set_desc(dev, "Unknown Winbond/Nuvoton model"); 622 device_printf(dev, "DevID 0x%02x DevRev 0x%02x, " 623 "please report this.\n", dev_id, dev_rev); 624 } 625 found++; 626 } 627 628 if (probe && found && bootverbose && dev != NULL) 629 device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x" 630 " CR26 0x%02x (probing)\n", device_get_desc(dev), 631 probe_addrs[i].efer, dev_id, dev_rev, cr26); 632 cleanup: 633 if (probe || !found) { 634 (*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer); 635 636 if (sc != NULL) 637 (void) bus_release_resource(dev, SYS_RES_IOPORT, 638 sc->rid, sc->portres); 639 } 640 641 /* 642 * Stop probing if have successfully identified the SuperIO. 643 * Remember the extended function mode enter/exit functions 644 * for operations. 645 */ 646 if (found) { 647 if (sc != NULL) { 648 sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f; 649 sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f; 650 } 651 error = BUS_PROBE_DEFAULT; 652 break; 653 } else 654 error = ENXIO; 655 } 656 657 return (error); 658 } 659 660 static void 661 wb_identify(driver_t *driver, device_t parent) 662 { 663 device_t dev; 664 665 if ((dev = device_find_child(parent, driver->name, 0)) == NULL) { 666 if (wb_probe_enable(dev, 1) != BUS_PROBE_DEFAULT) { 667 if (bootverbose) 668 device_printf(dev, "can not find compatible Winbond chip.\n"); 669 } else 670 dev = BUS_ADD_CHILD(parent, 0, driver->name, 0); 671 return; 672 } 673 } 674 675 static int 676 wb_probe(device_t dev) 677 { 678 679 /* Make sure we do not claim some ISA PNP device. */ 680 if (isa_get_logicalid(dev) != 0) 681 return (ENXIO); 682 683 return (wb_probe_enable(dev, 1)); 684 } 685 686 static int 687 wb_attach(device_t dev) 688 { 689 struct wb_softc *sc; 690 struct sysctl_ctx_list *sctx; 691 struct sysctl_oid *soid; 692 unsigned long timeout; 693 int error; 694 695 error = wb_probe_enable(dev, 0); 696 if (error > 0) 697 return (ENXIO); 698 699 sc = device_get_softc(dev); 700 KASSERT(sc->ext_cfg_enter_f != NULL && sc->ext_cfg_exit_f != NULL, 701 ("%s: successfull probe result but not setup correctly", __func__)); 702 703 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 704 write_efir_1(sc, 0, WB_LDN_REG); 705 write_efdr_1(sc, 0, WB_LDN_REG_LDN8); 706 707 /* Make sure LDN8 is enabled (Do we need to? Also affects GPIO). */ 708 write_efir_1(sc, 0, WB_LDN8_CR30); 709 write_efdr_1(sc, 0, WB_LDN8_CR30_ACTIVE); 710 711 /* Read the current watchdog configuration. */ 712 write_efir_1(sc, 0, WB_LDN8_CRF5); 713 sc->reg_1 = read_efdr_1(sc, 0); 714 write_efir_1(sc, 0, WB_LDN8_CRF6); 715 sc->reg_timeout = read_efdr_1(sc, 0); 716 write_efir_1(sc, 0, WB_LDN8_CRF7); 717 sc->reg_2 = read_efdr_1(sc, 0); 718 719 /* Print current state if bootverbose or watchdog already enabled. */ 720 if (bootverbose || (sc->reg_timeout > 0x00)) 721 wb_print_state(sc, "Before watchdog attach"); 722 723 /* 724 * Clear a previous watchdog timeout event (if (still) set). 725 * Disable all all interrupt reset sources (defaults). 726 */ 727 sc->reg_1 &= ~(WB_LDN8_CRF5_KEYB_P20); 728 sc->reg_1 |= WB_LDN8_CRF5_KBRST; 729 write_efir_1(sc, 0, WB_LDN8_CRF5); 730 write_efdr_1(sc, 0, sc->reg_1); 731 732 sc->reg_2 &= ~WB_LDN8_CRF7_CLEAR_MASK; 733 write_efir_1(sc, 0, WB_LDN8_CRF7); 734 write_efdr_1(sc, 0, sc->reg_2); 735 736 /* Read global timeout override tunable, Add per device sysctls. */ 737 if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) { 738 if (timeout > 0) 739 sc->timeout_override = timeout; 740 } 741 sctx = device_get_sysctl_ctx(dev); 742 soid = device_get_sysctl_tree(dev); 743 SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 744 "timeout_override", CTLFLAG_RW, &sc->timeout_override, 0, 745 "Timeout in seconds overriding default watchdog timeout"); 746 SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 747 "debug_verbose", CTLFLAG_RW, &sc->debug_verbose, 0, 748 "Enables extra debugging information"); 749 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", 750 CTLTYPE_STRING|CTLFLAG_RD, sc, 0, sysctl_wb_debug, "A", 751 "Selected register information from last change by driver"); 752 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug_current", 753 CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_SKIP, sc, 0, 754 sysctl_wb_debug_current, "A", 755 "Selected register information (may interfere)"); 756 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "force_timeout", 757 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_SKIP, sc, 0, 758 sysctl_wb_force_test_nmi, "I", "Enable to force watchdog to fire."); 759 760 /* Register watchdog. */ 761 sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, wb_watchdog_fn, sc, 762 0); 763 764 if (bootverbose) 765 wb_print_state(sc, "After watchdog attach"); 766 767 return (0); 768 } 769 770 static int 771 wb_detach(device_t dev) 772 { 773 struct wb_softc *sc; 774 775 sc = device_get_softc(dev); 776 777 /* Unregister and stop the watchdog if running. */ 778 if (sc->ev_tag) 779 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag); 780 wb_set_watchdog(sc, 0); 781 782 /* Disable extended function mode. */ 783 (*sc->ext_cfg_exit_f)(sc, 0); 784 785 /* Cleanup resources. */ 786 (void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 787 788 /* Bus subroutines take care of sysctls already. */ 789 790 return (0); 791 } 792 793 static device_method_t wb_methods[] = { 794 /* Device interface */ 795 DEVMETHOD(device_identify, wb_identify), 796 DEVMETHOD(device_probe, wb_probe), 797 DEVMETHOD(device_attach, wb_attach), 798 DEVMETHOD(device_detach, wb_detach), 799 800 DEVMETHOD_END 801 }; 802 803 static driver_t wb_isa_driver = { 804 "wbwd", 805 wb_methods, 806 sizeof(struct wb_softc) 807 }; 808 809 static devclass_t wb_devclass; 810 811 DRIVER_MODULE(wb, isa, wb_isa_driver, wb_devclass, NULL, NULL); 812