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