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