1 /* $NetBSD: itesio_isa.c,v 1.27 2017/09/12 09:54:45 msaitoh Exp $ */ 2 /* Derived from $OpenBSD: it.c,v 1.19 2006/04/10 00:57:54 deraadt Exp $ */ 3 4 /* 5 * Copyright (c) 2006-2007 Juan Romero Pardines <xtraeme@netbsd.org> 6 * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITD TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITD TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Driver for the iTE IT87xxF Super I/O. Currently supporting 32 * the Environmental Controller to monitor the sensors and the 33 * Watchdog Timer. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: itesio_isa.c,v 1.27 2017/09/12 09:54:45 msaitoh Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/kernel.h> 41 #include <sys/device.h> 42 #include <sys/module.h> 43 #include <sys/bus.h> 44 45 #include <dev/isa/isareg.h> 46 #include <dev/isa/isavar.h> 47 48 #include <dev/sysmon/sysmonvar.h> 49 50 #include <dev/isa/itesio_isavar.h> 51 52 #define IT_VOLTSTART_IDX 3 /* voltage start index */ 53 #define IT_FANSTART_IDX 12 /* fan start index */ 54 55 #if defined(ITESIO_DEBUG) 56 #define DPRINTF(x) do { printf x; } while (0) 57 #else 58 #define DPRINTF(x) 59 #endif 60 61 /* 62 * IT87-compatible chips can typically measure voltages up to 4.096 V. 63 * To measure higher voltages the input is attenuated with (external) 64 * resistors. Negative voltages are measured using a reference 65 * voltage. So we have to convert the sensor values back to real 66 * voltages by applying the appropriate resistor factor. 67 */ 68 #define RFACT_NONE 10000 69 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y)) 70 71 /* autoconf(9) functions */ 72 static int itesio_isa_match(device_t, cfdata_t, void *); 73 static void itesio_isa_attach(device_t, device_t, void *); 74 static int itesio_isa_detach(device_t, int); 75 76 CFATTACH_DECL_NEW(itesio, sizeof(struct itesio_softc), 77 itesio_isa_match, itesio_isa_attach, itesio_isa_detach, NULL); 78 79 /* driver functions */ 80 static uint8_t itesio_ecreadreg(struct itesio_softc *, int); 81 static void itesio_ecwritereg(struct itesio_softc *, int, int); 82 static uint8_t itesio_readreg(bus_space_tag_t, bus_space_handle_t, int); 83 static void itesio_writereg(bus_space_tag_t, bus_space_handle_t, int, int); 84 static void itesio_enter(bus_space_tag_t, bus_space_handle_t); 85 static void itesio_exit(bus_space_tag_t, bus_space_handle_t); 86 87 /* sysmon_envsys(9) glue */ 88 static void itesio_setup_sensors(struct itesio_softc *); 89 static void itesio_refresh_temp(struct itesio_softc *, envsys_data_t *); 90 static void itesio_refresh_volts(struct itesio_softc *, envsys_data_t *); 91 static void itesio_refresh_fans(struct itesio_softc *, envsys_data_t *); 92 static void itesio_refresh(struct sysmon_envsys *, envsys_data_t *); 93 94 /* sysmon_wdog glue */ 95 static bool itesio_wdt_suspend(device_t, const pmf_qual_t *); 96 static int itesio_wdt_setmode(struct sysmon_wdog *); 97 static int itesio_wdt_tickle(struct sysmon_wdog *); 98 99 /* rfact values for voltage sensors */ 100 static const int itesio_vrfact[] = { 101 RFACT_NONE, /* VCORE_A */ 102 RFACT_NONE, /* VCORE_B */ 103 RFACT_NONE, /* +3.3V */ 104 RFACT(68, 100), /* +5V */ 105 RFACT(30, 10), /* +12V */ 106 RFACT(21, 10), /* -5V */ 107 RFACT(83, 20), /* -12V */ 108 RFACT(68, 100), /* STANDBY */ 109 RFACT_NONE /* VBAT */ 110 }; 111 112 static int 113 itesio_isa_match(device_t parent, cfdata_t match, void *aux) 114 { 115 struct isa_attach_args *ia = aux; 116 bus_space_handle_t ioh; 117 uint16_t cr; 118 119 /* Must supply an address */ 120 if (ia->ia_nio < 1) 121 return 0; 122 123 if (ISA_DIRECT_CONFIG(ia)) 124 return 0; 125 126 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 127 return 0; 128 129 if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) 130 return 0; 131 132 itesio_enter(ia->ia_iot, ioh); 133 cr = (itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID1) << 8); 134 cr |= itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID2); 135 itesio_exit(ia->ia_iot, ioh); 136 bus_space_unmap(ia->ia_iot, ioh, 2); 137 138 switch (cr) { 139 case ITESIO_ID8628: 140 case ITESIO_ID8705: 141 case ITESIO_ID8712: 142 case ITESIO_ID8716: 143 case ITESIO_ID8718: 144 case ITESIO_ID8720: 145 case ITESIO_ID8721: 146 case ITESIO_ID8726: 147 case ITESIO_ID8728: 148 case ITESIO_ID8771: 149 case ITESIO_ID8772: 150 ia->ia_nio = 1; 151 ia->ia_io[0].ir_size = 2; 152 ia->ia_niomem = 0; 153 ia->ia_nirq = 0; 154 ia->ia_ndrq = 0; 155 return 1; 156 default: 157 return 0; 158 } 159 } 160 161 static void 162 itesio_isa_attach(device_t parent, device_t self, void *aux) 163 { 164 struct itesio_softc *sc = device_private(self); 165 struct isa_attach_args *ia = aux; 166 int i; 167 uint8_t cr; 168 169 sc->sc_iot = ia->ia_iot; 170 171 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0, 172 &sc->sc_pnp_ioh)) { 173 aprint_error(": can't map pnp i/o space\n"); 174 return; 175 } 176 177 aprint_naive("\n"); 178 179 /* 180 * Enter to the Super I/O MB PNP mode. 181 */ 182 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 183 /* 184 * Get info from the Super I/O Global Configuration Registers: 185 * Chip IDs and Device Revision. 186 */ 187 sc->sc_chipid = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 188 ITESIO_CHIPID1) << 8); 189 sc->sc_chipid |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 190 ITESIO_CHIPID2); 191 sc->sc_devrev = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 192 ITESIO_DEVREV) & 0x0f); 193 /* 194 * Select the EC LDN to get the Base Address. 195 */ 196 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 197 ITESIO_EC_LDN); 198 sc->sc_hwmon_baseaddr = 199 (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_EC_MSB) << 8); 200 sc->sc_hwmon_baseaddr |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 201 ITESIO_EC_LSB); 202 /* 203 * We are done, exit MB PNP mode. 204 */ 205 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 206 207 aprint_normal(": iTE IT%4xF Super I/O (rev %d)\n", 208 sc->sc_chipid, sc->sc_devrev); 209 aprint_normal_dev(self, "Hardware Monitor registers at 0x%x\n", 210 sc->sc_hwmon_baseaddr); 211 212 if (bus_space_map(sc->sc_iot, sc->sc_hwmon_baseaddr, 8, 0, 213 &sc->sc_ec_ioh)) { 214 aprint_error_dev(self, "cannot map hwmon i/o space\n"); 215 goto out2; 216 } 217 218 sc->sc_hwmon_mapped = true; 219 220 /* Activate monitoring */ 221 cr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG); 222 SET(cr, 0x01); 223 itesio_ecwritereg(sc, ITESIO_EC_CONFIG, cr); 224 225 #ifdef notyet 226 /* Enable beep alarms */ 227 cr = itesio_ecreadreg(sc, ITESIO_EC_BEEPEER); 228 SET(cr, 0x02); /* Voltage exceeds limit */ 229 SET(cr, 0x04); /* Temperature exceeds limit */ 230 itesio_ecwritereg(sc, ITESIO_EC_BEEPEER, cr); 231 #endif 232 233 /* 234 * Initialize and attach sensors. 235 */ 236 itesio_setup_sensors(sc); 237 sc->sc_sme = sysmon_envsys_create(); 238 for (i = 0; i < IT_NUM_SENSORS; i++) { 239 if (sysmon_envsys_sensor_attach(sc->sc_sme, 240 &sc->sc_sensor[i])) { 241 sysmon_envsys_destroy(sc->sc_sme); 242 goto out; 243 } 244 } 245 /* 246 * Hook into the system monitor. 247 */ 248 sc->sc_sme->sme_name = device_xname(self); 249 sc->sc_sme->sme_cookie = sc; 250 sc->sc_sme->sme_refresh = itesio_refresh; 251 252 if ((i = sysmon_envsys_register(sc->sc_sme))) { 253 aprint_error_dev(self, 254 "unable to register with sysmon (%d)\n", i); 255 sysmon_envsys_destroy(sc->sc_sme); 256 goto out; 257 } 258 sc->sc_hwmon_enabled = true; 259 260 if (!pmf_device_register(self, NULL, NULL)) 261 aprint_error_dev(self, "couldn't establish power handler\n"); 262 263 /* The IT8705 doesn't support the WDT */ 264 if (sc->sc_chipid == ITESIO_ID8705) 265 goto out2; 266 267 /* 268 * Initialize the watchdog timer. 269 */ 270 sc->sc_smw.smw_name = device_xname(self); 271 sc->sc_smw.smw_cookie = sc; 272 sc->sc_smw.smw_setmode = itesio_wdt_setmode; 273 sc->sc_smw.smw_tickle = itesio_wdt_tickle; 274 sc->sc_smw.smw_period = 60; 275 276 if (sysmon_wdog_register(&sc->sc_smw)) { 277 aprint_error_dev(self, "unable to register watchdog timer\n"); 278 goto out2; 279 } 280 sc->sc_wdt_enabled = true; 281 aprint_normal_dev(self, "Watchdog Timer present\n"); 282 283 pmf_device_deregister(self); 284 if (!pmf_device_register(self, itesio_wdt_suspend, NULL)) 285 aprint_error_dev(self, "couldn't establish power handler\n"); 286 287 return; 288 289 out: 290 bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8); 291 out2: 292 bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2); 293 } 294 295 static int 296 itesio_isa_detach(device_t self, int flags) 297 { 298 struct itesio_softc *sc = device_private(self); 299 300 if (sc->sc_hwmon_enabled) 301 sysmon_envsys_unregister(sc->sc_sme); 302 if (sc->sc_hwmon_mapped) 303 bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8); 304 if (sc->sc_wdt_enabled) { 305 sysmon_wdog_unregister(&sc->sc_smw); 306 bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2); 307 } 308 309 return 0; 310 } 311 312 static bool 313 itesio_wdt_suspend(device_t dev, const pmf_qual_t *qual) 314 { 315 struct itesio_softc *sc = device_private(dev); 316 317 /* Don't allow suspend if watchdog is armed */ 318 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED) 319 return false; 320 return true; 321 } 322 323 /* 324 * Functions to read/write to the Environmental Controller. 325 */ 326 static uint8_t 327 itesio_ecreadreg(struct itesio_softc *sc, int reg) 328 { 329 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg); 330 return bus_space_read_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA); 331 } 332 333 static void 334 itesio_ecwritereg(struct itesio_softc *sc, int reg, int val) 335 { 336 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg); 337 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA, val); 338 } 339 340 /* 341 * Functions to enter/exit/read/write to the Super I/O. 342 */ 343 static uint8_t 344 itesio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg) 345 { 346 bus_space_write_1(iot, ioh, ITESIO_ADDR, reg); 347 return bus_space_read_1(iot, ioh, ITESIO_DATA); 348 } 349 350 static void 351 itesio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val) 352 { 353 bus_space_write_1(iot, ioh, ITESIO_ADDR, reg); 354 bus_space_write_1(iot, ioh, ITESIO_DATA, val); 355 } 356 357 static void 358 itesio_enter(bus_space_tag_t iot, bus_space_handle_t ioh) 359 { 360 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x87); 361 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x01); 362 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55); 363 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55); 364 } 365 366 static void 367 itesio_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 368 { 369 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x02); 370 bus_space_write_1(iot, ioh, ITESIO_DATA, 0x02); 371 } 372 373 374 #define COPYDESCR(x, y) \ 375 do { \ 376 strlcpy((x), (y), sizeof(x)); \ 377 } while (0) 378 /* 379 * sysmon_envsys(9) glue. 380 */ 381 static void 382 itesio_setup_sensors(struct itesio_softc *sc) 383 { 384 int i; 385 386 /* temperatures */ 387 for (i = 0; i < IT_VOLTSTART_IDX; i++) 388 sc->sc_sensor[i].units = ENVSYS_STEMP; 389 390 COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp"); 391 COPYDESCR(sc->sc_sensor[1].desc, "System Temp"); 392 COPYDESCR(sc->sc_sensor[2].desc, "Aux Temp"); 393 394 /* voltages */ 395 for (i = IT_VOLTSTART_IDX; i < IT_FANSTART_IDX; i++) { 396 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 397 sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT; 398 } 399 400 COPYDESCR(sc->sc_sensor[3].desc, "VCORE_A"); 401 COPYDESCR(sc->sc_sensor[4].desc, "VCORE_B"); 402 COPYDESCR(sc->sc_sensor[5].desc, "+3.3V"); 403 COPYDESCR(sc->sc_sensor[6].desc, "+5V"); 404 COPYDESCR(sc->sc_sensor[7].desc, "+12V"); 405 COPYDESCR(sc->sc_sensor[8].desc, "-5V"); 406 COPYDESCR(sc->sc_sensor[9].desc, "-12V"); 407 COPYDESCR(sc->sc_sensor[10].desc, "STANDBY"); 408 COPYDESCR(sc->sc_sensor[11].desc, "VBAT"); 409 410 /* fans */ 411 for (i = IT_FANSTART_IDX; i < IT_NUM_SENSORS; i++) 412 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 413 414 COPYDESCR(sc->sc_sensor[12].desc, "CPU Fan"); 415 COPYDESCR(sc->sc_sensor[13].desc, "System Fan"); 416 COPYDESCR(sc->sc_sensor[14].desc, "Aux Fan"); 417 418 /* all */ 419 for (i = 0; i < IT_NUM_SENSORS; i++) 420 sc->sc_sensor[i].state = ENVSYS_SINVALID; 421 } 422 #undef COPYDESCR 423 424 static void 425 itesio_refresh_temp(struct itesio_softc *sc, envsys_data_t *edata) 426 { 427 int sdata; 428 429 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORTEMPBASE + edata->sensor); 430 /* sensor is not connected or reporting invalid data */ 431 if (sdata == 0 || sdata >= 0xfa) { 432 edata->state = ENVSYS_SINVALID; 433 return; 434 } 435 436 DPRINTF(("%s: sdata[temp%d] 0x%x\n", __func__, edata->sensor, sdata)); 437 /* Convert temperature to uK */ 438 edata->value_cur = sdata * 1000000 + 273150000; 439 edata->state = ENVSYS_SVALID; 440 } 441 442 static void 443 itesio_refresh_volts(struct itesio_softc *sc, envsys_data_t *edata) 444 { 445 uint8_t vbatcr = 0; 446 int i, sdata; 447 448 i = edata->sensor - IT_VOLTSTART_IDX; 449 450 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORVOLTBASE + i); 451 /* not connected */ 452 if (sdata == 0 || sdata == 0xff) { 453 edata->state = ENVSYS_SINVALID; 454 return; 455 } 456 457 /* 458 * update VBAT voltage reading every time we read it, to get 459 * latest value. 460 */ 461 if (i == 8) { 462 vbatcr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG); 463 SET(vbatcr, ITESIO_EC_UPDATEVBAT); 464 itesio_ecwritereg(sc, ITESIO_EC_CONFIG, vbatcr); 465 } 466 467 DPRINTF(("%s: sdata[volt%d] 0x%x\n", __func__, i, sdata)); 468 469 /* voltage returned as (mV << 4) */ 470 edata->value_cur = (sdata << 4); 471 /* negative values */ 472 if (i == 5 || i == 6) 473 edata->value_cur -= ITESIO_EC_VREF; 474 /* rfact is (factor * 10^4) */ 475 if (edata->rfact) 476 edata->value_cur *= edata->rfact; 477 else 478 edata->value_cur *= itesio_vrfact[i]; 479 /* division by 10 gets us back to uVDC */ 480 edata->value_cur /= 10; 481 if (i == 5 || i == 6) 482 edata->value_cur += ITESIO_EC_VREF * 1000; 483 484 edata->state = ENVSYS_SVALID; 485 } 486 487 static void 488 itesio_refresh_fans(struct itesio_softc *sc, envsys_data_t *edata) 489 { 490 uint8_t mode = 0; 491 uint16_t sdata = 0; 492 int i, divisor, odivisor, ndivisor; 493 494 i = edata->sensor - IT_FANSTART_IDX; 495 divisor = odivisor = ndivisor = 0; 496 497 if (sc->sc_chipid == ITESIO_ID8705 || sc->sc_chipid == ITESIO_ID8712) { 498 /* 499 * Use the Fan Tachometer Divisor Register for 500 * IT8705F and IT8712F. 501 */ 502 divisor = odivisor = ndivisor = 503 itesio_ecreadreg(sc, ITESIO_EC_FAN_TDR); 504 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i); 505 if (sdata == 0xff) { 506 edata->state = ENVSYS_SINVALID; 507 if (i == 2) 508 ndivisor |= 0x40; 509 else { 510 ndivisor &= ~(7 << (i * 3)); 511 ndivisor |= ((divisor + 1) & 7) << (i * 3); 512 } 513 } else { 514 if (i == 2) 515 divisor = divisor & 1 ? 3 : 1; 516 517 if ((sdata << (divisor & 7)) == 0) 518 edata->state = ENVSYS_SINVALID; 519 else { 520 edata->value_cur = 521 1350000 / (sdata << (divisor & 7)); 522 edata->state = ENVSYS_SVALID; 523 } 524 } 525 DPRINTF(("%s: 8bit sdata[fan%d] 0x%x div: 0x%x\n", __func__, 526 i, sdata, divisor)); 527 if (ndivisor != odivisor) 528 itesio_ecwritereg(sc, ITESIO_EC_FAN_TDR, ndivisor); 529 } else { 530 mode = itesio_ecreadreg(sc, ITESIO_EC_FAN16_CER); 531 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i); 532 if (mode & (1 << i)) 533 sdata += (itesio_ecreadreg(sc, 534 ITESIO_EC_SENSORFANEXTBASE + i) << 8); 535 edata->state = ENVSYS_SVALID; 536 if (sdata == 0 || 537 sdata == ((mode & (1 << i)) ? 0xffff : 0xff)) 538 edata->state = ENVSYS_SINVALID; 539 else { 540 edata->value_cur = 1350000 / 2 / sdata; 541 edata->state = ENVSYS_SVALID; 542 } 543 DPRINTF(("%s: 16bit sdata[fan%d] 0x%x\n", __func__, i, sdata)); 544 } 545 } 546 547 static void 548 itesio_refresh(struct sysmon_envsys *sme, struct envsys_data *edata) 549 { 550 struct itesio_softc *sc = sme->sme_cookie; 551 552 if (edata->sensor < IT_VOLTSTART_IDX) 553 itesio_refresh_temp(sc, edata); 554 else if (edata->sensor >= IT_VOLTSTART_IDX && 555 edata->sensor < IT_FANSTART_IDX) 556 itesio_refresh_volts(sc, edata); 557 else 558 itesio_refresh_fans(sc, edata); 559 } 560 561 static int 562 itesio_wdt_setmode(struct sysmon_wdog *smw) 563 { 564 struct itesio_softc *sc = smw->smw_cookie; 565 int period = smw->smw_period; 566 567 /* Enter MB PNP mode and select the WDT LDN */ 568 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 569 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 570 ITESIO_WDT_LDN); 571 572 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 573 /* Disable the watchdog */ 574 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CTL, 0); 575 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF, 0); 576 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 0); 577 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 0); 578 } else { 579 /* Enable the watchdog */ 580 if (period > ITESIO_WDT_MAXTIMO || period < 1) 581 period = smw->smw_period = ITESIO_WDT_MAXTIMO; 582 583 period *= 2; 584 585 /* set the timeout and start the watchdog */ 586 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 587 period >> 8); 588 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 589 period & 0xff); 590 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF, 591 ITESIO_WDT_CNF_SECS | ITESIO_WDT_CNF_KRST | 592 ITESIO_WDT_CNF_PWROK); 593 } 594 /* we are done, exit MB PNP mode */ 595 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 596 597 return 0; 598 } 599 600 static int 601 itesio_wdt_tickle(struct sysmon_wdog *smw) 602 { 603 struct itesio_softc *sc = smw->smw_cookie; 604 int period = smw->smw_period * 2; 605 606 /* refresh timeout value and exit */ 607 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 608 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 609 ITESIO_WDT_LDN); 610 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 611 period >> 8); 612 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 613 period & 0xff); 614 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 615 616 return 0; 617 } 618 619 MODULE(MODULE_CLASS_DRIVER, itesio, "sysmon_envsys,sysmon_wdog"); 620 621 #ifdef _MODULE 622 #include "ioconf.c" 623 #endif 624 625 static int 626 itesio_modcmd(modcmd_t cmd, void *opaque) 627 { 628 switch (cmd) { 629 case MODULE_CMD_INIT: 630 #ifdef _MODULE 631 return config_init_component(cfdriver_ioconf_itesio, 632 cfattach_ioconf_itesio, cfdata_ioconf_itesio); 633 #else 634 return 0; 635 #endif 636 case MODULE_CMD_FINI: 637 #ifdef _MODULE 638 return config_fini_component(cfdriver_ioconf_itesio, 639 cfattach_ioconf_itesio, cfdata_ioconf_itesio); 640 #else 641 return 0; 642 #endif 643 default: 644 return ENOTTY; 645 } 646 } 647