1 /* $NetBSD: adm1021.c,v 1.27 2021/01/30 01:22:06 thorpej Exp $ */ 2 /* $OpenBSD: adm1021.c,v 1.27 2007/06/24 05:34:35 dlg Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Theo de Raadt 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * Driver for ADM1021 and compatible temperature sensors, including ADM1021, 22 * ADM1021A, ADM1023, ADM1032, GL523SM, G781, LM84, MAX1617, MAX1617A, 23 * NE1617A, MAX6642 and Xeon embedded temperature sensors. 24 * 25 * Some sensors differ from the ADM1021/MAX1617/NE1617A: 26 * ADM1021A ADM1023 ADM1032 G781 LM84 MAX1617A MAX6642 27 * company/revision reg X X X X X X 28 * no negative temps X X X X 29 * 11-bit remote temp X X X X 30 * no low limits X X 31 * therm (high) limits X X X 32 * 33 * Registers 0x00 to 0x0f have separate read/write addresses, but 34 * registers 0x10 and above have the same read/write address. 35 * The 11-bit (extended) temperature consists of a separate register with 36 * 3 valid bits that are always added to the external temperature (even if 37 * the temperature is negative). 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: adm1021.c,v 1.27 2021/01/30 01:22:06 thorpej Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 #include <dev/sysmon/sysmonvar.h> 47 48 #include <dev/i2c/i2cvar.h> 49 50 /* Registers */ 51 #define ADM1021_INT_TEMP 0x00 /* Internal temperature value */ 52 #define ADM1021_EXT_TEMP 0x01 /* External temperature value */ 53 #define ADM1021_STATUS 0x02 /* Status */ 54 #define ADM1021_CONFIG_READ 0x03 /* Read configuration */ 55 #define ADM1021_CONV_RATE_READ 0x04 /* Read conversion rate */ 56 #define ADM1021_INT_HIGH_READ 0x05 /* Read internal high limit */ 57 #define ADM1021_INT_LOW_READ 0x06 /* Read internal low limit */ 58 #define ADM1021_EXT_HIGH_READ 0x07 /* Read external high limit */ 59 #define ADM1021_EXT_LOW_READ 0x08 /* Read external low limit */ 60 #define ADM1021_CONFIG_WRITE 0x09 /* Write configuration */ 61 #define ADM1021_CONV_RATE_WRITE 0x0a /* Write conversion rate */ 62 #define ADM1021_INT_HIGH_WRITE 0x0b /* Write internal high limit */ 63 #define ADM1021_INT_LOW_WRITE 0x0c /* Write internal low limit */ 64 #define ADM1021_EXT_HIGH_WRITE 0x0d /* Write external high limit */ 65 #define ADM1021_EXT_LOW_WRITE 0x0e /* Write external low limit */ 66 #define ADM1021_ONE_SHOT 0x0f /* One shot command */ 67 #define ADM1023_EXT_TEMP2 0x10 /* R/W external temp low byte */ 68 #define ADM1023_EXT_TEMP_OFF 0x11 /* R/W external temp offset */ 69 #define ADM1023_EXT_TEMP_OFF2 0x12 /* R/W external temp off low byte */ 70 #define ADM1023_EXT_HIGH2 0x13 /* R/W external high lim low byte */ 71 #define ADM1023_EXT_LOW2 0x14 /* R/W external low lim low byte */ 72 #define ADM1032_EXT_THERM 0x19 /* R/W external Therm (high) limit */ 73 #define ADM1032_INT_THERM 0x20 /* R/W internal Therm (high) limit */ 74 #define ADM1032_THERM_HYST 0x21 /* R/W Therm hysteris */ 75 #define ADM1032_ALERT_QUEUE 0x22 /* R/W consecutive alert queue */ 76 #define ADM1021_COMPANY 0xfe /* Company ID */ 77 #define ADM1021_DIE_REVISION 0xff /* Die revision code */ 78 79 /* Register values */ 80 #define ADM1021_CONFIG_RUN 0x40 81 82 #define ADM1021_STATUS_INVAL 0x7f 83 #define ADM1021_STATUS_NOEXT 0x40 /* External diode is open-circuit */ 84 85 #define ADM1023_EXT2_SHIFT 5 86 #define ADM1023_EXT2_MASK 0x07 87 88 #define ADM1021_COMPANY_ADM 0x41 /* 'A' */ 89 #define ADM1021_COMPANY_GMT 0x47 /* 'G' */ 90 #define ADM1021_COMPANY_MAXIM 0x4d /* 'M' */ 91 92 #define ADM1021_REV_1021 0x00 93 #define ADM1021_REV_1021A 0x30 94 #define ADM1021_REV_MASK 0xf0 95 96 /* Sensors */ 97 #define ADMTEMP_INT 0 98 #define ADMTEMP_EXT 1 99 #define ADMTEMP_NUM_SENSORS 2 100 101 #define ADMTEMP_MAX_NEG -65 102 #define ADMTEMP_MAX_POS 127 103 #define ADMTEMP_LOW_DEFAULT 0xc9 /* (-55) */ 104 105 /* Limit registers might read 0xff, so we ignore them if they do */ 106 #define ADMTEMP_LIM_INVAL -1 /* 0xff */ 107 108 #define ADMTEMP_NAMELEN 9 /* Maximum name length + 1 */ 109 110 struct admtemp_softc { 111 i2c_tag_t sc_tag; 112 i2c_addr_t sc_addr; 113 prop_dictionary_t sc_prop; 114 115 int sc_flags; 116 int sc_noexternal, sc_noneg, sc_nolow; 117 int sc_ext11, sc_therm; 118 struct sysmon_envsys *sc_sme; 119 envsys_data_t sc_sensor[ADMTEMP_NUM_SENSORS]; 120 int sc_setdef[ADMTEMP_NUM_SENSORS]; 121 uint8_t sc_highlim[ADMTEMP_NUM_SENSORS]; 122 uint8_t sc_lowlim[ADMTEMP_NUM_SENSORS]; 123 uint8_t sc_highlim2, sc_lowlim2; 124 uint8_t sc_thermlim[ADMTEMP_NUM_SENSORS]; 125 }; 126 127 int admtemp_match(device_t, cfdata_t, void *); 128 void admtemp_attach(device_t, device_t, void *); 129 void admtemp_refresh(struct sysmon_envsys *, envsys_data_t *); 130 void admtemp_getlim_1021(struct sysmon_envsys *, envsys_data_t *, 131 sysmon_envsys_lim_t *, uint32_t *); 132 void admtemp_getlim_1023(struct sysmon_envsys *, envsys_data_t *, 133 sysmon_envsys_lim_t *, uint32_t *); 134 void admtemp_getlim_1032(struct sysmon_envsys *, envsys_data_t *, 135 sysmon_envsys_lim_t *, uint32_t *); 136 void admtemp_setlim_1021(struct sysmon_envsys *, envsys_data_t *, 137 sysmon_envsys_lim_t *, uint32_t *); 138 void admtemp_setlim_1023(struct sysmon_envsys *, envsys_data_t *, 139 sysmon_envsys_lim_t *, uint32_t *); 140 void admtemp_setlim_1032(struct sysmon_envsys *, envsys_data_t *, 141 sysmon_envsys_lim_t *, uint32_t *); 142 143 CFATTACH_DECL_NEW(admtemp, sizeof(struct admtemp_softc), 144 admtemp_match, admtemp_attach, NULL, NULL); 145 146 struct admtemp_params { 147 const char *name; 148 int noneg; 149 int nolow; 150 int ext11; 151 int therm; 152 }; 153 154 static const struct admtemp_params admtemp_params_max1617 = { 155 .name = "MAX1617A", 156 .noneg = 0, 157 .nolow = 0, 158 .ext11 = 0, 159 .therm = 0, 160 }; 161 162 static const struct admtemp_params admtemp_params_max6642 = { 163 .name = "MAX6642", 164 .noneg = 0, 165 .nolow = 1, 166 .ext11 = 0, 167 .therm = 0, 168 }; 169 170 static const struct admtemp_params admtemp_params_max6690 = { 171 .name = "MAX6690", 172 .noneg = 0, 173 .nolow = 0, 174 .ext11 = 1, 175 .therm = 0, 176 }; 177 178 static const struct device_compatible_entry compat_data[] = { 179 { .compat = "i2c-max1617", .data = &admtemp_params_max1617 }, 180 { .compat = "max6642", .data = &admtemp_params_max6642 }, 181 { .compat = "max6690", .data = &admtemp_params_max6690 }, 182 DEVICE_COMPAT_EOL 183 }; 184 185 int 186 admtemp_match(device_t parent, cfdata_t match, void *aux) 187 { 188 struct i2c_attach_args *ia = aux; 189 int match_result; 190 191 if (iic_use_direct_match(ia, match, compat_data, &match_result)) 192 return match_result; 193 194 /* 195 * Indirect config - not much we can do! 196 * Check typical addresses. 197 */ 198 if (((ia->ia_addr >= 0x18) && (ia->ia_addr <= 0x1a)) || 199 ((ia->ia_addr >= 0x29) && (ia->ia_addr <= 0x2b)) || 200 ((ia->ia_addr >= 0x48) && (ia->ia_addr <= 0x4e))) 201 return I2C_MATCH_ADDRESS_ONLY; 202 203 return 0; 204 } 205 206 static int 207 admtemp_exec(struct admtemp_softc *sc, i2c_op_t op, uint8_t *cmd, 208 uint8_t *data) 209 { 210 return iic_exec(sc->sc_tag, op, sc->sc_addr, cmd, sizeof(*cmd), data, 211 sizeof(*data), 0); 212 } 213 214 /* 215 * Set flags based on chip type for direct config, or by testing for 216 * indirect config. 217 * 218 * LM84, MAX1617, and NE1617A don't have company/revision registers. 219 * If we can't read the company register, we'll check the 220 * internal low limit to see if we have an LM84. 221 * 222 * To check if an ADM chip has 11-bit sensors, we'll write 0.125 223 * to the external temperature limit low byte register and read it 224 * back (because we can't tell from the id/rev). 225 * 226 * To check if an ADM chip has a Therm output, we check that we 227 * read 0x55 (default value) from the external therm limit. 228 * 229 * If an ADM chip doesn't have 11-bit sensors, check the revision to 230 * determine if it handles negative temperatures. 231 */ 232 static void 233 admtemp_setflags(struct admtemp_softc *sc, struct i2c_attach_args *ia, 234 uint8_t* comp, uint8_t *rev, char* name) 235 { 236 uint8_t cmd, data, tmp; 237 238 *comp = 0; 239 *rev = 0; 240 241 cmd = ADM1021_COMPANY; 242 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, comp); 243 244 cmd = ADM1021_DIE_REVISION; 245 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, rev); 246 247 sc->sc_noneg = 1; 248 sc->sc_nolow = 0; 249 sc->sc_ext11 = 0; 250 sc->sc_therm = 0; 251 252 /* Direct config */ 253 const struct device_compatible_entry *dce = 254 iic_compatible_lookup(ia, compat_data); 255 if (dce != NULL) { 256 const struct admtemp_params *params = dce->data; 257 258 sc->sc_noneg = params->noneg; 259 sc->sc_nolow = params->nolow; 260 sc->sc_ext11 = params->ext11; 261 sc->sc_therm = params->therm; 262 strlcpy(name, params->name, ADMTEMP_NAMELEN); 263 return; 264 } 265 266 /* Indirect config */ 267 if (*comp == 0) { 268 sc->sc_noneg = 0; 269 cmd = ADM1021_INT_LOW_READ; 270 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, comp) == 0 && 271 *comp != ADMTEMP_LOW_DEFAULT) { 272 sc->sc_nolow = 1; 273 strlcpy(name, "LM84", ADMTEMP_NAMELEN); 274 } else 275 strlcpy(name, "MAX1617", ADMTEMP_NAMELEN); 276 } 277 278 if (*comp == ADM1021_COMPANY_MAXIM) { 279 sc->sc_noneg = 0; 280 /* 281 * MAX6642 doesn't have a revision register 282 * XXX this works only on macppc with iic at pmu because the 283 * pmu doesn't return an error for nonexistant registers, it 284 * just repeats previous data 285 */ 286 if (*comp == *rev) { 287 sc->sc_therm = 0; /* */ 288 sc->sc_nolow = 1; 289 strlcpy(name, "MAX6642", ADMTEMP_NAMELEN); 290 } else if (*rev == 0) { 291 strlcpy(name, "MAX6690", ADMTEMP_NAMELEN); 292 sc->sc_ext11 = 1; 293 } else { 294 strlcpy(name, "MAX1617A", ADMTEMP_NAMELEN); 295 } 296 } 297 298 if (*comp == ADM1021_COMPANY_GMT) { 299 sc->sc_ext11 = 1; 300 sc->sc_therm = 1; 301 strlcpy(name, "G781", ADMTEMP_NAMELEN); 302 } 303 304 if (*comp == ADM1021_COMPANY_ADM) { 305 cmd = ADM1023_EXT_HIGH2; 306 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0) { 307 tmp = 1 << ADM1023_EXT2_SHIFT; 308 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &tmp); 309 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, 310 &tmp) == 0 && tmp == 1 << ADM1023_EXT2_SHIFT) { 311 sc->sc_ext11 = 1; 312 strlcpy(name, "ADM1023", ADMTEMP_NAMELEN); 313 } 314 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data); 315 } 316 cmd = ADM1032_EXT_THERM; 317 if (sc->sc_ext11 && 318 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0 319 && data == 0x55) { 320 sc->sc_therm = 1; 321 strlcpy(name, "ADM1032", ADMTEMP_NAMELEN); 322 } 323 if (!sc->sc_ext11 && 324 (*rev & ADM1021_REV_MASK) == ADM1021_REV_1021A) { 325 sc->sc_noneg = 0; 326 strlcpy(name, "ADM1021A", ADMTEMP_NAMELEN); 327 } else 328 strlcpy(name, "ADM1021", ADMTEMP_NAMELEN); 329 } 330 } 331 332 void 333 admtemp_attach(device_t parent, device_t self, void *aux) 334 { 335 struct admtemp_softc *sc = device_private(self); 336 struct i2c_attach_args *ia = aux; 337 uint8_t cmd, data, stat, comp, rev; 338 char name[ADMTEMP_NAMELEN]; 339 char ename[64] = "external", iname[64] = "internal"; 340 const char *desc; 341 342 sc->sc_tag = ia->ia_tag; 343 sc->sc_addr = ia->ia_addr; 344 sc->sc_prop = ia->ia_prop; 345 prop_object_retain(sc->sc_prop); 346 347 iic_acquire_bus(sc->sc_tag, 0); 348 cmd = ADM1021_CONFIG_READ; 349 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) != 0) { 350 iic_release_bus(sc->sc_tag, 0); 351 aprint_error_dev(self, "cannot get control register\n"); 352 return; 353 } 354 if (data & ADM1021_CONFIG_RUN) { 355 cmd = ADM1021_STATUS; 356 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &stat)) { 357 iic_release_bus(sc->sc_tag, 0); 358 aprint_error_dev(self, 359 "cannot read status register\n"); 360 return; 361 } 362 if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) { 363 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, 364 &stat)) { 365 iic_release_bus(sc->sc_tag, 0); 366 aprint_error_dev(self, 367 "cannot read status register\n"); 368 return; 369 } 370 } 371 372 /* means external is dead */ 373 if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL && 374 (stat & ADM1021_STATUS_NOEXT)) 375 sc->sc_noexternal = 1; 376 377 data &= ~ADM1021_CONFIG_RUN; 378 cmd = ADM1021_CONFIG_WRITE; 379 if (admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data)) { 380 iic_release_bus(sc->sc_tag, 0); 381 aprint_error_dev(self, 382 "cannot set control register\n"); 383 return; 384 } 385 } 386 387 admtemp_setflags(sc, ia, &comp, &rev, name); 388 389 iic_release_bus(sc->sc_tag, 0); 390 391 aprint_normal(": %s temperature sensor", name); 392 if (comp) 393 aprint_normal(": id. 0x%02x, rev. 0x%02x\n", comp, rev); 394 else 395 aprint_normal("\n"); 396 aprint_naive(": Temperature sensor\n"); 397 398 /* Initialize sensor data. */ 399 sc->sc_sensor[ADMTEMP_INT].state = ENVSYS_SINVALID; 400 sc->sc_sensor[ADMTEMP_INT].units = ENVSYS_STEMP; 401 sc->sc_sensor[ADMTEMP_EXT].state = ENVSYS_SINVALID; 402 sc->sc_sensor[ADMTEMP_EXT].units = ENVSYS_STEMP; 403 sc->sc_sensor[ADMTEMP_INT].flags = 404 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 405 sc->sc_sensor[ADMTEMP_EXT].flags = 406 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 407 408 if (prop_dictionary_get_cstring_nocopy(sc->sc_prop, "s00", &desc)) { 409 strncpy(iname, desc, 64); 410 } 411 412 if (prop_dictionary_get_cstring_nocopy(sc->sc_prop, "s01", &desc)) { 413 strncpy(ename, desc, 64); 414 } 415 416 strlcpy(sc->sc_sensor[ADMTEMP_INT].desc, iname, 417 sizeof(sc->sc_sensor[ADMTEMP_INT].desc)); 418 strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc, ename, 419 sizeof(sc->sc_sensor[ADMTEMP_EXT].desc)); 420 421 sc->sc_sme = sysmon_envsys_create(); 422 if (sysmon_envsys_sensor_attach( 423 sc->sc_sme, &sc->sc_sensor[ADMTEMP_INT])) { 424 sysmon_envsys_destroy(sc->sc_sme); 425 sc->sc_sme = NULL; 426 aprint_error_dev(self, 427 "unable to attach internal at sysmon\n"); 428 return; 429 } 430 if (sc->sc_noexternal == 0 && 431 sysmon_envsys_sensor_attach( 432 sc->sc_sme, &sc->sc_sensor[ADMTEMP_EXT])) { 433 sysmon_envsys_destroy(sc->sc_sme); 434 sc->sc_sme = NULL; 435 aprint_error_dev(self, 436 "unable to attach external at sysmon\n"); 437 return; 438 } 439 sc->sc_sme->sme_name = device_xname(self); 440 sc->sc_sme->sme_cookie = sc; 441 sc->sc_sme->sme_refresh = admtemp_refresh; 442 if (sc->sc_therm) { 443 sc->sc_sme->sme_get_limits = admtemp_getlim_1032; 444 sc->sc_sme->sme_set_limits = admtemp_setlim_1032; 445 } else if (sc->sc_ext11) { 446 sc->sc_sme->sme_get_limits = admtemp_getlim_1023; 447 sc->sc_sme->sme_set_limits = admtemp_setlim_1023; 448 } else { 449 sc->sc_sme->sme_get_limits = admtemp_getlim_1021; 450 sc->sc_sme->sme_set_limits = admtemp_setlim_1021; 451 } 452 if (sysmon_envsys_register(sc->sc_sme)) { 453 aprint_error_dev(self, 454 "unable to register with sysmon\n"); 455 sysmon_envsys_destroy(sc->sc_sme); 456 sc->sc_sme = NULL; 457 return; 458 } 459 } 460 461 462 void 463 admtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 464 { 465 struct admtemp_softc *sc = sme->sme_cookie; 466 uint8_t cmd, xdata; 467 int8_t sdata; 468 469 if (iic_acquire_bus(sc->sc_tag, 0)) { 470 edata->state = ENVSYS_SINVALID; 471 return; 472 } 473 474 if (edata->sensor == ADMTEMP_INT) 475 cmd = ADM1021_INT_TEMP; 476 else 477 cmd = ADM1021_EXT_TEMP; 478 479 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &sdata) == 0) { 480 if (sdata == ADM1021_STATUS_INVAL) { 481 edata->state = ENVSYS_SINVALID; 482 } else { 483 edata->value_cur = 273150000 + 1000000 * sdata; 484 edata->state = ENVSYS_SVALID; 485 } 486 } 487 if (edata->sensor == ADMTEMP_EXT && sc->sc_ext11) { 488 cmd = ADM1023_EXT_TEMP2; 489 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xdata); 490 edata->value_cur += 491 (xdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) * 125000; 492 } 493 494 iic_release_bus(sc->sc_tag, 0); 495 } 496 497 void 498 admtemp_getlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata, 499 sysmon_envsys_lim_t *limits, uint32_t *props) 500 { 501 struct admtemp_softc *sc = sme->sme_cookie; 502 uint8_t cmd; 503 int8_t hdata = 0x7f, ldata = 0xc9; 504 505 *props &= ~(PROP_CRITMAX | PROP_CRITMIN); 506 507 if (iic_acquire_bus(sc->sc_tag, 0)) 508 return; 509 510 if (edata->sensor == ADMTEMP_INT) 511 cmd = ADM1021_INT_HIGH_READ; 512 else 513 cmd = ADM1021_EXT_HIGH_READ; 514 515 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 516 hdata != ADMTEMP_LIM_INVAL) { 517 limits->sel_critmax = 273150000 + 1000000 * hdata; 518 *props |= PROP_CRITMAX; 519 } 520 521 if (sc->sc_nolow == 1) { 522 goto release; 523 } 524 525 if (edata->sensor == ADMTEMP_INT) 526 cmd = ADM1021_INT_LOW_READ; 527 else 528 cmd = ADM1021_EXT_LOW_READ; 529 530 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 531 ldata != ADMTEMP_LIM_INVAL) { 532 limits->sel_critmin = 273150000 + 1000000 * ldata; 533 *props |= PROP_CRITMIN; 534 } 535 536 release: 537 iic_release_bus(sc->sc_tag, 0); 538 539 /* Save the values if this is the first time through. */ 540 if (sc->sc_setdef[edata->sensor] == 0) { 541 sc->sc_setdef[edata->sensor] = 1; 542 sc->sc_highlim[edata->sensor] = hdata; 543 sc->sc_lowlim[edata->sensor] = ldata; 544 } 545 } 546 547 void 548 admtemp_getlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata, 549 sysmon_envsys_lim_t *limits, uint32_t *props) 550 { 551 struct admtemp_softc *sc = sme->sme_cookie; 552 uint8_t cmd, xhdata = 0, xldata = 0; 553 int8_t hdata = 0x7f, ldata = 0xc9; 554 555 *props &= ~(PROP_CRITMAX | PROP_CRITMIN); 556 557 if (iic_acquire_bus(sc->sc_tag, 0)) 558 return; 559 560 if (edata->sensor == ADMTEMP_INT) 561 cmd = ADM1021_INT_HIGH_READ; 562 else 563 cmd = ADM1021_EXT_HIGH_READ; 564 565 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 566 hdata != ADMTEMP_LIM_INVAL) { 567 limits->sel_critmax = 273150000 + 1000000 * hdata; 568 *props |= PROP_CRITMAX; 569 } 570 571 if (edata->sensor == ADMTEMP_EXT) { 572 cmd = ADM1023_EXT_HIGH2; 573 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0) 574 limits->sel_critmax += 575 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 576 * 125000; 577 } 578 579 if (edata->sensor == ADMTEMP_INT) 580 cmd = ADM1021_INT_LOW_READ; 581 else 582 cmd = ADM1021_EXT_LOW_READ; 583 584 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 585 ldata != ADMTEMP_LIM_INVAL) { 586 limits->sel_critmin = 273150000 + 1000000 * ldata; 587 *props |= PROP_CRITMIN; 588 } 589 590 if (edata->sensor == ADMTEMP_EXT) { 591 cmd = ADM1023_EXT_LOW2; 592 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0) 593 limits->sel_critmin += 594 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 595 * 125000; 596 } 597 598 iic_release_bus(sc->sc_tag, 0); 599 600 /* Save the values if this is the first time through. */ 601 if (sc->sc_setdef[edata->sensor] == 0) { 602 sc->sc_setdef[edata->sensor] = 1; 603 sc->sc_highlim[edata->sensor] = hdata; 604 sc->sc_lowlim[edata->sensor] = ldata; 605 if (edata->sensor == ADMTEMP_EXT) { 606 sc->sc_highlim2 = xhdata; 607 sc->sc_lowlim2 = xldata; 608 } 609 } 610 } 611 612 void 613 admtemp_getlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata, 614 sysmon_envsys_lim_t *limits, uint32_t *props) 615 { 616 struct admtemp_softc *sc = sme->sme_cookie; 617 uint8_t cmd, xhdata = 0, xldata = 0; 618 int8_t tdata = 0x55, hdata = 0x55, ldata = 0; 619 620 *props &= ~(PROP_WARNMAX | PROP_CRITMAX | PROP_WARNMIN); 621 622 if (iic_acquire_bus(sc->sc_tag, 0)) 623 return; 624 625 if (edata->sensor == ADMTEMP_INT) 626 cmd = ADM1032_INT_THERM; 627 else 628 cmd = ADM1032_EXT_THERM; 629 630 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &tdata) == 0 && 631 tdata != ADMTEMP_LIM_INVAL) { 632 limits->sel_critmax = 273150000 + 1000000 * tdata; 633 *props |= PROP_CRITMAX; 634 } 635 636 if (edata->sensor == ADMTEMP_INT) 637 cmd = ADM1021_INT_HIGH_READ; 638 else 639 cmd = ADM1021_EXT_HIGH_READ; 640 641 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 642 hdata != ADMTEMP_LIM_INVAL) { 643 limits->sel_warnmax = 273150000 + 1000000 * hdata; 644 *props |= PROP_WARNMAX; 645 } 646 647 if (edata->sensor == ADMTEMP_EXT) { 648 cmd = ADM1023_EXT_HIGH2; 649 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0) 650 limits->sel_warnmax += 651 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 652 * 125000; 653 } 654 655 if (edata->sensor == ADMTEMP_INT) 656 cmd = ADM1021_INT_LOW_READ; 657 else 658 cmd = ADM1021_EXT_LOW_READ; 659 660 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 661 ldata != ADMTEMP_LIM_INVAL) { 662 limits->sel_warnmin = 273150000 + 1000000 * ldata; 663 *props |= PROP_WARNMIN; 664 } 665 666 if (edata->sensor == ADMTEMP_EXT) { 667 cmd = ADM1023_EXT_LOW2; 668 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0) 669 limits->sel_warnmin += 670 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 671 * 125000; 672 } 673 674 iic_release_bus(sc->sc_tag, 0); 675 676 /* Save the values if this is the first time through. */ 677 if (sc->sc_setdef[edata->sensor] == 0) { 678 sc->sc_setdef[edata->sensor] = 1; 679 sc->sc_thermlim[edata->sensor] = tdata; 680 sc->sc_highlim[edata->sensor] = hdata; 681 sc->sc_lowlim[edata->sensor] = ldata; 682 if (edata->sensor == ADMTEMP_EXT) { 683 sc->sc_highlim2 = xhdata; 684 sc->sc_lowlim2 = xldata; 685 } 686 } 687 } 688 689 void 690 admtemp_setlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata, 691 sysmon_envsys_lim_t *limits, uint32_t *props) 692 { 693 struct admtemp_softc *sc = sme->sme_cookie; 694 uint8_t cmd; 695 int tmp; 696 int8_t sdata; 697 698 if (iic_acquire_bus(sc->sc_tag, 0)) 699 return; 700 701 if (*props & PROP_CRITMAX) { 702 if (edata->sensor == ADMTEMP_INT) 703 cmd = ADM1021_INT_HIGH_WRITE; 704 else 705 cmd = ADM1021_EXT_HIGH_WRITE; 706 707 if (limits == NULL) /* Restore defaults */ 708 sdata = sc->sc_highlim[edata->sensor]; 709 else { 710 tmp = (limits->sel_critmax - 273150000) / 1000000; 711 if (tmp > ADMTEMP_MAX_POS) 712 sdata = ADMTEMP_MAX_POS; 713 else if (tmp < 0 && sc->sc_noneg) 714 sdata = 0; 715 else if (tmp < ADMTEMP_MAX_NEG) 716 sdata = ADMTEMP_MAX_NEG; 717 else 718 sdata = tmp & 0xff; 719 } 720 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 721 } 722 723 if (*props & PROP_CRITMIN && sc->sc_nolow == 0) { 724 if (edata->sensor == ADMTEMP_INT) 725 cmd = ADM1021_INT_LOW_WRITE; 726 else 727 cmd = ADM1021_EXT_LOW_WRITE; 728 if (limits == NULL) 729 sdata = sc->sc_lowlim[edata->sensor]; 730 else { 731 tmp = (limits->sel_critmin - 273150000) / 1000000; 732 if (tmp > ADMTEMP_MAX_POS) 733 sdata = ADMTEMP_MAX_POS; 734 else if (tmp < 0 && sc->sc_noneg) 735 sdata = 0; 736 else if (tmp < ADMTEMP_MAX_NEG) 737 sdata = ADMTEMP_MAX_NEG; 738 else 739 sdata = tmp & 0xff; 740 } 741 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 742 } 743 744 iic_release_bus(sc->sc_tag, 0); 745 } 746 747 static void 748 admtemp_encode_temp(const uint32_t val, int8_t *sdata, uint8_t *xdata, 749 const int ext11) 750 { 751 int32_t tmp; 752 753 if (ext11) { 754 /* Split temperature into high and low bytes */ 755 tmp = (val - 273150000) / 125000; 756 *xdata = (tmp & ADM1023_EXT2_MASK) << ADM1023_EXT2_SHIFT; 757 tmp -= (int32_t) (*xdata >> ADM1023_EXT2_SHIFT); 758 tmp /= 8; /* 1000000 / 125000 */ 759 } else { 760 *xdata = 0; 761 tmp = (val - 273150000) / 1000000; 762 } 763 if (tmp > ADMTEMP_MAX_POS) 764 *sdata = ADMTEMP_MAX_POS; 765 else if (tmp < 0) 766 *sdata = 0; 767 else 768 *sdata = tmp & 0xff; 769 } 770 771 void 772 admtemp_setlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata, 773 sysmon_envsys_lim_t *limits, uint32_t *props) 774 { 775 struct admtemp_softc *sc = sme->sme_cookie; 776 int ext11; 777 uint8_t cmd, xdata; 778 int8_t sdata; 779 780 if (edata->sensor == ADMTEMP_INT) 781 ext11 = 0; 782 else 783 ext11 = 1; 784 785 if (iic_acquire_bus(sc->sc_tag, 0)) 786 return; 787 788 if (*props & PROP_CRITMAX) { 789 if (edata->sensor == ADMTEMP_INT) 790 cmd = ADM1021_INT_HIGH_WRITE; 791 else 792 cmd = ADM1021_EXT_HIGH_WRITE; 793 794 if (limits == NULL) { /* Restore defaults */ 795 sdata = sc->sc_highlim[edata->sensor]; 796 xdata = sc->sc_highlim2; 797 } else 798 admtemp_encode_temp(limits->sel_critmax, &sdata, 799 &xdata, ext11); 800 801 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 802 if (ext11) { 803 cmd = ADM1023_EXT_HIGH2; 804 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 805 } 806 } 807 808 if (*props & PROP_CRITMIN) { 809 if (edata->sensor == ADMTEMP_INT) 810 cmd = ADM1021_INT_LOW_WRITE; 811 else 812 cmd = ADM1021_EXT_LOW_WRITE; 813 if (limits == NULL) { 814 sdata = sc->sc_lowlim[edata->sensor]; 815 xdata = sc->sc_lowlim2; 816 } else 817 admtemp_encode_temp(limits->sel_critmax, &sdata, 818 &xdata, ext11); 819 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 820 if (ext11) { 821 cmd = ADM1023_EXT_LOW2; 822 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 823 } 824 } 825 826 iic_release_bus(sc->sc_tag, 0); 827 } 828 829 void 830 admtemp_setlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata, 831 sysmon_envsys_lim_t *limits, uint32_t *props) 832 { 833 struct admtemp_softc *sc = sme->sme_cookie; 834 int ext11; 835 uint8_t cmd, xdata; 836 int8_t sdata; 837 838 if (edata->sensor == ADMTEMP_INT) 839 ext11 = 0; 840 else 841 ext11 = 1; 842 843 if (iic_acquire_bus(sc->sc_tag, 0)) 844 return; 845 846 if (*props & PROP_CRITMAX) { 847 if (edata->sensor == ADMTEMP_INT) 848 cmd = ADM1032_INT_THERM; 849 else 850 cmd = ADM1032_EXT_THERM; 851 if (limits == NULL) /* Restore default */ 852 sdata = sc->sc_thermlim[edata->sensor]; 853 else 854 admtemp_encode_temp(limits->sel_critmax, &sdata, 855 &xdata, 0); 856 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 857 } 858 859 if (*props & PROP_WARNMAX) { 860 if (edata->sensor == ADMTEMP_INT) 861 cmd = ADM1021_INT_HIGH_WRITE; 862 else 863 cmd = ADM1021_EXT_HIGH_WRITE; 864 865 if (limits == NULL) { /* Restore defaults */ 866 sdata = sc->sc_highlim[edata->sensor]; 867 xdata = sc->sc_highlim2; 868 } else 869 admtemp_encode_temp(limits->sel_warnmax, &sdata, 870 &xdata, ext11); 871 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 872 873 if (ext11) { 874 cmd = ADM1023_EXT_HIGH2; 875 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 876 } 877 } 878 879 if (*props & PROP_WARNMIN) { 880 if (edata->sensor == ADMTEMP_INT) 881 cmd = ADM1021_INT_LOW_WRITE; 882 else 883 cmd = ADM1021_EXT_LOW_WRITE; 884 if (limits == NULL) { 885 sdata = sc->sc_lowlim[edata->sensor]; 886 xdata = sc->sc_lowlim2; 887 } else 888 admtemp_encode_temp(limits->sel_warnmin, &sdata, 889 &xdata, ext11); 890 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 891 892 if (ext11) { 893 cmd = ADM1023_EXT_LOW2; 894 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 895 } 896 } 897 898 iic_release_bus(sc->sc_tag, 0); 899 } 900