1 /* $NetBSD: adm1021.c,v 1.31 2025/09/21 13:54:56 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.31 2025/09/21 13:54:56 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 114 int sc_flags; 115 int sc_noexternal, sc_noneg, sc_nolow; 116 int sc_ext11, sc_therm; 117 struct sysmon_envsys *sc_sme; 118 envsys_data_t sc_sensor[ADMTEMP_NUM_SENSORS]; 119 int sc_setdef[ADMTEMP_NUM_SENSORS]; 120 uint8_t sc_highlim[ADMTEMP_NUM_SENSORS]; 121 uint8_t sc_lowlim[ADMTEMP_NUM_SENSORS]; 122 uint8_t sc_highlim2, sc_lowlim2; 123 uint8_t sc_thermlim[ADMTEMP_NUM_SENSORS]; 124 }; 125 126 int admtemp_match(device_t, cfdata_t, void *); 127 void admtemp_attach(device_t, device_t, void *); 128 void admtemp_refresh(struct sysmon_envsys *, envsys_data_t *); 129 void admtemp_getlim_1021(struct sysmon_envsys *, envsys_data_t *, 130 sysmon_envsys_lim_t *, uint32_t *); 131 void admtemp_getlim_1023(struct sysmon_envsys *, envsys_data_t *, 132 sysmon_envsys_lim_t *, uint32_t *); 133 void admtemp_getlim_1032(struct sysmon_envsys *, envsys_data_t *, 134 sysmon_envsys_lim_t *, uint32_t *); 135 void admtemp_setlim_1021(struct sysmon_envsys *, envsys_data_t *, 136 sysmon_envsys_lim_t *, uint32_t *); 137 void admtemp_setlim_1023(struct sysmon_envsys *, envsys_data_t *, 138 sysmon_envsys_lim_t *, uint32_t *); 139 void admtemp_setlim_1032(struct sysmon_envsys *, envsys_data_t *, 140 sysmon_envsys_lim_t *, uint32_t *); 141 142 CFATTACH_DECL_NEW(admtemp, sizeof(struct admtemp_softc), 143 admtemp_match, admtemp_attach, NULL, NULL); 144 145 struct admtemp_params { 146 const char *name; 147 int noneg; 148 int nolow; 149 int ext11; 150 int therm; 151 }; 152 153 static const struct admtemp_params admtemp_params_max1617 = { 154 .name = "MAX1617A", 155 .noneg = 0, 156 .nolow = 0, 157 .ext11 = 0, 158 .therm = 0, 159 }; 160 161 static const struct admtemp_params admtemp_params_max6642 = { 162 .name = "MAX6642", 163 .noneg = 0, 164 .nolow = 1, 165 .ext11 = 0, 166 .therm = 0, 167 }; 168 169 static const struct admtemp_params admtemp_params_max6690 = { 170 .name = "MAX6690", 171 .noneg = 0, 172 .nolow = 0, 173 .ext11 = 1, 174 .therm = 0, 175 }; 176 177 static const struct device_compatible_entry compat_data[] = { 178 { .compat = "i2c-max1617", .data = &admtemp_params_max1617 }, 179 { .compat = "max6642", .data = &admtemp_params_max6642 }, 180 { .compat = "max6690", .data = &admtemp_params_max6690 }, 181 DEVICE_COMPAT_EOL 182 }; 183 184 int 185 admtemp_match(device_t parent, cfdata_t match, void *aux) 186 { 187 struct i2c_attach_args *ia = aux; 188 int match_result; 189 190 if (iic_use_direct_match(ia, match, compat_data, &match_result)) 191 return match_result; 192 193 /* 194 * Indirect config - not much we can do! 195 * Check typical addresses. 196 */ 197 if (((ia->ia_addr >= 0x18) && (ia->ia_addr <= 0x1a)) || 198 ((ia->ia_addr >= 0x29) && (ia->ia_addr <= 0x2b)) || 199 ((ia->ia_addr >= 0x48) && (ia->ia_addr <= 0x4e))) 200 return I2C_MATCH_ADDRESS_ONLY; 201 202 return 0; 203 } 204 205 static int 206 admtemp_exec(struct admtemp_softc *sc, i2c_op_t op, uint8_t *cmd, 207 uint8_t *data) 208 { 209 return iic_exec(sc->sc_tag, op, sc->sc_addr, cmd, sizeof(*cmd), data, 210 sizeof(*data), 0); 211 } 212 213 /* 214 * Set flags based on chip type for direct config, or by testing for 215 * indirect config. 216 * 217 * LM84, MAX1617, and NE1617A don't have company/revision registers. 218 * If we can't read the company register, we'll check the 219 * internal low limit to see if we have an LM84. 220 * 221 * To check if an ADM chip has 11-bit sensors, we'll write 0.125 222 * to the external temperature limit low byte register and read it 223 * back (because we can't tell from the id/rev). 224 * 225 * To check if an ADM chip has a Therm output, we check that we 226 * read 0x55 (default value) from the external therm limit. 227 * 228 * If an ADM chip doesn't have 11-bit sensors, check the revision to 229 * determine if it handles negative temperatures. 230 */ 231 static void 232 admtemp_setflags(struct admtemp_softc *sc, struct i2c_attach_args *ia, 233 uint8_t* comp, uint8_t *rev, char* name) 234 { 235 uint8_t cmd, data, tmp; 236 237 *comp = 0; 238 *rev = 0; 239 240 cmd = ADM1021_COMPANY; 241 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, comp); 242 243 cmd = ADM1021_DIE_REVISION; 244 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, rev); 245 246 sc->sc_noneg = 1; 247 sc->sc_nolow = 0; 248 sc->sc_ext11 = 0; 249 sc->sc_therm = 0; 250 251 /* Direct config */ 252 const struct device_compatible_entry *dce = 253 iic_compatible_lookup(ia, compat_data); 254 if (dce != NULL) { 255 const struct admtemp_params *params = dce->data; 256 257 sc->sc_noneg = params->noneg; 258 sc->sc_nolow = params->nolow; 259 sc->sc_ext11 = params->ext11; 260 sc->sc_therm = params->therm; 261 strlcpy(name, params->name, ADMTEMP_NAMELEN); 262 return; 263 } 264 265 /* Indirect config */ 266 if (*comp == 0) { 267 sc->sc_noneg = 0; 268 cmd = ADM1021_INT_LOW_READ; 269 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, comp) == 0 && 270 *comp != ADMTEMP_LOW_DEFAULT) { 271 sc->sc_nolow = 1; 272 strlcpy(name, "LM84", ADMTEMP_NAMELEN); 273 } else 274 strlcpy(name, "MAX1617", ADMTEMP_NAMELEN); 275 } 276 277 if (*comp == ADM1021_COMPANY_MAXIM) { 278 sc->sc_noneg = 0; 279 /* 280 * MAX6642 doesn't have a revision register 281 * XXX this works only on macppc with iic at pmu because the 282 * pmu doesn't return an error for nonexistent registers, it 283 * just repeats previous data 284 */ 285 if (*comp == *rev) { 286 sc->sc_therm = 0; /* */ 287 sc->sc_nolow = 1; 288 strlcpy(name, "MAX6642", ADMTEMP_NAMELEN); 289 } else if (*rev == 0) { 290 strlcpy(name, "MAX6690", ADMTEMP_NAMELEN); 291 sc->sc_ext11 = 1; 292 } else { 293 strlcpy(name, "MAX1617A", ADMTEMP_NAMELEN); 294 } 295 } 296 297 if (*comp == ADM1021_COMPANY_GMT) { 298 sc->sc_ext11 = 1; 299 sc->sc_therm = 1; 300 strlcpy(name, "G781", ADMTEMP_NAMELEN); 301 } 302 303 if (*comp == ADM1021_COMPANY_ADM) { 304 cmd = ADM1023_EXT_HIGH2; 305 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0) { 306 tmp = 1 << ADM1023_EXT2_SHIFT; 307 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &tmp); 308 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, 309 &tmp) == 0 && tmp == 1 << ADM1023_EXT2_SHIFT) { 310 sc->sc_ext11 = 1; 311 strlcpy(name, "ADM1023", ADMTEMP_NAMELEN); 312 } 313 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data); 314 } 315 cmd = ADM1032_EXT_THERM; 316 if (sc->sc_ext11 && 317 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0 318 && data == 0x55) { 319 sc->sc_therm = 1; 320 strlcpy(name, "ADM1032", ADMTEMP_NAMELEN); 321 } 322 if (!sc->sc_ext11 && 323 (*rev & ADM1021_REV_MASK) == ADM1021_REV_1021A) { 324 sc->sc_noneg = 0; 325 strlcpy(name, "ADM1021A", ADMTEMP_NAMELEN); 326 } else 327 strlcpy(name, "ADM1021", ADMTEMP_NAMELEN); 328 } 329 } 330 331 void 332 admtemp_attach(device_t parent, device_t self, void *aux) 333 { 334 struct admtemp_softc *sc = device_private(self); 335 struct i2c_attach_args *ia = aux; 336 uint8_t cmd, data, stat, comp, rev; 337 char name[ADMTEMP_NAMELEN]; 338 char ename[64] = "external", iname[64] = "internal"; 339 const char *desc; 340 prop_dictionary_t props = device_properties(self); 341 342 sc->sc_tag = ia->ia_tag; 343 sc->sc_addr = ia->ia_addr; 344 345 if (iic_acquire_bus(sc->sc_tag, 0)) { 346 aprint_error_dev(self, "cannot acquire iic bus\n"); 347 return; 348 } 349 350 cmd = ADM1021_CONFIG_READ; 351 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) != 0) { 352 iic_release_bus(sc->sc_tag, 0); 353 aprint_error_dev(self, "cannot get control register\n"); 354 return; 355 } 356 if (data & ADM1021_CONFIG_RUN) { 357 cmd = ADM1021_STATUS; 358 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &stat)) { 359 iic_release_bus(sc->sc_tag, 0); 360 aprint_error_dev(self, 361 "cannot read status register\n"); 362 return; 363 } 364 if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) { 365 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, 366 &stat)) { 367 iic_release_bus(sc->sc_tag, 0); 368 aprint_error_dev(self, 369 "cannot read status register\n"); 370 return; 371 } 372 } 373 374 /* means external is dead */ 375 if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL && 376 (stat & ADM1021_STATUS_NOEXT)) 377 sc->sc_noexternal = 1; 378 379 data &= ~ADM1021_CONFIG_RUN; 380 cmd = ADM1021_CONFIG_WRITE; 381 if (admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data)) { 382 iic_release_bus(sc->sc_tag, 0); 383 aprint_error_dev(self, 384 "cannot set control register\n"); 385 return; 386 } 387 } 388 389 admtemp_setflags(sc, ia, &comp, &rev, name); 390 391 iic_release_bus(sc->sc_tag, 0); 392 393 aprint_normal(": %s temperature sensor", name); 394 if (comp) 395 aprint_normal(": id. 0x%02x, rev. 0x%02x\n", comp, rev); 396 else 397 aprint_normal("\n"); 398 aprint_naive(": Temperature sensor\n"); 399 400 /* Initialize sensor data. */ 401 sc->sc_sensor[ADMTEMP_INT].state = ENVSYS_SINVALID; 402 sc->sc_sensor[ADMTEMP_INT].units = ENVSYS_STEMP; 403 sc->sc_sensor[ADMTEMP_EXT].state = ENVSYS_SINVALID; 404 sc->sc_sensor[ADMTEMP_EXT].units = ENVSYS_STEMP; 405 sc->sc_sensor[ADMTEMP_INT].flags = 406 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 407 sc->sc_sensor[ADMTEMP_EXT].flags = 408 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 409 410 if (prop_dictionary_get_string(props, "s00", &desc)) { 411 strncpy(iname, desc, 64); 412 } 413 414 if (prop_dictionary_get_string(props, "s01", &desc)) { 415 strncpy(ename, desc, 64); 416 } 417 418 strlcpy(sc->sc_sensor[ADMTEMP_INT].desc, iname, 419 sizeof(sc->sc_sensor[ADMTEMP_INT].desc)); 420 strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc, ename, 421 sizeof(sc->sc_sensor[ADMTEMP_EXT].desc)); 422 423 sc->sc_sme = sysmon_envsys_create(); 424 if (sysmon_envsys_sensor_attach( 425 sc->sc_sme, &sc->sc_sensor[ADMTEMP_INT])) { 426 sysmon_envsys_destroy(sc->sc_sme); 427 sc->sc_sme = NULL; 428 aprint_error_dev(self, 429 "unable to attach internal at sysmon\n"); 430 return; 431 } 432 if (sc->sc_noexternal == 0 && 433 sysmon_envsys_sensor_attach( 434 sc->sc_sme, &sc->sc_sensor[ADMTEMP_EXT])) { 435 sysmon_envsys_destroy(sc->sc_sme); 436 sc->sc_sme = NULL; 437 aprint_error_dev(self, 438 "unable to attach external at sysmon\n"); 439 return; 440 } 441 sc->sc_sme->sme_name = device_xname(self); 442 sc->sc_sme->sme_cookie = sc; 443 sc->sc_sme->sme_refresh = admtemp_refresh; 444 if (sc->sc_therm) { 445 sc->sc_sme->sme_get_limits = admtemp_getlim_1032; 446 sc->sc_sme->sme_set_limits = admtemp_setlim_1032; 447 } else if (sc->sc_ext11) { 448 sc->sc_sme->sme_get_limits = admtemp_getlim_1023; 449 sc->sc_sme->sme_set_limits = admtemp_setlim_1023; 450 } else { 451 sc->sc_sme->sme_get_limits = admtemp_getlim_1021; 452 sc->sc_sme->sme_set_limits = admtemp_setlim_1021; 453 } 454 if (sysmon_envsys_register(sc->sc_sme)) { 455 aprint_error_dev(self, 456 "unable to register with sysmon\n"); 457 sysmon_envsys_destroy(sc->sc_sme); 458 sc->sc_sme = NULL; 459 return; 460 } 461 } 462 463 464 void 465 admtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 466 { 467 struct admtemp_softc *sc = sme->sme_cookie; 468 uint8_t cmd, xdata; 469 int8_t sdata; 470 471 if (iic_acquire_bus(sc->sc_tag, 0) != 0) 472 return; 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