1/* $NetBSD: itesio_isa.c,v 1.30 2022/06/29 15:56:58 mlelstv 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.30 2022/06/29 15:56:58 mlelstv 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#include <sys/kmem.h> 45 46#include <dev/isa/isareg.h> 47#include <dev/isa/isavar.h> 48 49#include <dev/sysmon/sysmonvar.h> 50 51#include <dev/isa/itesio_isavar.h> 52 53#define IT_VOLTSTART_IDX 3 /* voltage start index */ 54#define IT_FANSTART_IDX 12 /* fan start index */ 55 56/* IT8625: 3 temps, 10 volts, 6 fans */ 57#define IT8625_NUM_SENSORS 19 58#define IT8625_VOLTSTART_IDX 3 /* voltage start index */ 59#define IT8625_FANSTART_IDX 13 /* fan start index */ 60 61#if defined(ITESIO_DEBUG) 62#define DPRINTF(x) do { printf x; } while (0) 63#else 64#define DPRINTF(x) 65#endif 66 67/* 68 * IT87-compatible chips can typically measure voltages up to 4.096 V. 69 * To measure higher voltages the input is attenuated with (external) 70 * resistors. Negative voltages are measured using a reference 71 * voltage. So we have to convert the sensor values back to real 72 * voltages by applying the appropriate resistor factor. 73 */ 74#define RFACT_NONE 10000 75#define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y)) 76 77/* autoconf(9) functions */ 78static int itesio_isa_match(device_t, cfdata_t, void *); 79static void itesio_isa_attach(device_t, device_t, void *); 80static int itesio_isa_detach(device_t, int); 81 82CFATTACH_DECL_NEW(itesio, sizeof(struct itesio_softc), 83 itesio_isa_match, itesio_isa_attach, itesio_isa_detach, NULL); 84 85/* driver functions */ 86static uint8_t itesio_ecreadreg(struct itesio_softc *, int); 87static void itesio_ecwritereg(struct itesio_softc *, int, int); 88static uint8_t itesio_readreg(bus_space_tag_t, bus_space_handle_t, int); 89static void itesio_writereg(bus_space_tag_t, bus_space_handle_t, int, int); 90static void itesio_enter(bus_space_tag_t, bus_space_handle_t); 91static void itesio_exit(bus_space_tag_t, bus_space_handle_t); 92 93/* sysmon_envsys(9) glue */ 94static void itesio_setup_sensors(struct itesio_softc *); 95static void itesio_refresh_temp(struct itesio_softc *, envsys_data_t *); 96static void itesio_refresh_volts(struct itesio_softc *, envsys_data_t *); 97static void itesio_refresh_fans(struct itesio_softc *, envsys_data_t *); 98static void itesio_refresh(struct sysmon_envsys *, envsys_data_t *); 99static void itesio_refresh_it8705_fans(struct itesio_softc *, 100 envsys_data_t *); 101static void itesio_setup_it8625_sensors(struct itesio_softc *); 102static void itesio_refresh_it8625_volts(struct itesio_softc *, 103 envsys_data_t *); 104static void itesio_refresh_it8625_fans(struct itesio_softc *, 105 envsys_data_t *); 106 107/* sysmon_wdog glue */ 108static bool itesio_wdt_suspend(device_t, const pmf_qual_t *); 109static int itesio_wdt_setmode(struct sysmon_wdog *); 110static int itesio_wdt_tickle(struct sysmon_wdog *); 111 112/* rfact values for voltage sensors */ 113static const int itesio_vrfact[] = { 114 RFACT_NONE, /* VCORE_A */ 115 RFACT_NONE, /* VCORE_B */ 116 RFACT_NONE, /* +3.3V */ 117 RFACT(68, 100), /* +5V */ 118 RFACT(30, 10), /* +12V */ 119 RFACT(21, 10), /* -5V */ 120 RFACT(83, 20), /* -12V */ 121 RFACT(68, 100), /* STANDBY */ 122 RFACT_NONE /* VBAT */ 123}; 124 125static const struct itesio_config itesio_config[] = { 126 { 127 .chipid = ITESIO_ID8625, 128 .no_wdt = true, 129 .num_sensors = IT8625_NUM_SENSORS, 130 .voltstart_idx = IT8625_VOLTSTART_IDX, 131 .fanstart_idx = IT8625_FANSTART_IDX, 132 .setup_sensors = itesio_setup_it8625_sensors, 133 .refresh_volts = itesio_refresh_it8625_volts, 134 .refresh_fans = itesio_refresh_it8625_fans, 135 }, 136 { .chipid = ITESIO_ID8628, }, 137 { .chipid = ITESIO_ID8655, }, 138 { 139 .chipid = ITESIO_ID8705, 140 .no_wdt = true, 141 .refresh_fans = itesio_refresh_it8705_fans, 142 }, 143 { 144 .chipid = ITESIO_ID8712, 145 .refresh_fans = itesio_refresh_it8705_fans, 146 }, 147 { .chipid = ITESIO_ID8716, }, 148 { .chipid = ITESIO_ID8718, }, 149 { .chipid = ITESIO_ID8720, }, 150 { .chipid = ITESIO_ID8721, }, 151 { .chipid = ITESIO_ID8726, }, 152 { .chipid = ITESIO_ID8728, }, 153 { .chipid = ITESIO_ID8771, }, 154 { .chipid = ITESIO_ID8772, }, 155}; 156 157static const struct itesio_config * 158itesio_isa_find_config(uint16_t chipid) 159{ 160 const struct itesio_config *ic; 161 size_t i; 162 163 for (i = 0; i < __arraycount(itesio_config); i++) { 164 ic = &itesio_config[i]; 165 if (chipid == ic->chipid) 166 return ic; 167 } 168 return NULL; 169} 170 171static int 172itesio_isa_match(device_t parent, cfdata_t match, void *aux) 173{ 174 struct isa_attach_args *ia = aux; 175 bus_space_handle_t ioh; 176 const struct itesio_config *ic; 177 uint16_t cr; 178 179 /* Must supply an address */ 180 if (ia->ia_nio < 1) 181 return 0; 182 183 if (ISA_DIRECT_CONFIG(ia)) 184 return 0; 185 186 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 187 return 0; 188 189 if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) 190 return 0; 191 192 itesio_enter(ia->ia_iot, ioh); 193 cr = (itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID1) << 8); 194 cr |= itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID2); 195 itesio_exit(ia->ia_iot, ioh); 196 bus_space_unmap(ia->ia_iot, ioh, 2); 197 198 ic = itesio_isa_find_config(cr); 199 if (ic == NULL) 200 return 0; 201 202 ia->ia_nio = 1; 203 ia->ia_io[0].ir_size = 2; 204 ia->ia_niomem = 0; 205 ia->ia_nirq = 0; 206 ia->ia_ndrq = 0; 207 return 1; 208} 209 210static void 211itesio_isa_attach(device_t parent, device_t self, void *aux) 212{ 213 struct itesio_softc *sc = device_private(self); 214 struct isa_attach_args *ia = aux; 215 const struct itesio_config *ic; 216 uint32_t i; 217 int error; 218 uint8_t cr; 219 220 sc->sc_iot = ia->ia_iot; 221 222 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0, 223 &sc->sc_pnp_ioh)) { 224 aprint_error(": can't map pnp i/o space\n"); 225 return; 226 } 227 228 aprint_naive("\n"); 229 230 /* 231 * Enter to the Super I/O MB PNP mode. 232 */ 233 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 234 /* 235 * Get info from the Super I/O Global Configuration Registers: 236 * Chip IDs and Device Revision. 237 */ 238 sc->sc_chipid = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 239 ITESIO_CHIPID1) << 8); 240 sc->sc_chipid |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 241 ITESIO_CHIPID2); 242 sc->sc_devrev = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 243 ITESIO_DEVREV) & 0x0f); 244 /* 245 * Select the EC LDN to get the Base Address. 246 */ 247 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 248 ITESIO_EC_LDN); 249 sc->sc_hwmon_baseaddr = 250 (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_EC_MSB) << 8); 251 sc->sc_hwmon_baseaddr |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, 252 ITESIO_EC_LSB); 253 /* 254 * We are done, exit MB PNP mode. 255 */ 256 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 257 258 ic = itesio_isa_find_config(sc->sc_chipid); 259 if (ic == NULL) { 260 aprint_error(": unknown chipid: %04x", sc->sc_chipid); 261 goto out2; 262 } 263 sc->sc_config = *ic; 264 if (sc->sc_config.num_sensors == 0) 265 sc->sc_config.num_sensors = IT_NUM_SENSORS; 266 if (sc->sc_config.voltstart_idx == 0) 267 sc->sc_config.voltstart_idx = IT_VOLTSTART_IDX; 268 if (sc->sc_config.fanstart_idx == 0) 269 sc->sc_config.fanstart_idx = IT_FANSTART_IDX; 270 if (sc->sc_config.setup_sensors == NULL) 271 sc->sc_config.setup_sensors = itesio_setup_sensors; 272 if (sc->sc_config.refresh_temp == NULL) 273 sc->sc_config.refresh_temp = itesio_refresh_temp; 274 if (sc->sc_config.refresh_volts == NULL) 275 sc->sc_config.refresh_volts = itesio_refresh_volts; 276 if (sc->sc_config.refresh_fans == NULL) 277 sc->sc_config.refresh_fans = itesio_refresh_fans; 278 279 aprint_normal(": iTE IT%4xF Super I/O (rev %d)\n", 280 sc->sc_chipid, sc->sc_devrev); 281 aprint_normal_dev(self, "Hardware Monitor registers at 0x%x\n", 282 sc->sc_hwmon_baseaddr); 283 284 if (bus_space_map(sc->sc_iot, sc->sc_hwmon_baseaddr, 8, 0, 285 &sc->sc_ec_ioh)) { 286 aprint_error_dev(self, "cannot map hwmon i/o space\n"); 287 goto out2; 288 } 289 290 sc->sc_hwmon_mapped = true; 291 292 /* Activate monitoring */ 293 cr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG); 294 SET(cr, 0x01); 295 itesio_ecwritereg(sc, ITESIO_EC_CONFIG, cr); 296 297#ifdef notyet 298 /* Enable beep alarms */ 299 cr = itesio_ecreadreg(sc, ITESIO_EC_BEEPEER); 300 SET(cr, 0x02); /* Voltage exceeds limit */ 301 SET(cr, 0x04); /* Temperature exceeds limit */ 302 itesio_ecwritereg(sc, ITESIO_EC_BEEPEER, cr); 303#endif 304 305 /* 306 * Initialize and attach sensors. 307 */ 308 (*sc->sc_config.setup_sensors)(sc); 309 sc->sc_sme = sysmon_envsys_create(); 310 for (i = 0; i < sc->sc_config.num_sensors; i++) { 311 if (sysmon_envsys_sensor_attach(sc->sc_sme, 312 &sc->sc_sensor[i])) { 313 sysmon_envsys_destroy(sc->sc_sme); 314 sc->sc_sme = NULL; 315 goto out; 316 } 317 } 318 /* 319 * Hook into the system monitor. 320 */ 321 sc->sc_sme->sme_name = device_xname(self); 322 sc->sc_sme->sme_cookie = sc; 323 sc->sc_sme->sme_refresh = itesio_refresh; 324 325 if ((error = sysmon_envsys_register(sc->sc_sme))) { 326 aprint_error_dev(self, 327 "unable to register with sysmon (%d)\n", error); 328 sysmon_envsys_destroy(sc->sc_sme); 329 sc->sc_sme = NULL; 330 goto out; 331 } 332 sc->sc_hwmon_enabled = true; 333 334 if (!pmf_device_register(self, NULL, NULL)) 335 aprint_error_dev(self, "couldn't establish power handler\n"); 336 337 /* Some chips don't support the WDT */ 338 if (sc->sc_config.no_wdt) 339 goto out2; 340 341 /* 342 * Initialize the watchdog timer. 343 */ 344 sc->sc_smw.smw_name = device_xname(self); 345 sc->sc_smw.smw_cookie = sc; 346 sc->sc_smw.smw_setmode = itesio_wdt_setmode; 347 sc->sc_smw.smw_tickle = itesio_wdt_tickle; 348 sc->sc_smw.smw_period = 60; 349 350 if (sysmon_wdog_register(&sc->sc_smw)) { 351 aprint_error_dev(self, "unable to register watchdog timer\n"); 352 goto out2; 353 } 354 sc->sc_wdt_enabled = true; 355 aprint_normal_dev(self, "Watchdog Timer present\n"); 356 357 pmf_device_deregister(self); 358 if (!pmf_device_register(self, itesio_wdt_suspend, NULL)) 359 aprint_error_dev(self, "couldn't establish power handler\n"); 360 361 return; 362 363out: 364 bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8); 365out2: 366 bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2); 367} 368 369static int 370itesio_isa_detach(device_t self, int flags) 371{ 372 struct itesio_softc *sc = device_private(self); 373 374 if (sc->sc_hwmon_enabled) 375 sysmon_envsys_unregister(sc->sc_sme); 376 if (sc->sc_hwmon_mapped) 377 bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8); 378 if (sc->sc_wdt_enabled) { 379 sysmon_wdog_unregister(&sc->sc_smw); 380 bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2); 381 } 382 383 if (sc->sc_sensor != NULL) { 384 kmem_free(sc->sc_sensor, 385 sizeof(sc->sc_sensor[0]) * sc->sc_config.num_sensors); 386 } 387 388 return 0; 389} 390 391static bool 392itesio_wdt_suspend(device_t dev, const pmf_qual_t *qual) 393{ 394 struct itesio_softc *sc = device_private(dev); 395 396 /* Don't allow suspend if watchdog is armed */ 397 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED) 398 return false; 399 return true; 400} 401 402/* 403 * Functions to read/write to the Environmental Controller. 404 */ 405static uint8_t 406itesio_ecreadreg(struct itesio_softc *sc, int reg) 407{ 408 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg); 409 return bus_space_read_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA); 410} 411 412static void 413itesio_ecwritereg(struct itesio_softc *sc, int reg, int val) 414{ 415 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg); 416 bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA, val); 417} 418 419/* 420 * Functions to enter/exit/read/write to the Super I/O. 421 */ 422static uint8_t 423itesio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg) 424{ 425 bus_space_write_1(iot, ioh, ITESIO_ADDR, reg); 426 return bus_space_read_1(iot, ioh, ITESIO_DATA); 427} 428 429static void 430itesio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val) 431{ 432 bus_space_write_1(iot, ioh, ITESIO_ADDR, reg); 433 bus_space_write_1(iot, ioh, ITESIO_DATA, val); 434} 435 436static void 437itesio_enter(bus_space_tag_t iot, bus_space_handle_t ioh) 438{ 439 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x87); 440 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x01); 441 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55); 442 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55); 443} 444 445static void 446itesio_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 447{ 448 bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x02); 449 bus_space_write_1(iot, ioh, ITESIO_DATA, 0x02); 450} 451 452 453#define COPYDESCR(x, y) \ 454 do { \ 455 strlcpy((x), (y), sizeof(x)); \ 456 } while (0) 457/* 458 * sysmon_envsys(9) glue. 459 */ 460static void 461itesio_setup_sensors_common(struct itesio_softc *sc) 462{ 463 const struct itesio_config *ic = &sc->sc_config; 464 size_t allocsz; 465 uint32_t i; 466 467 allocsz = sizeof(sc->sc_sensor[0]) * ic->num_sensors; 468 sc->sc_sensor = kmem_zalloc(allocsz, KM_SLEEP); 469 470 /* temperatures */ 471 for (i = 0; i < ic->voltstart_idx; i++) 472 sc->sc_sensor[i].units = ENVSYS_STEMP; 473 474 /* voltages */ 475 for (i = ic->voltstart_idx; i < ic->fanstart_idx; i++) { 476 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 477 sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT; 478 } 479 480 /* fans */ 481 for (i = ic->fanstart_idx; i < ic->num_sensors; i++) 482 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 483 484 /* all */ 485 for (i = 0; i < ic->num_sensors; i++) 486 sc->sc_sensor[i].state = ENVSYS_SINVALID; 487} 488 489static void 490itesio_setup_sensors(struct itesio_softc *sc) 491{ 492 493 itesio_setup_sensors_common(sc); 494 495 /* temperatures */ 496 COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp"); 497 COPYDESCR(sc->sc_sensor[1].desc, "System Temp"); 498 COPYDESCR(sc->sc_sensor[2].desc, "Aux Temp"); 499 500 /* voltages */ 501 COPYDESCR(sc->sc_sensor[3].desc, "VCORE_A"); 502 COPYDESCR(sc->sc_sensor[4].desc, "VCORE_B"); 503 COPYDESCR(sc->sc_sensor[5].desc, "+3.3V"); 504 COPYDESCR(sc->sc_sensor[6].desc, "+5V"); 505 COPYDESCR(sc->sc_sensor[7].desc, "+12V"); 506 COPYDESCR(sc->sc_sensor[8].desc, "-5V"); 507 COPYDESCR(sc->sc_sensor[9].desc, "-12V"); 508 COPYDESCR(sc->sc_sensor[10].desc, "STANDBY"); 509 COPYDESCR(sc->sc_sensor[11].desc, "VBAT"); 510 511 /* fans */ 512 COPYDESCR(sc->sc_sensor[12].desc, "CPU Fan"); 513 COPYDESCR(sc->sc_sensor[13].desc, "System Fan"); 514 COPYDESCR(sc->sc_sensor[14].desc, "Aux Fan"); 515} 516 517static void 518itesio_setup_it8625_sensors(struct itesio_softc *sc) 519{ 520 521 itesio_setup_sensors_common(sc); 522 523 /* temperatures */ 524 COPYDESCR(sc->sc_sensor[0].desc, "Temp0"); 525 COPYDESCR(sc->sc_sensor[1].desc, "Temp1"); 526 COPYDESCR(sc->sc_sensor[2].desc, "Temp2"); 527 528 /* voltages */ 529 COPYDESCR(sc->sc_sensor[3].desc, "VIN0"); 530 COPYDESCR(sc->sc_sensor[4].desc, "VIN1"); 531 COPYDESCR(sc->sc_sensor[5].desc, "VIN2"); 532 COPYDESCR(sc->sc_sensor[6].desc, "VIN3"); 533 COPYDESCR(sc->sc_sensor[7].desc, "VIN4"); 534 COPYDESCR(sc->sc_sensor[8].desc, "VIN5"); 535 COPYDESCR(sc->sc_sensor[9].desc, "VIN6"); 536 COPYDESCR(sc->sc_sensor[10].desc, "Internal 3VSB"); 537 COPYDESCR(sc->sc_sensor[11].desc, "VBAT"); 538 COPYDESCR(sc->sc_sensor[12].desc, "Internal AVCC3"); 539 540 /* fans */ 541 COPYDESCR(sc->sc_sensor[13].desc, "Fan0"); 542 COPYDESCR(sc->sc_sensor[14].desc, "Fan1"); 543 COPYDESCR(sc->sc_sensor[15].desc, "Fan2"); 544 COPYDESCR(sc->sc_sensor[16].desc, "Fan3"); 545 COPYDESCR(sc->sc_sensor[17].desc, "Fan4"); 546 COPYDESCR(sc->sc_sensor[18].desc, "Fan5"); 547} 548#undef COPYDESCR 549 550static void 551itesio_refresh_temp(struct itesio_softc *sc, envsys_data_t *edata) 552{ 553 int sdata; 554 555 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORTEMPBASE + edata->sensor); 556 /* sensor is not connected or reporting invalid data */ 557 if (sdata == 0 || sdata >= 0xfa) { 558 edata->state = ENVSYS_SINVALID; 559 return; 560 } 561 562 DPRINTF(("%s: sdata[temp%d] 0x%x\n", __func__, edata->sensor, sdata)); 563 /* Convert temperature to uK */ 564 edata->value_cur = sdata * 1000000 + 273150000; 565 edata->state = ENVSYS_SVALID; 566} 567 568static void 569itesio_refresh_volts(struct itesio_softc *sc, envsys_data_t *edata) 570{ 571 uint8_t vbatcr = 0; 572 int i, sdata; 573 574 i = edata->sensor - sc->sc_config.voltstart_idx; 575 576 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORVOLTBASE + i); 577 /* not connected */ 578 if (sdata == 0 || sdata == 0xff) { 579 edata->state = ENVSYS_SINVALID; 580 return; 581 } 582 583 /* 584 * update VBAT voltage reading every time we read it, to get 585 * latest value. 586 */ 587 if (i == 8) { 588 vbatcr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG); 589 SET(vbatcr, ITESIO_EC_UPDATEVBAT); 590 itesio_ecwritereg(sc, ITESIO_EC_CONFIG, vbatcr); 591 } 592 593 DPRINTF(("%s: sdata[volt%d] 0x%x\n", __func__, i, sdata)); 594 595 /* voltage returned as (mV << 4) */ 596 edata->value_cur = (sdata << 4); 597 /* negative values */ 598 if (i == 5 || i == 6) 599 edata->value_cur -= ITESIO_EC_VREF; 600 /* rfact is (factor * 10^4) */ 601 if (edata->rfact) 602 edata->value_cur *= edata->rfact; 603 else 604 edata->value_cur *= itesio_vrfact[i]; 605 /* division by 10 gets us back to uVDC */ 606 edata->value_cur /= 10; 607 if (i == 5 || i == 6) 608 edata->value_cur += ITESIO_EC_VREF * 1000; 609 610 edata->state = ENVSYS_SVALID; 611} 612 613static void 614itesio_refresh_it8625_volts(struct itesio_softc *sc, envsys_data_t *edata) 615{ 616 int i, sdata; 617 618 i = edata->sensor - sc->sc_config.voltstart_idx; 619 620 if (i < 9) 621 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORVOLTBASE + i); 622 else 623 sdata = itesio_ecreadreg(sc, 624 ITESIO_EC_SENSORVOLTEXTBASE + i - 9); 625 /* not connected */ 626 if (sdata == 0 || sdata == 0xff) { 627 edata->state = ENVSYS_SINVALID; 628 return; 629 } 630 631 DPRINTF(("%s: sdata[volt%d] 0x%x\n", __func__, i, sdata)); 632 633 if (i == 7) { 634 /* Internal 3VSB: reading value * 2 * 10.9mV */ 635 edata->value_cur = sdata * 2 * 109; 636 } else { 637 /* other: reading value * 10.9mV */ 638 edata->value_cur = sdata * 109; 639 } 640 /* rfact is (factor * 10^4) */ 641 if (edata->rfact) 642 edata->value_cur *= edata->rfact; 643 else 644 edata->value_cur *= RFACT_NONE; 645 /* division by 100 gets us back to uVDC */ 646 edata->value_cur /= 100; 647 edata->state = ENVSYS_SVALID; 648} 649 650static void 651itesio_refresh_fans(struct itesio_softc *sc, envsys_data_t *edata) 652{ 653 uint8_t mode; 654 uint16_t sdata; 655 int i; 656 657 i = edata->sensor - sc->sc_config.fanstart_idx; 658 659 mode = itesio_ecreadreg(sc, ITESIO_EC_FAN16_CER); 660 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i); 661 if (mode & (1 << i)) 662 sdata += (itesio_ecreadreg(sc, 663 ITESIO_EC_SENSORFANEXTBASE + i) << 8); 664 edata->state = ENVSYS_SVALID; 665 if (sdata == 0 || 666 sdata == ((mode & (1 << i)) ? 0xffff : 0xff)) 667 edata->state = ENVSYS_SINVALID; 668 else { 669 edata->value_cur = 1350000 / 2 / sdata; 670 edata->state = ENVSYS_SVALID; 671 } 672 DPRINTF(("%s: 16bit sdata[fan%d] 0x%x\n", __func__, i, sdata)); 673} 674 675static void 676itesio_refresh_it8705_fans(struct itesio_softc *sc, envsys_data_t *edata) 677{ 678 uint16_t sdata; 679 int i, divisor, odivisor, ndivisor; 680 681 i = edata->sensor - sc->sc_config.fanstart_idx; 682 683 /* 684 * Use the Fan Tachometer Divisor Register for 685 * IT8705F and IT8712F. 686 */ 687 divisor = odivisor = ndivisor = 688 itesio_ecreadreg(sc, ITESIO_EC_FAN_TDR); 689 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i); 690 if (sdata == 0xff) { 691 edata->state = ENVSYS_SINVALID; 692 if (i == 2) 693 ndivisor |= 0x40; 694 else { 695 ndivisor &= ~(7 << (i * 3)); 696 ndivisor |= ((divisor + 1) & 7) << (i * 3); 697 } 698 } else { 699 if (i == 2) 700 divisor = divisor & 1 ? 3 : 1; 701 702 if ((sdata << (divisor & 7)) == 0) 703 edata->state = ENVSYS_SINVALID; 704 else { 705 edata->value_cur = 706 1350000 / (sdata << (divisor & 7)); 707 edata->state = ENVSYS_SVALID; 708 } 709 } 710 DPRINTF(("%s: 8bit sdata[fan%d] 0x%x div: 0x%x\n", __func__, 711 i, sdata, divisor)); 712 if (ndivisor != odivisor) 713 itesio_ecwritereg(sc, ITESIO_EC_FAN_TDR, ndivisor); 714} 715 716static void 717itesio_refresh_it8625_fans(struct itesio_softc *sc, envsys_data_t *edata) 718{ 719 uint16_t sdata; 720 int i; 721 722 i = edata->sensor - sc->sc_config.fanstart_idx; 723 724 switch (i) { 725 case 0: 726 case 1: 727 case 2: 728 sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i); 729 sdata += (itesio_ecreadreg(sc, 730 ITESIO_EC_SENSORFANEXTBASE + i) << 8); 731 break; 732 case 3: 733 sdata = itesio_ecreadreg(sc, IT8625_EC_SENSORFAN4_LSB); 734 sdata += itesio_ecreadreg(sc, IT8625_EC_SENSORFAN4_MSB) << 8; 735 break; 736 case 4: 737 sdata = itesio_ecreadreg(sc, IT8625_EC_SENSORFAN5_LSB); 738 sdata += itesio_ecreadreg(sc, IT8625_EC_SENSORFAN5_MSB) << 8; 739 break; 740 case 5: 741 sdata = itesio_ecreadreg(sc, IT8625_EC_SENSORFAN6_LSB); 742 sdata += itesio_ecreadreg(sc, IT8625_EC_SENSORFAN6_MSB) << 8; 743 break; 744 default: 745 edata->state = ENVSYS_SINVALID; 746 return; 747 } 748 edata->state = ENVSYS_SVALID; 749 if (sdata == 0 || sdata == 0xffff) 750 edata->state = ENVSYS_SINVALID; 751 else { 752 edata->value_cur = 1350000 / 2 / sdata; 753 edata->state = ENVSYS_SVALID; 754 } 755 DPRINTF(("%s: 16bit sdata[fan%d] 0x%x\n", __func__, i, sdata)); 756} 757 758static void 759itesio_refresh(struct sysmon_envsys *sme, struct envsys_data *edata) 760{ 761 struct itesio_softc *sc = sme->sme_cookie; 762 763 if (edata->sensor < sc->sc_config.voltstart_idx) 764 (*sc->sc_config.refresh_temp)(sc, edata); 765 else if (edata->sensor >= sc->sc_config.voltstart_idx && 766 edata->sensor < sc->sc_config.fanstart_idx) 767 (*sc->sc_config.refresh_volts)(sc, edata); 768 else 769 (*sc->sc_config.refresh_fans)(sc, edata); 770} 771 772static int 773itesio_wdt_setmode(struct sysmon_wdog *smw) 774{ 775 struct itesio_softc *sc = smw->smw_cookie; 776 int period = smw->smw_period; 777 778 /* Enter MB PNP mode and select the WDT LDN */ 779 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 780 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 781 ITESIO_WDT_LDN); 782 783 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 784 /* Disable the watchdog */ 785 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CTL, 0); 786 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF, 0); 787 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 0); 788 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 0); 789 } else { 790 /* Enable the watchdog */ 791 if (period > ITESIO_WDT_MAXTIMO || period < 1) 792 period = smw->smw_period = ITESIO_WDT_MAXTIMO; 793 794 period *= 2; 795 796 /* set the timeout and start the watchdog */ 797 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 798 period >> 8); 799 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 800 period & 0xff); 801 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF, 802 ITESIO_WDT_CNF_SECS | ITESIO_WDT_CNF_KRST | 803 ITESIO_WDT_CNF_PWROK); 804 } 805 /* we are done, exit MB PNP mode */ 806 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 807 808 return 0; 809} 810 811static int 812itesio_wdt_tickle(struct sysmon_wdog *smw) 813{ 814 struct itesio_softc *sc = smw->smw_cookie; 815 int period = smw->smw_period * 2; 816 817 /* refresh timeout value and exit */ 818 itesio_enter(sc->sc_iot, sc->sc_pnp_ioh); 819 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL, 820 ITESIO_WDT_LDN); 821 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 822 period >> 8); 823 itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 824 period & 0xff); 825 itesio_exit(sc->sc_iot, sc->sc_pnp_ioh); 826 827 return 0; 828} 829 830MODULE(MODULE_CLASS_DRIVER, itesio, "sysmon_envsys,sysmon_wdog"); 831 832#ifdef _MODULE 833#include "ioconf.c" 834#endif 835 836static int 837itesio_modcmd(modcmd_t cmd, void *opaque) 838{ 839 switch (cmd) { 840 case MODULE_CMD_INIT: 841#ifdef _MODULE 842 return config_init_component(cfdriver_ioconf_itesio, 843 cfattach_ioconf_itesio, cfdata_ioconf_itesio); 844#else 845 return 0; 846#endif 847 case MODULE_CMD_FINI: 848#ifdef _MODULE 849 return config_fini_component(cfdriver_ioconf_itesio, 850 cfattach_ioconf_itesio, cfdata_ioconf_itesio); 851#else 852 return 0; 853#endif 854 default: 855 return ENOTTY; 856 } 857} 858