1 /* $OpenBSD: fins.c,v 1.1 2008/03/19 19:33:09 deraadt Exp $ */ 2 /* $NetBSD: finsio_isa.c,v 1.9 2022/06/29 15:56:58 mlelstv Exp $ */ 3 4 /* 5 * Copyright (c) 2008 Juan Romero Pardines 6 * Copyright (c) 2007, 2008 Geoff Steckel 7 * Copyright (c) 2005, 2006 Mark Kettenis 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: finsio_isa.c,v 1.9 2022/06/29 15:56:58 mlelstv Exp $"); 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/device.h> 27 #include <sys/module.h> 28 #include <sys/bus.h> 29 30 #include <dev/isa/isareg.h> 31 #include <dev/isa/isavar.h> 32 33 #include <dev/sysmon/sysmonvar.h> 34 35 /* Derived from LM78 code. Only handles chips attached to ISA bus */ 36 37 /* 38 * Fintek F71805/F71883 Super I/O datasheets: 39 * http://www.fintek.com.tw/files/productfiles/F71805F_V025.pdf 40 * http://www.fintek.com.tw/files/productfiles/F71883_V026P.pdf 41 * 42 * This chip is a multi-io chip with many functions. 43 * Each function may be relocated in I/O space by the BIOS. 44 * The base address (2E or 4E) accesses a configuration space which 45 * has pointers to the individual functions. The config space must be 46 * unlocked with a cookie and relocked afterwards. The chip ID is stored 47 * in config space so it is not normally visible. 48 * 49 * The voltage dividers specified are from reading the chips on one board. 50 * There is no way to determine what they are in the general case. 51 */ 52 53 #define FINSIO_UNLOCK 0x87 /* magic constant - write 2x to select chip */ 54 #define FINSIO_LOCK 0xaa /* magic constant - write 1x to deselect reg */ 55 56 #define FINSIO_FUNC_SEL 0x07 /* select which subchip to access */ 57 # define FINSIO_FUNC_HWMON 0x4 58 59 /* ISA registers index to an internal register space on chip */ 60 #define FINSIO_DECODE_SIZE (8) 61 #define FINSIO_DECODE_MASK (FINSIO_DECODE_SIZE - 1) 62 #define FINSIO_ADDR 5 /* global configuration index */ 63 #define FINSIO_DATA 6 /* and data registers */ 64 65 /* Global configuration registers */ 66 #define FINSIO_MANUF 0x23 /* manufacturer ID */ 67 # define FINTEK_ID 0x1934 68 #define FINSIO_CHIP 0x20 /* chip ID */ 69 # define FINSIO_IDF71805 0x0406 70 # define FINSIO_IDF71806 0x0341 /* F71872 and F1806 F/FG */ 71 # define FINSIO_IDF71883 0x0541 /* F71882 and F1883 */ 72 # define FINSIO_IDF71862 0x0601 /* F71862FG */ 73 # define FINSIO_IDF8000 0x0581 /* F8000 */ 74 75 /* in bank sensors of config space */ 76 #define FINSIO_SENSADDR 0x60 /* sensors assigned I/O address (2 bytes) */ 77 78 #define FINSIO_HWMON_CONF 0x01 /* Hardware Monitor Config. Register */ 79 80 /* in sensors space */ 81 #define FINSIO_TMODE 0x01 /* temperature mode reg */ 82 83 #define FINSIO_MAX_SENSORS 20 84 /* 85 * Fintek chips typically measure voltages using 8mv steps. 86 * To measure higher voltages the input is attenuated with (external) 87 * resistors. Negative voltages are measured using inverting op amps 88 * and resistors. So we have to convert the sensor values back to 89 * real voltages by applying the appropriate resistor factor. 90 */ 91 #define FRFACT_NONE 8000 92 #define FRFACT(x, y) (FRFACT_NONE * ((x) + (y)) / (y)) 93 #define FNRFACT(x, y) (-FRFACT_NONE * (x) / (y)) 94 95 #if defined(FINSIODEBUG) 96 #define DPRINTF(x) do { printf x; } while (0) 97 #else 98 #define DPRINTF(x) 99 #endif 100 101 struct finsio_softc { 102 bus_space_tag_t sc_iot; 103 bus_space_handle_t sc_ioh; 104 105 struct sysmon_envsys *sc_sme; 106 envsys_data_t sc_sensor[FINSIO_MAX_SENSORS]; 107 struct finsio_sensor *sc_finsio_sensors; 108 109 u_int sc_tempsel; 110 }; 111 112 struct finsio_sensor { 113 const char *fs_desc; 114 u_int fs_type; 115 uint8_t fs_aux; 116 uint8_t fs_reg; 117 void (*fs_refresh)(struct finsio_softc *, envsys_data_t *); 118 int fs_rfact; 119 }; 120 121 static int finsio_isa_match(device_t, cfdata_t, void *); 122 static void finsio_isa_attach(device_t, device_t, void *); 123 static int finsio_isa_detach(device_t, int); 124 125 static void finsio_enter(bus_space_tag_t, bus_space_handle_t); 126 static void finsio_exit(bus_space_tag_t, bus_space_handle_t); 127 static uint8_t finsio_readreg(bus_space_tag_t, bus_space_handle_t, int); 128 static void finsio_writereg(bus_space_tag_t, bus_space_handle_t, int, int); 129 130 static void finsio_refresh(struct sysmon_envsys *, envsys_data_t *); 131 static void finsio_refresh_volt(struct finsio_softc *, envsys_data_t *); 132 static void finsio_refresh_temp(struct finsio_softc *, envsys_data_t *); 133 static void finsio_refresh_fanrpm(struct finsio_softc *, envsys_data_t *); 134 135 CFATTACH_DECL_NEW(finsio, sizeof(struct finsio_softc), 136 finsio_isa_match, finsio_isa_attach, finsio_isa_detach, NULL); 137 138 /* Sensors available in F71805/F71806 */ 139 static struct finsio_sensor f71805_sensors[] = { 140 /* Voltage */ 141 { 142 .fs_desc = "+3.3V", 143 .fs_type = ENVSYS_SVOLTS_DC, 144 .fs_aux = 0, 145 .fs_reg = 0x10, 146 .fs_refresh = finsio_refresh_volt, 147 .fs_rfact = FRFACT(100, 100) 148 }, 149 { 150 .fs_desc = "Vtt", 151 .fs_type = ENVSYS_SVOLTS_DC, 152 .fs_aux = 0, 153 .fs_reg = 0x11, 154 .fs_refresh = finsio_refresh_volt, 155 .fs_rfact = FRFACT_NONE 156 }, 157 { 158 .fs_desc = "Vram", 159 .fs_type = ENVSYS_SVOLTS_DC, 160 .fs_aux = 0, 161 .fs_reg = 0x12, 162 .fs_refresh = finsio_refresh_volt, 163 .fs_rfact = FRFACT(100, 100) 164 }, 165 { 166 .fs_desc = "Vchips", 167 .fs_type = ENVSYS_SVOLTS_DC, 168 .fs_aux = 0, 169 .fs_reg = 0x13, 170 .fs_refresh = finsio_refresh_volt, 171 .fs_rfact = FRFACT(47, 100) 172 }, 173 { 174 .fs_desc = "+5V", 175 .fs_type = ENVSYS_SVOLTS_DC, 176 .fs_aux = 0, 177 .fs_reg = 0x14, 178 .fs_refresh = finsio_refresh_volt, 179 .fs_rfact = FRFACT(200, 47) 180 }, 181 { 182 .fs_desc = "+12V", 183 .fs_type = ENVSYS_SVOLTS_DC, 184 .fs_aux = 0, 185 .fs_reg = 0x15, 186 .fs_refresh = finsio_refresh_volt, 187 .fs_rfact = FRFACT(200, 20) 188 }, 189 { 190 .fs_desc = "Vcc 1.5V", 191 .fs_type = ENVSYS_SVOLTS_DC, 192 .fs_aux = 0, 193 .fs_reg = 0x16, 194 .fs_refresh = finsio_refresh_volt, 195 .fs_rfact = FRFACT_NONE 196 }, 197 { 198 .fs_desc = "VCore", 199 .fs_type = ENVSYS_SVOLTS_DC, 200 .fs_aux = 0, 201 .fs_reg = 0x17, 202 .fs_refresh = finsio_refresh_volt, 203 .fs_rfact = FRFACT_NONE 204 }, 205 { 206 .fs_desc = "Vsb", 207 .fs_type = ENVSYS_SVOLTS_DC, 208 .fs_aux = 0, 209 .fs_reg = 0x18, 210 .fs_refresh = finsio_refresh_volt, 211 .fs_rfact = FRFACT(200, 47) 212 }, 213 { 214 .fs_desc = "Vsbint", 215 .fs_type = ENVSYS_SVOLTS_DC, 216 .fs_aux = 0, 217 .fs_reg = 0x19, 218 .fs_refresh = finsio_refresh_volt, 219 .fs_rfact = FRFACT(200, 47) 220 }, 221 { 222 .fs_desc = "Vbat", 223 .fs_type = ENVSYS_SVOLTS_DC, 224 .fs_aux = 0, 225 .fs_reg = 0x1a, 226 .fs_refresh = finsio_refresh_volt, 227 .fs_rfact = FRFACT(200, 47) 228 }, 229 /* Temperature */ 230 { 231 .fs_desc = "Temp1", 232 .fs_type = ENVSYS_STEMP, 233 .fs_aux = 0x01, 234 .fs_reg = 0x1b, 235 .fs_refresh = finsio_refresh_temp, 236 .fs_rfact = 0 237 }, 238 { 239 .fs_desc = "Temp2", 240 .fs_type = ENVSYS_STEMP, 241 .fs_aux = 0x02, 242 .fs_reg = 0x1c, 243 .fs_refresh = finsio_refresh_temp, 244 .fs_rfact = 0 245 }, 246 { 247 .fs_desc = "Temp3", 248 .fs_type = ENVSYS_STEMP, 249 .fs_aux = 0x04, 250 .fs_reg = 0x1d, 251 .fs_refresh = finsio_refresh_temp, 252 .fs_rfact = 0 253 }, 254 /* Fans */ 255 { 256 .fs_desc = "Fan1", 257 .fs_type = ENVSYS_SFANRPM, 258 .fs_aux = 0, 259 .fs_reg = 0x20, 260 .fs_refresh = finsio_refresh_fanrpm, 261 .fs_rfact = 0 262 }, 263 { 264 .fs_desc = "Fan2", 265 .fs_type = ENVSYS_SFANRPM, 266 .fs_aux = 0, 267 .fs_reg = 0x22, 268 .fs_refresh = finsio_refresh_fanrpm, 269 .fs_rfact = 0 270 }, 271 { 272 .fs_desc = "Fan3", 273 .fs_type = ENVSYS_SFANRPM, 274 .fs_aux = 0, 275 .fs_reg = 0x24, 276 .fs_refresh = finsio_refresh_fanrpm, 277 .fs_rfact = 0 278 }, 279 280 { .fs_desc = NULL } 281 }; 282 283 /* Sensors available in F71862/F71882/F71883 */ 284 static struct finsio_sensor f71883_sensors[] = { 285 /* Voltage */ 286 { 287 .fs_desc = "+3.3V", 288 .fs_type = ENVSYS_SVOLTS_DC, 289 .fs_aux = 0, 290 .fs_reg = 0x20, 291 .fs_refresh = finsio_refresh_volt, 292 .fs_rfact = FRFACT(100, 100) 293 }, 294 { 295 .fs_desc = "Vcore", 296 .fs_type = ENVSYS_SVOLTS_DC, 297 .fs_aux = 0, 298 .fs_reg = 0x21, 299 .fs_refresh = finsio_refresh_volt, 300 .fs_rfact = FRFACT_NONE 301 }, 302 { 303 .fs_desc = "VIN2", 304 .fs_type = ENVSYS_SVOLTS_DC, 305 .fs_aux = 0, 306 .fs_reg = 0x22, 307 .fs_refresh = finsio_refresh_volt, 308 .fs_rfact = FRFACT(100, 100) 309 }, 310 { 311 .fs_desc = "VIN3", 312 .fs_type = ENVSYS_SVOLTS_DC, 313 .fs_aux = 0, 314 .fs_reg = 0x23, 315 .fs_refresh = finsio_refresh_volt, 316 .fs_rfact = FRFACT(47, 100) 317 }, 318 { 319 .fs_desc = "VIN4", 320 .fs_type = ENVSYS_SVOLTS_DC, 321 .fs_aux = 0, 322 .fs_reg = 0x24, 323 .fs_refresh = finsio_refresh_volt, 324 .fs_rfact = FRFACT(200, 47) 325 }, 326 { 327 .fs_desc = "VIN5", 328 .fs_type = ENVSYS_SVOLTS_DC, 329 .fs_aux = 0, 330 .fs_reg = 0x25, 331 .fs_refresh = finsio_refresh_volt, 332 .fs_rfact = FRFACT(200, 20) 333 }, 334 { 335 .fs_desc = "VIN6", 336 .fs_type = ENVSYS_SVOLTS_DC, 337 .fs_aux = 0, 338 .fs_reg = 0x26, 339 .fs_refresh = finsio_refresh_volt, 340 .fs_rfact = FRFACT(100, 100) 341 }, 342 { 343 .fs_desc = "VSB +3.3V", 344 .fs_type = ENVSYS_SVOLTS_DC, 345 .fs_aux = 0, 346 .fs_reg = 0x27, 347 .fs_refresh = finsio_refresh_volt, 348 .fs_rfact = FRFACT(200, 47) 349 }, 350 { 351 .fs_desc = "VBAT", 352 .fs_type = ENVSYS_SVOLTS_DC, 353 .fs_aux = 0, 354 .fs_reg = 0x28, 355 .fs_refresh = finsio_refresh_volt, 356 .fs_rfact = FRFACT(200, 47) 357 }, 358 /* Temperature */ 359 { 360 .fs_desc = "Temp1", 361 .fs_type = ENVSYS_STEMP, 362 .fs_aux = 0x1, 363 .fs_reg = 0x72, 364 .fs_refresh = finsio_refresh_temp, 365 .fs_rfact = 0 366 }, 367 { 368 .fs_desc = "Temp2", 369 .fs_type = ENVSYS_STEMP, 370 .fs_aux = 0x2, 371 .fs_reg = 0x74, 372 .fs_refresh = finsio_refresh_temp, 373 .fs_rfact = 0 374 }, 375 { 376 .fs_desc = "Temp3", 377 .fs_type = ENVSYS_STEMP, 378 .fs_aux = 0x4, 379 .fs_reg = 0x76, 380 .fs_refresh = finsio_refresh_temp, 381 .fs_rfact = 0 382 }, 383 /* Fan */ 384 { 385 .fs_desc = "Fan1", 386 .fs_type = ENVSYS_SFANRPM, 387 .fs_aux = 0, 388 .fs_reg = 0xa0, 389 .fs_refresh = finsio_refresh_fanrpm, 390 .fs_rfact = 0 391 }, 392 { 393 .fs_desc = "Fan2", 394 .fs_type = ENVSYS_SFANRPM, 395 .fs_aux = 0, 396 .fs_reg = 0xb0, 397 .fs_refresh = finsio_refresh_fanrpm, 398 .fs_rfact = 0 399 }, 400 { 401 .fs_desc = "Fan3", 402 .fs_type = ENVSYS_SFANRPM, 403 .fs_aux = 0, 404 .fs_reg = 0xc0, 405 .fs_refresh = finsio_refresh_fanrpm, 406 .fs_rfact = 0 407 }, 408 { 409 .fs_desc = "Fan4", 410 .fs_type = ENVSYS_SFANRPM, 411 .fs_aux = 0, 412 .fs_reg = 0xd0, 413 .fs_refresh = finsio_refresh_fanrpm, 414 .fs_rfact = 0 415 }, 416 417 { .fs_desc = NULL } 418 }; 419 420 static int 421 finsio_isa_match(device_t parent, cfdata_t match, void *aux) 422 { 423 struct isa_attach_args *ia = aux; 424 bus_space_handle_t ioh; 425 uint16_t val; 426 427 /* Must supply an address */ 428 if (ia->ia_nio < 1) 429 return 0; 430 431 if (ISA_DIRECT_CONFIG(ia)) 432 return 0; 433 434 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 435 return 0; 436 437 if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) 438 return 0; 439 440 finsio_enter(ia->ia_iot, ioh); 441 /* Find out Manufacturer ID */ 442 val = finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF) << 8; 443 val |= finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF + 1); 444 finsio_exit(ia->ia_iot, ioh); 445 bus_space_unmap(ia->ia_iot, ioh, 2); 446 447 if (val != FINTEK_ID) 448 return 0; 449 450 ia->ia_nio = 1; 451 ia->ia_io[0].ir_size = 2; 452 ia->ia_niomem = 0; 453 ia->ia_nirq = 0; 454 ia->ia_ndrq = 0; 455 456 return 1; 457 } 458 459 static void 460 finsio_isa_attach(device_t parent, device_t self, void *aux) 461 { 462 struct finsio_softc *sc = device_private(self); 463 struct isa_attach_args *ia = aux; 464 bus_space_handle_t ioh; 465 uint16_t hwmon_baddr, chipid, cr; 466 int i, rv = 0; 467 468 aprint_naive("\n"); 469 470 sc->sc_iot = ia->ia_iot; 471 472 /* Map Super I/O configuration space */ 473 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) { 474 aprint_error(": can't map configuration I/O space\n"); 475 return; 476 } 477 478 finsio_enter(sc->sc_iot, ioh); 479 /* Get the Chip ID */ 480 chipid = finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP) << 8; 481 chipid |= finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP + 1); 482 /* 483 * Select the Hardware Monitor LDN to find out the I/O 484 * address space. 485 */ 486 finsio_writereg(sc->sc_iot, ioh, FINSIO_FUNC_SEL, FINSIO_FUNC_HWMON); 487 hwmon_baddr = finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR) << 8; 488 hwmon_baddr |= finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR + 1); 489 finsio_exit(sc->sc_iot, ioh); 490 bus_space_unmap(sc->sc_iot, ioh, 2); 491 492 /* 493 * The address decoder ignores the bottom 3 bits, so do we. 494 */ 495 hwmon_baddr &= ~FINSIO_DECODE_MASK; 496 497 switch (chipid) { 498 case FINSIO_IDF71805: 499 sc->sc_finsio_sensors = f71805_sensors; 500 aprint_normal(": Fintek F71805 Super I/O\n"); 501 break; 502 case FINSIO_IDF71806: 503 sc->sc_finsio_sensors = f71805_sensors; 504 aprint_normal(": Fintek F71806/F71872 Super I/O\n"); 505 break; 506 case FINSIO_IDF71862: 507 sc->sc_finsio_sensors = f71883_sensors; 508 aprint_normal(": Fintek F71862 Super I/O\n"); 509 break; 510 case FINSIO_IDF71883: 511 sc->sc_finsio_sensors = f71883_sensors; 512 aprint_normal(": Fintek F71882/F71883 Super I/O\n"); 513 break; 514 case FINSIO_IDF8000: 515 sc->sc_finsio_sensors = f71883_sensors; 516 aprint_normal(": ASUS F8000 Super I/O\n"); 517 break; 518 default: 519 /* 520 * Unknown Chip ID, assume the same register layout 521 * than F71805 for now. 522 */ 523 sc->sc_finsio_sensors = f71805_sensors; 524 aprint_normal(": Fintek Super I/O (unknown chip ID %x)\n", 525 chipid); 526 break; 527 } 528 529 /* Map Hardware Monitor I/O space */ 530 if (bus_space_map(sc->sc_iot, hwmon_baddr, FINSIO_DECODE_SIZE, 531 0, &sc->sc_ioh)) { 532 aprint_error(": can't map hwmon I/O space\n"); 533 return; 534 } 535 536 /* 537 * Enable Hardware monitoring for fan/temperature and 538 * voltage sensors. 539 */ 540 cr = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF); 541 finsio_writereg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF, cr | 0x3); 542 543 /* Find out the temperature mode */ 544 sc->sc_tempsel = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_TMODE); 545 546 /* 547 * Initialize and attach sensors with sysmon_envsys(9). 548 */ 549 sc->sc_sme = sysmon_envsys_create(); 550 for (i = 0; sc->sc_finsio_sensors[i].fs_desc; i++) { 551 sc->sc_sensor[i].state = ENVSYS_SINVALID; 552 sc->sc_sensor[i].units = sc->sc_finsio_sensors[i].fs_type; 553 if (sc->sc_sensor[i].units == ENVSYS_SVOLTS_DC) 554 sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT; 555 strlcpy(sc->sc_sensor[i].desc, sc->sc_finsio_sensors[i].fs_desc, 556 sizeof(sc->sc_sensor[i].desc)); 557 if (sysmon_envsys_sensor_attach(sc->sc_sme, 558 &sc->sc_sensor[i])) 559 goto fail; 560 } 561 562 sc->sc_sme->sme_name = device_xname(self); 563 sc->sc_sme->sme_cookie = sc; 564 sc->sc_sme->sme_refresh = finsio_refresh; 565 if ((rv = sysmon_envsys_register(sc->sc_sme))) { 566 aprint_error(": unable to register with sysmon (%d)\n", rv); 567 goto fail; 568 } 569 570 aprint_normal_dev(self, 571 "Hardware Monitor registers at 0x%x\n", hwmon_baddr); 572 return; 573 574 fail: 575 sysmon_envsys_destroy(sc->sc_sme); 576 sc->sc_sme = NULL; 577 bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 578 } 579 580 static int 581 finsio_isa_detach(device_t self, int flags) 582 { 583 struct finsio_softc *sc = device_private(self); 584 585 if (sc->sc_sme != NULL) 586 sysmon_envsys_unregister(sc->sc_sme); 587 bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 588 return 0; 589 } 590 591 /* Enter Super I/O configuration mode */ 592 static void 593 finsio_enter(bus_space_tag_t iot, bus_space_handle_t ioh) 594 { 595 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 596 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 597 } 598 599 /* Exit Super I/O configuration mode */ 600 static void 601 finsio_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 602 { 603 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_LOCK); 604 } 605 606 static uint8_t 607 finsio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg) 608 { 609 bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 610 return bus_space_read_1(iot, ioh, FINSIO_DATA); 611 } 612 613 static void 614 finsio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val) 615 { 616 bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 617 bus_space_write_1(iot, ioh, FINSIO_DATA, val); 618 } 619 620 static void 621 finsio_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 622 { 623 struct finsio_softc *sc = sme->sme_cookie; 624 int i = edata->sensor; 625 626 sc->sc_finsio_sensors[i].fs_refresh(sc, edata); 627 } 628 629 static void 630 finsio_refresh_volt(struct finsio_softc *sc, envsys_data_t *edata) 631 { 632 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 633 int data; 634 635 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg); 636 DPRINTF(("%s: data 0x%x\n", __func__, data)); 637 638 if (data == 0xff || data == 0) 639 edata->state = ENVSYS_SINVALID; 640 else { 641 edata->state = ENVSYS_SVALID; 642 if (edata->rfact) 643 edata->value_cur = data * edata->rfact; 644 else 645 edata->value_cur = data * fs->fs_rfact; 646 } 647 } 648 649 /* The BIOS seems to add a fudge factor to the CPU temp of +5C */ 650 static void 651 finsio_refresh_temp(struct finsio_softc *sc, envsys_data_t *edata) 652 { 653 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 654 u_int data; 655 u_int llmax; 656 657 /* 658 * The data sheet says that the range of the temperature 659 * sensor is between 0 and 127 or 140 degrees C depending on 660 * what kind of sensor is used. 661 * A disconnected sensor seems to read over 110 or so. 662 */ 663 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) & 0xFF; 664 DPRINTF(("%s: data 0x%x\n", __func__, data)); 665 666 llmax = (sc->sc_tempsel & fs->fs_aux) ? 111 : 128; 667 if (data == 0 || data >= llmax) /* disconnected? */ 668 edata->state = ENVSYS_SINVALID; 669 else { 670 edata->state = ENVSYS_SVALID; 671 edata->value_cur = data * 1000000 + 273150000; 672 } 673 } 674 675 /* fan speed appears to be a 12-bit number */ 676 static void 677 finsio_refresh_fanrpm(struct finsio_softc *sc, envsys_data_t *edata) 678 { 679 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 680 int data; 681 682 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) << 8; 683 data |= finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg + 1); 684 DPRINTF(("%s: data 0x%x\n", __func__, data)); 685 686 if (data >= 0xfff) 687 edata->state = ENVSYS_SINVALID; 688 else { 689 edata->value_cur = 1500000 / data; 690 edata->state = ENVSYS_SVALID; 691 } 692 } 693 694 MODULE(MODULE_CLASS_DRIVER, finsio, "sysmon_envsys"); 695 696 #ifdef _MODULE 697 #include "ioconf.c" 698 #endif 699 700 static int 701 finsio_modcmd(modcmd_t cmd, void *opaque) 702 { 703 int error = 0; 704 705 switch (cmd) { 706 case MODULE_CMD_INIT: 707 #ifdef _MODULE 708 error = config_init_component(cfdriver_ioconf_finsio, 709 cfattach_ioconf_finsio, cfdata_ioconf_finsio); 710 #endif 711 return error; 712 case MODULE_CMD_FINI: 713 #ifdef _MODULE 714 error = config_fini_component(cfdriver_ioconf_finsio, 715 cfattach_ioconf_finsio, cfdata_ioconf_finsio); 716 #endif 717 return error; 718 default: 719 return ENOTTY; 720 } 721 } 722