1 /* $NetBSD: adm1021.c,v 1.33 2026/09/25 18:58:35 jdc 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.33 2026/09/25 18:58:35 jdc 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 int sc_temp_off[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 nonexistent 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 prop_dictionary_t props = device_properties(self); 338 uint8_t cmd, data, stat, comp, rev; 339 uint16_t temp_off; 340 char name[ADMTEMP_NAMELEN]; 341 char ename[64] = "external", iname[64] = "internal"; 342 343 sc->sc_tag = ia->ia_tag; 344 sc->sc_addr = ia->ia_addr; 345 346 if (iic_acquire_bus(sc->sc_tag, 0)) { 347 aprint_error_dev(self, "cannot acquire iic bus\n"); 348 return; 349 } 350 351 cmd = ADM1021_CONFIG_READ; 352 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) != 0) { 353 iic_release_bus(sc->sc_tag, 0); 354 aprint_error_dev(self, "cannot get control register\n"); 355 return; 356 } 357 if (data & ADM1021_CONFIG_RUN) { 358 cmd = ADM1021_STATUS; 359 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &stat)) { 360 iic_release_bus(sc->sc_tag, 0); 361 aprint_error_dev(self, 362 "cannot read status register\n"); 363 return; 364 } 365 if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) { 366 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, 367 &stat)) { 368 iic_release_bus(sc->sc_tag, 0); 369 aprint_error_dev(self, 370 "cannot read status register\n"); 371 return; 372 } 373 } 374 375 /* means external is dead */ 376 if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL && 377 (stat & ADM1021_STATUS_NOEXT)) 378 sc->sc_noexternal = 1; 379 380 data &= ~ADM1021_CONFIG_RUN; 381 cmd = ADM1021_CONFIG_WRITE; 382 if (admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data)) { 383 iic_release_bus(sc->sc_tag, 0); 384 aprint_error_dev(self, 385 "cannot set control register\n"); 386 return; 387 } 388 } 389 390 admtemp_setflags(sc, ia, &comp, &rev, name); 391 392 iic_release_bus(sc->sc_tag, 0); 393 394 aprint_normal(": %s temperature sensor", name); 395 if (comp) 396 aprint_normal(": id. 0x%02x, rev. 0x%02x\n", comp, rev); 397 else 398 aprint_normal("\n"); 399 aprint_naive(": Temperature sensor\n"); 400 401 /* Property override for temperature offsets */ 402 if (prop_dictionary_get_uint16(props, "temp_off", &temp_off) == 0) { 403 /* no offsets */ 404 sc->sc_temp_off[ADMTEMP_INT] = 0; 405 sc->sc_temp_off[ADMTEMP_EXT] = 0; 406 } else { 407 sc->sc_temp_off[ADMTEMP_INT] = (temp_off & 0xff) * 1000000; 408 sc->sc_temp_off[ADMTEMP_EXT] = (temp_off >> 8 & 0xff) * 1000000; 409 } 410 411 /* Initialize sensor data. */ 412 sc->sc_sensor[ADMTEMP_INT].state = ENVSYS_SINVALID; 413 sc->sc_sensor[ADMTEMP_INT].units = ENVSYS_STEMP; 414 sc->sc_sensor[ADMTEMP_EXT].state = ENVSYS_SINVALID; 415 sc->sc_sensor[ADMTEMP_EXT].units = ENVSYS_STEMP; 416 sc->sc_sensor[ADMTEMP_INT].flags = 417 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 418 sc->sc_sensor[ADMTEMP_EXT].flags = 419 ENVSYS_FMONLIMITS | ENVSYS_FHAS_ENTROPY; 420 421 /* Override default sensor names if the properties have been set. */ 422 device_getprop_string(self, "s00", iname, sizeof(iname)); 423 device_getprop_string(self, "s01", ename, sizeof(ename)); 424 425 strlcpy(sc->sc_sensor[ADMTEMP_INT].desc, iname, 426 sizeof(sc->sc_sensor[ADMTEMP_INT].desc)); 427 strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc, ename, 428 sizeof(sc->sc_sensor[ADMTEMP_EXT].desc)); 429 430 sc->sc_sme = sysmon_envsys_create(); 431 if (sysmon_envsys_sensor_attach( 432 sc->sc_sme, &sc->sc_sensor[ADMTEMP_INT])) { 433 sysmon_envsys_destroy(sc->sc_sme); 434 sc->sc_sme = NULL; 435 aprint_error_dev(self, 436 "unable to attach internal at sysmon\n"); 437 return; 438 } 439 if (sc->sc_noexternal == 0 && 440 sysmon_envsys_sensor_attach( 441 sc->sc_sme, &sc->sc_sensor[ADMTEMP_EXT])) { 442 sysmon_envsys_destroy(sc->sc_sme); 443 sc->sc_sme = NULL; 444 aprint_error_dev(self, 445 "unable to attach external at sysmon\n"); 446 return; 447 } 448 sc->sc_sme->sme_name = device_xname(self); 449 sc->sc_sme->sme_cookie = sc; 450 sc->sc_sme->sme_refresh = admtemp_refresh; 451 if (sc->sc_therm) { 452 sc->sc_sme->sme_get_limits = admtemp_getlim_1032; 453 sc->sc_sme->sme_set_limits = admtemp_setlim_1032; 454 } else if (sc->sc_ext11) { 455 sc->sc_sme->sme_get_limits = admtemp_getlim_1023; 456 sc->sc_sme->sme_set_limits = admtemp_setlim_1023; 457 } else { 458 sc->sc_sme->sme_get_limits = admtemp_getlim_1021; 459 sc->sc_sme->sme_set_limits = admtemp_setlim_1021; 460 } 461 if (sysmon_envsys_register(sc->sc_sme)) { 462 aprint_error_dev(self, 463 "unable to register with sysmon\n"); 464 sysmon_envsys_destroy(sc->sc_sme); 465 sc->sc_sme = NULL; 466 return; 467 } 468 } 469 470 471 void 472 admtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 473 { 474 struct admtemp_softc *sc = sme->sme_cookie; 475 uint8_t cmd, xdata; 476 int8_t sdata; 477 int temp_off; 478 479 if (iic_acquire_bus(sc->sc_tag, 0) != 0) 480 return; 481 482 if (edata->sensor == ADMTEMP_INT) { 483 cmd = ADM1021_INT_TEMP; 484 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 485 } else { 486 cmd = ADM1021_EXT_TEMP; 487 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 488 } 489 490 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &sdata) == 0) { 491 if (sdata == ADM1021_STATUS_INVAL) { 492 edata->state = ENVSYS_SINVALID; 493 } else { 494 edata->value_cur = (273150000 + 1000000 * sdata) + 495 temp_off; 496 edata->state = ENVSYS_SVALID; 497 } 498 } 499 if (edata->sensor == ADMTEMP_EXT && sc->sc_ext11) { 500 cmd = ADM1023_EXT_TEMP2; 501 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xdata); 502 edata->value_cur += 503 (xdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) * 125000; 504 } 505 506 iic_release_bus(sc->sc_tag, 0); 507 } 508 509 void 510 admtemp_getlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata, 511 sysmon_envsys_lim_t *limits, uint32_t *props) 512 { 513 struct admtemp_softc *sc = sme->sme_cookie; 514 uint8_t cmd; 515 int8_t hdata = 0x7f, ldata = 0xc9; 516 int temp_off; 517 518 *props &= ~(PROP_CRITMAX | PROP_CRITMIN); 519 520 if (iic_acquire_bus(sc->sc_tag, 0)) 521 return; 522 523 if (edata->sensor == ADMTEMP_INT) { 524 cmd = ADM1021_INT_HIGH_READ; 525 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 526 } else { 527 cmd = ADM1021_EXT_HIGH_READ; 528 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 529 } 530 531 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 532 hdata != ADMTEMP_LIM_INVAL) { 533 limits->sel_critmax = (273150000 + 1000000 * hdata) + temp_off; 534 *props |= PROP_CRITMAX; 535 } 536 537 if (sc->sc_nolow == 1) { 538 goto release; 539 } 540 541 if (edata->sensor == ADMTEMP_INT) 542 cmd = ADM1021_INT_LOW_READ; 543 else 544 cmd = ADM1021_EXT_LOW_READ; 545 546 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 547 ldata != ADMTEMP_LIM_INVAL) { 548 limits->sel_critmin = (273150000 + 1000000 * ldata) + temp_off; 549 *props |= PROP_CRITMIN; 550 } 551 552 release: 553 iic_release_bus(sc->sc_tag, 0); 554 555 /* Save the values if this is the first time through. */ 556 if (sc->sc_setdef[edata->sensor] == 0) { 557 sc->sc_setdef[edata->sensor] = 1; 558 sc->sc_highlim[edata->sensor] = hdata; 559 sc->sc_lowlim[edata->sensor] = ldata; 560 } 561 } 562 563 void 564 admtemp_getlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata, 565 sysmon_envsys_lim_t *limits, uint32_t *props) 566 { 567 struct admtemp_softc *sc = sme->sme_cookie; 568 uint8_t cmd, xhdata = 0, xldata = 0; 569 int8_t hdata = 0x7f, ldata = 0xc9; 570 int temp_off; 571 572 *props &= ~(PROP_CRITMAX | PROP_CRITMIN); 573 574 if (iic_acquire_bus(sc->sc_tag, 0)) 575 return; 576 577 if (edata->sensor == ADMTEMP_INT) { 578 cmd = ADM1021_INT_HIGH_READ; 579 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 580 } else { 581 cmd = ADM1021_EXT_HIGH_READ; 582 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 583 } 584 585 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 586 hdata != ADMTEMP_LIM_INVAL) { 587 limits->sel_critmax = (273150000 + 1000000 * hdata) + temp_off; 588 *props |= PROP_CRITMAX; 589 } 590 591 if (edata->sensor == ADMTEMP_EXT) { 592 cmd = ADM1023_EXT_HIGH2; 593 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0) 594 limits->sel_critmax += 595 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 596 * 125000; 597 } 598 599 if (edata->sensor == ADMTEMP_INT) 600 cmd = ADM1021_INT_LOW_READ; 601 else 602 cmd = ADM1021_EXT_LOW_READ; 603 604 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 605 ldata != ADMTEMP_LIM_INVAL) { 606 limits->sel_critmin = (273150000 + 1000000 * ldata) + temp_off; 607 *props |= PROP_CRITMIN; 608 } 609 610 if (edata->sensor == ADMTEMP_EXT) { 611 cmd = ADM1023_EXT_LOW2; 612 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0) 613 limits->sel_critmin += 614 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 615 * 125000; 616 } 617 618 iic_release_bus(sc->sc_tag, 0); 619 620 /* Save the values if this is the first time through. */ 621 if (sc->sc_setdef[edata->sensor] == 0) { 622 sc->sc_setdef[edata->sensor] = 1; 623 sc->sc_highlim[edata->sensor] = hdata; 624 sc->sc_lowlim[edata->sensor] = ldata; 625 if (edata->sensor == ADMTEMP_EXT) { 626 sc->sc_highlim2 = xhdata; 627 sc->sc_lowlim2 = xldata; 628 } 629 } 630 } 631 632 void 633 admtemp_getlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata, 634 sysmon_envsys_lim_t *limits, uint32_t *props) 635 { 636 struct admtemp_softc *sc = sme->sme_cookie; 637 uint8_t cmd, xhdata = 0, xldata = 0; 638 int8_t tdata = 0x55, hdata = 0x55, ldata = 0; 639 int temp_off; 640 641 *props &= ~(PROP_WARNMAX | PROP_CRITMAX | PROP_WARNMIN); 642 643 if (iic_acquire_bus(sc->sc_tag, 0)) 644 return; 645 646 if (edata->sensor == ADMTEMP_INT) { 647 cmd = ADM1032_INT_THERM; 648 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 649 } else { 650 cmd = ADM1032_EXT_THERM; 651 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 652 } 653 654 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &tdata) == 0 && 655 tdata != ADMTEMP_LIM_INVAL) { 656 limits->sel_critmax = (273150000 + 1000000 * tdata) + temp_off; 657 *props |= PROP_CRITMAX; 658 } 659 660 if (edata->sensor == ADMTEMP_INT) 661 cmd = ADM1021_INT_HIGH_READ; 662 else 663 cmd = ADM1021_EXT_HIGH_READ; 664 665 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 && 666 hdata != ADMTEMP_LIM_INVAL) { 667 limits->sel_warnmax = (273150000 + 1000000 * hdata) + temp_off; 668 *props |= PROP_WARNMAX; 669 } 670 671 if (edata->sensor == ADMTEMP_EXT) { 672 cmd = ADM1023_EXT_HIGH2; 673 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0) 674 limits->sel_warnmax += 675 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 676 * 125000; 677 } 678 679 if (edata->sensor == ADMTEMP_INT) 680 cmd = ADM1021_INT_LOW_READ; 681 else 682 cmd = ADM1021_EXT_LOW_READ; 683 684 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 && 685 ldata != ADMTEMP_LIM_INVAL) { 686 limits->sel_warnmin = (273150000 + 1000000 * ldata) + temp_off; 687 *props |= PROP_WARNMIN; 688 } 689 690 if (edata->sensor == ADMTEMP_EXT) { 691 cmd = ADM1023_EXT_LOW2; 692 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0) 693 limits->sel_warnmin += 694 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) 695 * 125000; 696 } 697 698 iic_release_bus(sc->sc_tag, 0); 699 700 /* Save the values if this is the first time through. */ 701 if (sc->sc_setdef[edata->sensor] == 0) { 702 sc->sc_setdef[edata->sensor] = 1; 703 sc->sc_thermlim[edata->sensor] = tdata; 704 sc->sc_highlim[edata->sensor] = hdata; 705 sc->sc_lowlim[edata->sensor] = ldata; 706 if (edata->sensor == ADMTEMP_EXT) { 707 sc->sc_highlim2 = xhdata; 708 sc->sc_lowlim2 = xldata; 709 } 710 } 711 } 712 713 void 714 admtemp_setlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata, 715 sysmon_envsys_lim_t *limits, uint32_t *props) 716 { 717 struct admtemp_softc *sc = sme->sme_cookie; 718 uint8_t cmd; 719 int tmp; 720 int8_t sdata; 721 int temp_off; 722 723 if (iic_acquire_bus(sc->sc_tag, 0)) 724 return; 725 726 if (edata->sensor == ADMTEMP_INT) 727 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 728 else 729 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 730 731 if (*props & PROP_CRITMAX) { 732 if (edata->sensor == ADMTEMP_INT) 733 cmd = ADM1021_INT_HIGH_WRITE; 734 else 735 cmd = ADM1021_EXT_HIGH_WRITE; 736 737 if (limits == NULL) /* Restore defaults */ 738 sdata = sc->sc_highlim[edata->sensor]; 739 else { 740 tmp = (limits->sel_critmax - temp_off - 273150000) 741 / 1000000; 742 if (tmp > ADMTEMP_MAX_POS) 743 sdata = ADMTEMP_MAX_POS; 744 else if (tmp < 0 && sc->sc_noneg) 745 sdata = 0; 746 else if (tmp < ADMTEMP_MAX_NEG) 747 sdata = ADMTEMP_MAX_NEG; 748 else 749 sdata = tmp & 0xff; 750 } 751 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 752 } 753 754 if (*props & PROP_CRITMIN && sc->sc_nolow == 0) { 755 if (edata->sensor == ADMTEMP_INT) 756 cmd = ADM1021_INT_LOW_WRITE; 757 else 758 cmd = ADM1021_EXT_LOW_WRITE; 759 if (limits == NULL) 760 sdata = sc->sc_lowlim[edata->sensor]; 761 else { 762 tmp = (limits->sel_critmin - temp_off - 273150000) 763 / 1000000; 764 if (tmp > ADMTEMP_MAX_POS) 765 sdata = ADMTEMP_MAX_POS; 766 else if (tmp < 0 && sc->sc_noneg) 767 sdata = 0; 768 else if (tmp < ADMTEMP_MAX_NEG) 769 sdata = ADMTEMP_MAX_NEG; 770 else 771 sdata = tmp & 0xff; 772 } 773 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 774 } 775 776 iic_release_bus(sc->sc_tag, 0); 777 } 778 779 static void 780 admtemp_encode_temp(const uint32_t val, int8_t *sdata, uint8_t *xdata, 781 const int ext11) 782 { 783 int32_t tmp; 784 785 if (ext11) { 786 /* Split temperature into high and low bytes */ 787 tmp = (val - 273150000) / 125000; 788 *xdata = (tmp & ADM1023_EXT2_MASK) << ADM1023_EXT2_SHIFT; 789 tmp -= (int32_t) (*xdata >> ADM1023_EXT2_SHIFT); 790 tmp /= 8; /* 1000000 / 125000 */ 791 } else { 792 *xdata = 0; 793 tmp = (val - 273150000) / 1000000; 794 } 795 if (tmp > ADMTEMP_MAX_POS) 796 *sdata = ADMTEMP_MAX_POS; 797 else if (tmp < 0) 798 *sdata = 0; 799 else 800 *sdata = tmp & 0xff; 801 } 802 803 void 804 admtemp_setlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata, 805 sysmon_envsys_lim_t *limits, uint32_t *props) 806 { 807 struct admtemp_softc *sc = sme->sme_cookie; 808 int ext11; 809 uint8_t cmd, xdata; 810 int8_t sdata; 811 int temp_off; 812 813 if (edata->sensor == ADMTEMP_INT) { 814 ext11 = 0; 815 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 816 } else { 817 ext11 = 1; 818 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 819 } 820 821 if (iic_acquire_bus(sc->sc_tag, 0)) 822 return; 823 824 if (*props & PROP_CRITMAX) { 825 if (edata->sensor == ADMTEMP_INT) 826 cmd = ADM1021_INT_HIGH_WRITE; 827 else 828 cmd = ADM1021_EXT_HIGH_WRITE; 829 830 if (limits == NULL) { /* Restore defaults */ 831 sdata = sc->sc_highlim[edata->sensor]; 832 xdata = sc->sc_highlim2; 833 } else 834 admtemp_encode_temp(limits->sel_critmax - temp_off, 835 &sdata, &xdata, ext11); 836 837 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 838 if (ext11) { 839 cmd = ADM1023_EXT_HIGH2; 840 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 841 } 842 } 843 844 if (*props & PROP_CRITMIN) { 845 if (edata->sensor == ADMTEMP_INT) 846 cmd = ADM1021_INT_LOW_WRITE; 847 else 848 cmd = ADM1021_EXT_LOW_WRITE; 849 if (limits == NULL) { 850 sdata = sc->sc_lowlim[edata->sensor]; 851 xdata = sc->sc_lowlim2; 852 } else 853 admtemp_encode_temp(limits->sel_critmax - temp_off, 854 &sdata, &xdata, ext11); 855 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 856 if (ext11) { 857 cmd = ADM1023_EXT_LOW2; 858 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 859 } 860 } 861 862 iic_release_bus(sc->sc_tag, 0); 863 } 864 865 void 866 admtemp_setlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata, 867 sysmon_envsys_lim_t *limits, uint32_t *props) 868 { 869 struct admtemp_softc *sc = sme->sme_cookie; 870 int ext11; 871 uint8_t cmd, xdata; 872 int8_t sdata; 873 int temp_off; 874 875 if (edata->sensor == ADMTEMP_INT) { 876 ext11 = 0; 877 temp_off = sc->sc_temp_off[ADMTEMP_INT]; 878 } else { 879 ext11 = 1; 880 temp_off = sc->sc_temp_off[ADMTEMP_EXT]; 881 } 882 883 if (iic_acquire_bus(sc->sc_tag, 0)) 884 return; 885 886 if (*props & PROP_CRITMAX) { 887 if (edata->sensor == ADMTEMP_INT) 888 cmd = ADM1032_INT_THERM; 889 else 890 cmd = ADM1032_EXT_THERM; 891 if (limits == NULL) /* Restore default */ 892 sdata = sc->sc_thermlim[edata->sensor]; 893 else 894 admtemp_encode_temp(limits->sel_critmax - temp_off, 895 &sdata, &xdata, 0); 896 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 897 } 898 899 if (*props & PROP_WARNMAX) { 900 if (edata->sensor == ADMTEMP_INT) 901 cmd = ADM1021_INT_HIGH_WRITE; 902 else 903 cmd = ADM1021_EXT_HIGH_WRITE; 904 905 if (limits == NULL) { /* Restore defaults */ 906 sdata = sc->sc_highlim[edata->sensor]; 907 xdata = sc->sc_highlim2; 908 } else 909 admtemp_encode_temp(limits->sel_warnmax - temp_off, 910 &sdata, &xdata, ext11); 911 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 912 913 if (ext11) { 914 cmd = ADM1023_EXT_HIGH2; 915 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 916 } 917 } 918 919 if (*props & PROP_WARNMIN) { 920 if (edata->sensor == ADMTEMP_INT) 921 cmd = ADM1021_INT_LOW_WRITE; 922 else 923 cmd = ADM1021_EXT_LOW_WRITE; 924 if (limits == NULL) { 925 sdata = sc->sc_lowlim[edata->sensor]; 926 xdata = sc->sc_lowlim2; 927 } else 928 admtemp_encode_temp(limits->sel_warnmin - temp_off, 929 &sdata, &xdata, ext11); 930 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata); 931 932 if (ext11) { 933 cmd = ADM1023_EXT_LOW2; 934 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata); 935 } 936 } 937 938 iic_release_bus(sc->sc_tag, 0); 939 } 940