1 /* $OpenBSD: it.c,v 1.46 2015/03/14 03:38:47 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2007-2008 Oleg Safiullin <form@pdp-11.org.ru> 5 * Copyright (c) 2006-2007 Juan Romero Pardines <juan@xtrarom.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 LIMITED 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 LIMITED 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 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/device.h> 33 #include <sys/sensors.h> 34 35 #include <machine/bus.h> 36 37 #include <dev/isa/isavar.h> 38 #include <dev/isa/itvar.h> 39 40 41 #if defined(ITDEBUG) 42 #define DPRINTF(x) do { printf x; } while (0) 43 #else 44 #define DPRINTF(x) 45 #endif 46 47 48 int it_match(struct device *, void *, void *); 49 void it_attach(struct device *, struct device *, void *); 50 int it_activate(struct device *, int); 51 u_int8_t it_readreg(bus_space_tag_t, bus_space_handle_t, int); 52 void it_writereg(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); 53 void it_enter(bus_space_tag_t, bus_space_handle_t, int); 54 void it_exit(bus_space_tag_t, bus_space_handle_t); 55 56 u_int8_t it_ec_readreg(struct it_softc *, int); 57 void it_ec_writereg(struct it_softc *, int, u_int8_t); 58 void it_ec_refresh(void *arg); 59 60 int it_wdog_cb(void *, int); 61 62 /* 63 * IT87-compatible chips can typically measure voltages up to 4.096 V. 64 * To measure higher voltages the input is attenuated with (external) 65 * resistors. Negative voltages are measured using a reference 66 * voltage. So we have to convert the sensor values back to real 67 * voltages by applying the appropriate resistor factor. 68 */ 69 #define RFACT_NONE 10000 70 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y)) 71 72 73 struct { 74 enum sensor_type type; 75 const char *desc; 76 } it_sensors[IT_EC_NUMSENSORS] = { 77 #define IT_TEMP_BASE 0 78 #define IT_TEMP_COUNT 3 79 { SENSOR_TEMP, NULL }, 80 { SENSOR_TEMP, NULL }, 81 { SENSOR_TEMP, NULL }, 82 83 #define IT_FAN_BASE 3 84 #define IT_FAN_COUNT 5 85 { SENSOR_FANRPM, NULL }, 86 { SENSOR_FANRPM, NULL }, 87 { SENSOR_FANRPM, NULL }, 88 { SENSOR_FANRPM, NULL }, 89 { SENSOR_FANRPM, NULL }, 90 91 #define IT_VOLT_BASE 8 92 #define IT_VOLT_COUNT 9 93 { SENSOR_VOLTS_DC, "VCORE_A" }, 94 { SENSOR_VOLTS_DC, "VCORE_B" }, 95 { SENSOR_VOLTS_DC, "+3.3V" }, 96 { SENSOR_VOLTS_DC, "+5V" }, 97 { SENSOR_VOLTS_DC, "+12V" }, 98 { SENSOR_VOLTS_DC, "-12V" }, 99 { SENSOR_VOLTS_DC, "-5V" }, 100 { SENSOR_VOLTS_DC, "+5VSB" }, 101 { SENSOR_VOLTS_DC, "VBAT" } 102 }; 103 104 /* rfact values for voltage sensors */ 105 int it_vrfact[IT_VOLT_COUNT] = { 106 RFACT_NONE, /* VCORE_A */ 107 RFACT_NONE, /* VCORE_A */ 108 RFACT_NONE, /* +3.3V */ 109 RFACT(68, 100), /* +5V */ 110 RFACT(30, 10), /* +12V */ 111 RFACT(83, 20), /* -12V */ 112 RFACT(21, 10), /* -5V */ 113 RFACT(68, 100), /* +5VSB */ 114 RFACT_NONE /* VBAT */ 115 }; 116 117 int it_fan_regs[] = { 118 IT_EC_FAN_TAC1, IT_EC_FAN_TAC2, IT_EC_FAN_TAC3, 119 IT_EC_FAN_TAC4_LSB, IT_EC_FAN_TAC5_LSB 120 }; 121 122 int it_fan_ext_regs[] = { 123 IT_EC_FAN_EXT_TAC1, IT_EC_FAN_EXT_TAC2, IT_EC_FAN_EXT_TAC3, 124 IT_EC_FAN_TAC4_MSB, IT_EC_FAN_TAC5_MSB 125 }; 126 127 LIST_HEAD(, it_softc) it_softc_list = LIST_HEAD_INITIALIZER(it_softc_list); 128 129 130 int 131 it_match(struct device *parent, void *match, void *aux) 132 { 133 struct isa_attach_args *ia = aux; 134 struct it_softc *sc; 135 bus_space_handle_t ioh; 136 int ec_iobase, found = 0; 137 u_int16_t cr; 138 139 if (ia->ipa_io[0].base != IO_IT1 && ia->ipa_io[0].base != IO_IT2) 140 return (0); 141 142 /* map i/o space */ 143 if (bus_space_map(ia->ia_iot, ia->ipa_io[0].base, 2, 0, &ioh) != 0) { 144 DPRINTF(("it_match: can't map i/o space")); 145 return (0); 146 } 147 148 /* enter MB PnP mode */ 149 it_enter(ia->ia_iot, ioh, ia->ipa_io[0].base); 150 151 /* 152 * SMSC or similar SuperIO chips use 0x55 magic to enter PnP mode 153 * and 0xaa to exit. These chips also enter PnP mode via ITE 154 * `enter MB PnP mode' sequence, so force chip to exit PnP mode 155 * if this is the case. 156 */ 157 bus_space_write_1(ia->ia_iot, ioh, IT_IO_ADDR, 0xaa); 158 159 /* get chip id */ 160 cr = it_readreg(ia->ia_iot, ioh, IT_CHIPID1) << 8; 161 cr |= it_readreg(ia->ia_iot, ioh, IT_CHIPID2); 162 163 switch (cr) { 164 case IT_ID_8705: 165 case IT_ID_8712: 166 case IT_ID_8716: 167 case IT_ID_8718: 168 case IT_ID_8720: 169 case IT_ID_8721: 170 case IT_ID_8726: 171 case IT_ID_8728: 172 case IT_ID_8772: 173 /* get environment controller base address */ 174 it_writereg(ia->ia_iot, ioh, IT_LDN, IT_EC_LDN); 175 ec_iobase = it_readreg(ia->ia_iot, ioh, IT_EC_MSB) << 8; 176 ec_iobase |= it_readreg(ia->ia_iot, ioh, IT_EC_LSB); 177 178 /* check if device already attached */ 179 LIST_FOREACH(sc, &it_softc_list, sc_list) 180 if (sc->sc_ec_iobase == ec_iobase) 181 break; 182 183 if (sc == NULL) { 184 ia->ipa_nio = 1; 185 ia->ipa_io[0].length = 2; 186 ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0; 187 found++; 188 } 189 190 break; 191 } 192 193 /* exit MB PnP mode */ 194 it_exit(ia->ia_iot, ioh); 195 196 /* unmap i/o space */ 197 bus_space_unmap(ia->ia_iot, ioh, 2); 198 199 return (found); 200 } 201 202 void 203 it_attach(struct device *parent, struct device *self, void *aux) 204 { 205 struct it_softc *sc = (void *)self; 206 struct isa_attach_args *ia = aux; 207 int i; 208 209 sc->sc_iot = ia->ia_iot; 210 sc->sc_iobase = ia->ipa_io[0].base; 211 if (bus_space_map(sc->sc_iot, sc->sc_iobase, 2, 0, &sc->sc_ioh) != 0) { 212 printf(": can't map i/o space\n"); 213 return; 214 } 215 216 /* enter MB PnP mode */ 217 it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase); 218 219 /* get chip id and rev */ 220 sc->sc_chipid = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID1) << 8; 221 sc->sc_chipid |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID2); 222 sc->sc_chiprev = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPREV) & 0x0f; 223 224 /* get environment controller base address */ 225 it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_EC_LDN); 226 sc->sc_ec_iobase = it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_MSB) << 8; 227 sc->sc_ec_iobase |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_LSB); 228 229 /* initialize watchdog timer */ 230 if (sc->sc_chipid != IT_ID_8705) { 231 it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN); 232 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_CSR, 0x00); 233 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00); 234 wdog_register(it_wdog_cb, sc); 235 } 236 237 /* exit MB PnP mode and unmap */ 238 it_exit(sc->sc_iot, sc->sc_ioh); 239 240 LIST_INSERT_HEAD(&it_softc_list, sc, sc_list); 241 printf(": IT%xF rev %X", sc->sc_chipid, sc->sc_chiprev); 242 243 if (sc->sc_ec_iobase == 0) { 244 printf(", EC disabled\n"); 245 return; 246 } 247 248 printf(", EC port 0x%x\n", sc->sc_ec_iobase); 249 250 /* map environment controller i/o space */ 251 sc->sc_ec_iot = ia->ia_iot; 252 if (bus_space_map(sc->sc_ec_iot, sc->sc_ec_iobase, 8, 0, 253 &sc->sc_ec_ioh) != 0) { 254 printf("%s: can't map EC i/o space\n", sc->sc_dev.dv_xname); 255 return; 256 } 257 258 /* initialize sensor structures */ 259 for (i = 0; i < IT_EC_NUMSENSORS; i++) { 260 sc->sc_sensors[i].type = it_sensors[i].type; 261 262 if (it_sensors[i].desc != NULL) 263 strlcpy(sc->sc_sensors[i].desc, it_sensors[i].desc, 264 sizeof(sc->sc_sensors[i].desc)); 265 } 266 267 /* register sensor update task */ 268 if (sensor_task_register(sc, it_ec_refresh, IT_EC_INTERVAL) == NULL) { 269 printf("%s: unable to register update task\n", 270 sc->sc_dev.dv_xname); 271 bus_space_unmap(sc->sc_ec_iot, sc->sc_ec_ioh, 8); 272 return; 273 } 274 275 /* use 16-bit FAN tachometer registers for newer chips */ 276 if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712) 277 it_ec_writereg(sc, IT_EC_FAN_ECER, 278 it_ec_readreg(sc, IT_EC_FAN_ECER) | 0x07); 279 280 /* activate monitoring */ 281 it_ec_writereg(sc, IT_EC_CFG, 282 it_ec_readreg(sc, IT_EC_CFG) | IT_EC_CFG_START | IT_EC_CFG_INTCLR); 283 284 /* initialize sensors */ 285 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 286 sizeof(sc->sc_sensordev.xname)); 287 for (i = 0; i < IT_EC_NUMSENSORS; i++) 288 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 289 sensordev_install(&sc->sc_sensordev); 290 } 291 292 int 293 it_activate(struct device *self, int act) 294 { 295 switch (act) { 296 case DVACT_POWERDOWN: 297 wdog_shutdown(self); 298 break; 299 } 300 301 return (0); 302 } 303 304 u_int8_t 305 it_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int r) 306 { 307 bus_space_write_1(iot, ioh, IT_IO_ADDR, r); 308 return (bus_space_read_1(iot, ioh, IT_IO_DATA)); 309 } 310 311 void 312 it_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int r, u_int8_t v) 313 { 314 bus_space_write_1(iot, ioh, IT_IO_ADDR, r); 315 bus_space_write_1(iot, ioh, IT_IO_DATA, v); 316 } 317 318 void 319 it_enter(bus_space_tag_t iot, bus_space_handle_t ioh, int iobase) 320 { 321 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x87); 322 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x01); 323 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55); 324 if (iobase == IO_IT1) 325 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55); 326 else 327 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0xaa); 328 } 329 330 void 331 it_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 332 { 333 bus_space_write_1(iot, ioh, IT_IO_ADDR, IT_CCR); 334 bus_space_write_1(iot, ioh, IT_IO_DATA, 0x02); 335 } 336 337 u_int8_t 338 it_ec_readreg(struct it_softc *sc, int r) 339 { 340 bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r); 341 return (bus_space_read_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA)); 342 } 343 344 void 345 it_ec_writereg(struct it_softc *sc, int r, u_int8_t v) 346 { 347 bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r); 348 bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA, v); 349 } 350 351 void 352 it_ec_refresh(void *arg) 353 { 354 struct it_softc *sc = arg; 355 int i, sdata, divisor, odivisor, ndivisor; 356 u_int8_t cr, ecr; 357 358 /* refresh temp sensors */ 359 cr = it_ec_readreg(sc, IT_EC_ADC_TEMPER); 360 361 for (i = 0; i < IT_TEMP_COUNT; i++) { 362 sc->sc_sensors[IT_TEMP_BASE + i].flags &= 363 SENSOR_FINVALID; 364 365 if (!(cr & (1 << i)) && !(cr & (1 << (i + 3)))) { 366 sc->sc_sensors[IT_TEMP_BASE + i].flags |= 367 SENSOR_FINVALID; 368 continue; 369 } 370 371 sdata = it_ec_readreg(sc, IT_EC_TEMPBASE + i); 372 /* convert to degF */ 373 sc->sc_sensors[IT_TEMP_BASE + i].value = 374 sdata * 1000000 + 273150000; 375 } 376 377 /* refresh volt sensors */ 378 cr = it_ec_readreg(sc, IT_EC_ADC_VINER); 379 380 for (i = 0; i < IT_VOLT_COUNT; i++) { 381 sc->sc_sensors[IT_VOLT_BASE + i].flags &= 382 SENSOR_FINVALID; 383 384 if ((i < 8) && !(cr & (1 << i))) { 385 sc->sc_sensors[IT_VOLT_BASE + i].flags |= 386 SENSOR_FINVALID; 387 continue; 388 } 389 390 sdata = it_ec_readreg(sc, IT_EC_VOLTBASE + i); 391 /* voltage returned as (mV >> 4) */ 392 sc->sc_sensors[IT_VOLT_BASE + i].value = sdata << 4; 393 /* these two values are negative and formula is different */ 394 if (i == 5 || i == 6) 395 sc->sc_sensors[IT_VOLT_BASE + i].value -= IT_EC_VREF; 396 /* rfact is (factor * 10^4) */ 397 sc->sc_sensors[IT_VOLT_BASE + i].value *= it_vrfact[i]; 398 /* division by 10 gets us back to uVDC */ 399 sc->sc_sensors[IT_VOLT_BASE + i].value /= 10; 400 if (i == 5 || i == 6) 401 sc->sc_sensors[IT_VOLT_BASE + i].value += 402 IT_EC_VREF * 1000; 403 } 404 405 /* refresh fan sensors */ 406 cr = it_ec_readreg(sc, IT_EC_FAN_MCR); 407 408 if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712) { 409 /* use 16-bit FAN tachometer registers */ 410 ecr = it_ec_readreg(sc, IT_EC_FAN_ECER); 411 412 for (i = 0; i < IT_FAN_COUNT; i++) { 413 sc->sc_sensors[IT_FAN_BASE + i].flags &= 414 ~SENSOR_FINVALID; 415 416 if (i < 3 && !(cr & (1 << (i + 4)))) { 417 sc->sc_sensors[IT_FAN_BASE + i].flags |= 418 SENSOR_FINVALID; 419 continue; 420 } else if (i > 2 && !(ecr & (1 << (i + 1)))) { 421 sc->sc_sensors[IT_FAN_BASE + i].flags |= 422 SENSOR_FINVALID; 423 continue; 424 } 425 426 sdata = it_ec_readreg(sc, it_fan_regs[i]); 427 sdata |= it_ec_readreg(sc, it_fan_ext_regs[i]) << 8; 428 429 if (sdata == 0 || sdata == 0xffff) 430 sc->sc_sensors[IT_FAN_BASE + i].value = 0; 431 else 432 sc->sc_sensors[IT_FAN_BASE + i].value = 433 675000 / sdata; 434 } 435 } else { 436 /* use 8-bit FAN tachometer & FAN divisor registers */ 437 odivisor = ndivisor = divisor = 438 it_ec_readreg(sc, IT_EC_FAN_DIV); 439 440 for (i = 0; i < IT_FAN_COUNT; i++) { 441 if (i > 2 || !(cr & (1 << (i + 4)))) { 442 sc->sc_sensors[IT_FAN_BASE + i].flags |= 443 SENSOR_FINVALID; 444 continue; 445 } 446 447 sc->sc_sensors[IT_FAN_BASE + i].flags &= 448 ~SENSOR_FINVALID; 449 450 sdata = it_ec_readreg(sc, it_fan_regs[i]); 451 452 if (sdata == 0xff) { 453 sc->sc_sensors[IT_FAN_BASE + i].value = 0; 454 455 if (i == 2) 456 ndivisor ^= 0x40; 457 else { 458 ndivisor &= ~(7 << (i * 3)); 459 ndivisor |= ((divisor + 1) & 7) << 460 (i * 3); 461 } 462 } else if (sdata != 0) { 463 if (i == 2) 464 divisor = divisor & 1 ? 3 : 1; 465 sc->sc_sensors[IT_FAN_BASE + i].value = 466 1350000 / (sdata << (divisor & 7)); 467 } else 468 sc->sc_sensors[IT_FAN_BASE + i].value = 0; 469 } 470 471 if (ndivisor != odivisor) 472 it_ec_writereg(sc, IT_EC_FAN_DIV, ndivisor); 473 } 474 } 475 476 int 477 it_wdog_cb(void *arg, int period) 478 { 479 struct it_softc *sc = arg; 480 int minutes = 0; 481 482 /* enter MB PnP mode and select WDT device */ 483 it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase); 484 it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN); 485 486 /* disable watchdog timer */ 487 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00); 488 489 /* 1000s should be enough for everyone */ 490 if (period > 1000) 491 period = 1000; 492 else if (period < 0) 493 period = 0; 494 495 if (period > 0) { 496 /* 497 * Older IT8712F chips have 8-bit timeout counter. 498 * Use minutes for 16-bit values for these chips. 499 */ 500 if (sc->sc_chipid == IT_ID_8712 && sc->sc_chiprev < 0x8 && 501 period > 0xff) { 502 if (period % 60 >= 30) 503 period += 60; 504 period /= 60; 505 minutes++; 506 } 507 508 /* set watchdog timeout (low byte) */ 509 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_LSB, 510 period & 0xff); 511 512 if (minutes) { 513 /* enable watchdog timer */ 514 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 515 IT_WDT_TCR_KRST | IT_WDT_TCR_PWROK); 516 517 period *= 60; 518 } else { 519 /* set watchdog timeout (high byte) */ 520 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_MSB, 521 period >> 8); 522 523 /* enable watchdog timer */ 524 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 525 IT_WDT_TCR_SECS | IT_WDT_TCR_KRST | 526 IT_WDT_TCR_PWROK); 527 } 528 } 529 530 /* exit MB PnP mode */ 531 it_exit(sc->sc_iot, sc->sc_ioh); 532 533 return (period); 534 } 535 536 537 struct cfattach it_ca = { 538 sizeof(struct it_softc), 539 it_match, 540 it_attach, 541 NULL, 542 it_activate 543 }; 544 545 struct cfdriver it_cd = { 546 NULL, "it", DV_DULL 547 }; 548