1 /* $OpenBSD: fins.c,v 1.1 2008/03/19 19:33:09 deraadt Exp $ */ 2 /* $NetBSD: finsio_isa.c,v 1.8 2015/04/23 23:23:00 pgoyette 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.8 2015/04/23 23:23:00 pgoyette 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 bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 577 } 578 579 static int 580 finsio_isa_detach(device_t self, int flags) 581 { 582 struct finsio_softc *sc = device_private(self); 583 584 sysmon_envsys_unregister(sc->sc_sme); 585 bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 586 return 0; 587 } 588 589 /* Enter Super I/O configuration mode */ 590 static void 591 finsio_enter(bus_space_tag_t iot, bus_space_handle_t ioh) 592 { 593 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 594 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 595 } 596 597 /* Exit Super I/O configuration mode */ 598 static void 599 finsio_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 600 { 601 bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_LOCK); 602 } 603 604 static uint8_t 605 finsio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg) 606 { 607 bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 608 return bus_space_read_1(iot, ioh, FINSIO_DATA); 609 } 610 611 static void 612 finsio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val) 613 { 614 bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 615 bus_space_write_1(iot, ioh, FINSIO_DATA, val); 616 } 617 618 static void 619 finsio_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 620 { 621 struct finsio_softc *sc = sme->sme_cookie; 622 int i = edata->sensor; 623 624 sc->sc_finsio_sensors[i].fs_refresh(sc, edata); 625 } 626 627 static void 628 finsio_refresh_volt(struct finsio_softc *sc, envsys_data_t *edata) 629 { 630 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 631 int data; 632 633 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg); 634 DPRINTF(("%s: data 0x%x\n", __func__, data)); 635 636 if (data == 0xff || data == 0) 637 edata->state = ENVSYS_SINVALID; 638 else { 639 edata->state = ENVSYS_SVALID; 640 if (edata->rfact) 641 edata->value_cur = data * edata->rfact; 642 else 643 edata->value_cur = data * fs->fs_rfact; 644 } 645 } 646 647 /* The BIOS seems to add a fudge factor to the CPU temp of +5C */ 648 static void 649 finsio_refresh_temp(struct finsio_softc *sc, envsys_data_t *edata) 650 { 651 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 652 u_int data; 653 u_int llmax; 654 655 /* 656 * The data sheet says that the range of the temperature 657 * sensor is between 0 and 127 or 140 degrees C depending on 658 * what kind of sensor is used. 659 * A disconnected sensor seems to read over 110 or so. 660 */ 661 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) & 0xFF; 662 DPRINTF(("%s: data 0x%x\n", __func__, data)); 663 664 llmax = (sc->sc_tempsel & fs->fs_aux) ? 111 : 128; 665 if (data == 0 || data >= llmax) /* disconnected? */ 666 edata->state = ENVSYS_SINVALID; 667 else { 668 edata->state = ENVSYS_SVALID; 669 edata->value_cur = data * 1000000 + 273150000; 670 } 671 } 672 673 /* fan speed appears to be a 12-bit number */ 674 static void 675 finsio_refresh_fanrpm(struct finsio_softc *sc, envsys_data_t *edata) 676 { 677 struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 678 int data; 679 680 data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) << 8; 681 data |= finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg + 1); 682 DPRINTF(("%s: data 0x%x\n", __func__, data)); 683 684 if (data >= 0xfff) 685 edata->state = ENVSYS_SINVALID; 686 else { 687 edata->value_cur = 1500000 / data; 688 edata->state = ENVSYS_SVALID; 689 } 690 } 691 692 MODULE(MODULE_CLASS_DRIVER, finsio, "sysmon_envsys"); 693 694 #ifdef _MODULE 695 #include "ioconf.c" 696 #endif 697 698 static int 699 finsio_modcmd(modcmd_t cmd, void *opaque) 700 { 701 int error = 0; 702 703 switch (cmd) { 704 case MODULE_CMD_INIT: 705 #ifdef _MODULE 706 error = config_init_component(cfdriver_ioconf_finsio, 707 cfattach_ioconf_finsio, cfdata_ioconf_finsio); 708 #endif 709 return error; 710 case MODULE_CMD_FINI: 711 #ifdef _MODULE 712 error = config_fini_component(cfdriver_ioconf_finsio, 713 cfattach_ioconf_finsio, cfdata_ioconf_finsio); 714 #endif 715 return error; 716 default: 717 return ENOTTY; 718 } 719 } 720