adm1021.c revision 1.12 1 /* $NetBSD: adm1021.c,v 1.12 2016/01/04 19:24:15 christos 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, and Xeon embedded temperature sensors.
24 *
25 * Some sensors differ from the ADM1021/MAX1617/NE1617A:
26 * ADM1021A ADM1023 ADM1032 G781 LM84 MAX1617A
27 * company/revision reg X X X X X
28 * no negative temps X X X X
29 * 11-bit remote temp X X X
30 * no low limits X
31 * therm (high) limits 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.12 2016/01/04 19:24:15 christos 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 /* XXX: add flags for compats to admtemp_setflags() */
146 static const char * admtemp_compats[] = {
147 "i2c-max1617",
148 NULL
149 };
150
151 int
152 admtemp_match(device_t parent, cfdata_t match, void *aux)
153 {
154 struct i2c_attach_args *ia = aux;
155
156 if (ia->ia_name == NULL) {
157 /*
158 * Indirect config - not much we can do!
159 * Check typical addresses.
160 */
161 if (((ia->ia_addr >= 0x18) && (ia->ia_addr <= 0x1a)) ||
162 ((ia->ia_addr >= 0x29) && (ia->ia_addr <= 0x2b)) ||
163 ((ia->ia_addr >= 0x4c) && (ia->ia_addr <= 0x4e)))
164 return (1);
165 } else {
166 /*
167 * Direct config - match via the list of compatible
168 * hardware or simply match the device name.
169 */
170 if (ia->ia_ncompat > 0) {
171 if (iic_compat_match(ia, admtemp_compats))
172 return 1;
173 } else {
174 if (strcmp(ia->ia_name, "admtemp") == 0)
175 return 1;
176 }
177 }
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 }
237
238 /* Indirect config */
239 if (*comp == 0) {
240 sc->sc_noneg = 0;
241 cmd = ADM1021_INT_LOW_READ;
242 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, comp) == 0 &&
243 *comp != ADMTEMP_LOW_DEFAULT) {
244 sc->sc_nolow = 1;
245 strlcpy(name, "LM84", ADMTEMP_NAMELEN);
246 } else
247 strlcpy(name, "MAX1617", ADMTEMP_NAMELEN);
248 }
249
250 if (*comp == ADM1021_COMPANY_MAXIM) {
251 sc->sc_noneg = 0;
252 strlcpy(name, "MAX1617A", ADMTEMP_NAMELEN);
253 }
254
255 if (*comp == ADM1021_COMPANY_GMT) {
256 sc->sc_ext11 = 1;
257 sc->sc_therm = 1;
258 strlcpy(name, "G781", ADMTEMP_NAMELEN);
259 }
260
261 if (*comp == ADM1021_COMPANY_ADM) {
262 cmd = ADM1023_EXT_HIGH2;
263 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0) {
264 tmp = 1 << ADM1023_EXT2_SHIFT;
265 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &tmp);
266 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd,
267 &tmp) == 0 && tmp == 1 << ADM1023_EXT2_SHIFT) {
268 sc->sc_ext11 = 1;
269 strlcpy(name, "ADM1023", ADMTEMP_NAMELEN);
270 }
271 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data);
272 }
273 cmd = ADM1032_EXT_THERM;
274 if (sc->sc_ext11 &&
275 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) == 0
276 && data == 0x55) {
277 sc->sc_therm = 1;
278 strlcpy(name, "ADM1032", ADMTEMP_NAMELEN);
279 }
280 if (!sc->sc_ext11 &&
281 (*rev & ADM1021_REV_MASK) == ADM1021_REV_1021A) {
282 sc->sc_noneg = 0;
283 strlcpy(name, "ADM1021A", ADMTEMP_NAMELEN);
284 } else
285 strlcpy(name, "ADM1021", ADMTEMP_NAMELEN);
286 }
287 }
288
289 void
290 admtemp_attach(device_t parent, device_t self, void *aux)
291 {
292 struct admtemp_softc *sc = device_private(self);
293 struct i2c_attach_args *ia = aux;
294 uint8_t cmd, data, stat, comp, rev;
295 char name[ADMTEMP_NAMELEN];
296
297 sc->sc_tag = ia->ia_tag;
298 sc->sc_addr = ia->ia_addr;
299
300 iic_acquire_bus(sc->sc_tag, 0);
301 cmd = ADM1021_CONFIG_READ;
302 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &data) != 0) {
303 iic_release_bus(sc->sc_tag, 0);
304 aprint_error_dev(self, "cannot get control register\n");
305 return;
306 }
307 if (data & ADM1021_CONFIG_RUN) {
308 cmd = ADM1021_STATUS;
309 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &stat)) {
310 iic_release_bus(sc->sc_tag, 0);
311 aprint_error_dev(self,
312 "cannot read status register\n");
313 return;
314 }
315 if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) {
316 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd,
317 &stat)) {
318 iic_release_bus(sc->sc_tag, 0);
319 aprint_error_dev(self,
320 "cannot read status register\n");
321 return;
322 }
323 }
324
325 /* means external is dead */
326 if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL &&
327 (stat & ADM1021_STATUS_NOEXT))
328 sc->sc_noexternal = 1;
329
330 data &= ~ADM1021_CONFIG_RUN;
331 cmd = ADM1021_CONFIG_WRITE;
332 if (admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &data)) {
333 iic_release_bus(sc->sc_tag, 0);
334 aprint_error_dev(self,
335 "cannot set control register\n");
336 return;
337 }
338 }
339
340 admtemp_setflags(sc, ia, &comp, &rev, name);
341
342 iic_release_bus(sc->sc_tag, 0);
343
344 aprint_normal(": %s temperature sensor", name);
345 if (comp)
346 aprint_normal(": id. 0x%02x, rev. 0x%02x\n", comp, rev);
347 else
348 aprint_normal("\n");
349 aprint_naive(": Temperature sensor\n");
350
351 /* Initialize sensor data. */
352 sc->sc_sensor[ADMTEMP_INT].state = ENVSYS_SINVALID;
353 sc->sc_sensor[ADMTEMP_INT].units = ENVSYS_STEMP;
354 sc->sc_sensor[ADMTEMP_EXT].state = ENVSYS_SINVALID;
355 sc->sc_sensor[ADMTEMP_EXT].units = ENVSYS_STEMP;
356 sc->sc_sensor[ADMTEMP_INT].flags = ENVSYS_FMONLIMITS;
357 sc->sc_sensor[ADMTEMP_EXT].flags = ENVSYS_FMONLIMITS;
358 strlcpy(sc->sc_sensor[ADMTEMP_INT].desc, "internal",
359 sizeof(sc->sc_sensor[ADMTEMP_INT].desc));
360 strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc, "external",
361 sizeof(sc->sc_sensor[ADMTEMP_EXT].desc));
362 sc->sc_sme = sysmon_envsys_create();
363 if (sysmon_envsys_sensor_attach(
364 sc->sc_sme, &sc->sc_sensor[ADMTEMP_INT])) {
365 sysmon_envsys_destroy(sc->sc_sme);
366 aprint_error_dev(self,
367 "unable to attach internal at sysmon\n");
368 return;
369 }
370 if (sc->sc_noexternal == 0 &&
371 sysmon_envsys_sensor_attach(
372 sc->sc_sme, &sc->sc_sensor[ADMTEMP_EXT])) {
373 sysmon_envsys_destroy(sc->sc_sme);
374 aprint_error_dev(self,
375 "unable to attach external at sysmon\n");
376 return;
377 }
378 sc->sc_sme->sme_name = device_xname(self);
379 sc->sc_sme->sme_cookie = sc;
380 sc->sc_sme->sme_refresh = admtemp_refresh;
381 if (sc->sc_therm) {
382 sc->sc_sme->sme_get_limits = admtemp_getlim_1032;
383 sc->sc_sme->sme_set_limits = admtemp_setlim_1032;
384 } else if (sc->sc_ext11) {
385 sc->sc_sme->sme_get_limits = admtemp_getlim_1023;
386 sc->sc_sme->sme_set_limits = admtemp_setlim_1023;
387 } else {
388 sc->sc_sme->sme_get_limits = admtemp_getlim_1021;
389 sc->sc_sme->sme_set_limits = admtemp_setlim_1021;
390 }
391 if (sysmon_envsys_register(sc->sc_sme)) {
392 aprint_error_dev(self,
393 "unable to register with sysmon\n");
394 sysmon_envsys_destroy(sc->sc_sme);
395 return;
396 }
397 }
398
399
400 void
401 admtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
402 {
403 struct admtemp_softc *sc = sme->sme_cookie;
404 uint8_t cmd, xdata;
405 int8_t sdata;
406
407 iic_acquire_bus(sc->sc_tag, 0);
408
409 if (edata->sensor == ADMTEMP_INT)
410 cmd = ADM1021_INT_TEMP;
411 else
412 cmd = ADM1021_EXT_TEMP;
413
414 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &sdata) == 0) {
415 if (sdata == ADM1021_STATUS_INVAL) {
416 edata->state = ENVSYS_SINVALID;
417 } else {
418 edata->value_cur = 273150000 + 1000000 * sdata;
419 edata->state = ENVSYS_SVALID;
420 }
421 }
422 if (edata->sensor == ADMTEMP_EXT && sc->sc_ext11) {
423 cmd = ADM1023_EXT_TEMP2;
424 admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xdata);
425 edata->value_cur +=
426 (xdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK) * 125000;
427 }
428
429 iic_release_bus(sc->sc_tag, 0);
430 }
431
432 void
433 admtemp_getlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata,
434 sysmon_envsys_lim_t *limits, uint32_t *props)
435 {
436 struct admtemp_softc *sc = sme->sme_cookie;
437 uint8_t cmd;
438 int8_t hdata = 0x7f, ldata = 0xc9;
439
440 *props &= ~(PROP_CRITMAX | PROP_CRITMIN);
441
442 iic_acquire_bus(sc->sc_tag, 0);
443
444 if (edata->sensor == ADMTEMP_INT)
445 cmd = ADM1021_INT_HIGH_READ;
446 else
447 cmd = ADM1021_EXT_HIGH_READ;
448
449 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 &&
450 hdata != ADMTEMP_LIM_INVAL) {
451 limits->sel_critmax = 273150000 + 1000000 * hdata;
452 *props |= PROP_CRITMAX;
453 }
454
455 if (sc->sc_nolow == 1) {
456 goto release;
457 }
458
459 if (edata->sensor == ADMTEMP_INT)
460 cmd = ADM1021_INT_LOW_READ;
461 else
462 cmd = ADM1021_EXT_LOW_READ;
463
464 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 &&
465 ldata != ADMTEMP_LIM_INVAL) {
466 limits->sel_critmin = 273150000 + 1000000 * ldata;
467 *props |= PROP_CRITMIN;
468 }
469
470 release:
471 iic_release_bus(sc->sc_tag, 0);
472
473 /* Save the values if this is the first time through. */
474 if (sc->sc_setdef[edata->sensor] == 0) {
475 sc->sc_setdef[edata->sensor] = 1;
476 sc->sc_highlim[edata->sensor] = hdata;
477 sc->sc_lowlim[edata->sensor] = ldata;
478 }
479 }
480
481 void
482 admtemp_getlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata,
483 sysmon_envsys_lim_t *limits, uint32_t *props)
484 {
485 struct admtemp_softc *sc = sme->sme_cookie;
486 uint8_t cmd, xhdata = 0, xldata = 0;
487 int8_t hdata = 0x7f, ldata = 0xc9;
488
489 *props &= ~(PROP_CRITMAX | PROP_CRITMIN);
490
491 iic_acquire_bus(sc->sc_tag, 0);
492
493 if (edata->sensor == ADMTEMP_INT)
494 cmd = ADM1021_INT_HIGH_READ;
495 else
496 cmd = ADM1021_EXT_HIGH_READ;
497
498 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 &&
499 hdata != ADMTEMP_LIM_INVAL) {
500 limits->sel_critmax = 273150000 + 1000000 * hdata;
501 *props |= PROP_CRITMAX;
502 }
503
504 if (edata->sensor == ADMTEMP_EXT) {
505 cmd = ADM1023_EXT_HIGH2;
506 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0)
507 limits->sel_critmax +=
508 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK)
509 * 125000;
510 }
511
512 if (edata->sensor == ADMTEMP_INT)
513 cmd = ADM1021_INT_LOW_READ;
514 else
515 cmd = ADM1021_EXT_LOW_READ;
516
517 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 &&
518 ldata != ADMTEMP_LIM_INVAL) {
519 limits->sel_critmin = 273150000 + 1000000 * ldata;
520 *props |= PROP_CRITMIN;
521 }
522
523 if (edata->sensor == ADMTEMP_EXT) {
524 cmd = ADM1023_EXT_LOW2;
525 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0)
526 limits->sel_critmin +=
527 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK)
528 * 125000;
529 }
530
531 iic_release_bus(sc->sc_tag, 0);
532
533 /* Save the values if this is the first time through. */
534 if (sc->sc_setdef[edata->sensor] == 0) {
535 sc->sc_setdef[edata->sensor] = 1;
536 sc->sc_highlim[edata->sensor] = hdata;
537 sc->sc_lowlim[edata->sensor] = ldata;
538 if (edata->sensor == ADMTEMP_EXT) {
539 sc->sc_highlim2 = xhdata;
540 sc->sc_lowlim2 = xldata;
541 }
542 }
543 }
544
545 void
546 admtemp_getlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata,
547 sysmon_envsys_lim_t *limits, uint32_t *props)
548 {
549 struct admtemp_softc *sc = sme->sme_cookie;
550 uint8_t cmd, xhdata = 0, xldata = 0;
551 int8_t tdata = 0x55, hdata = 0x55, ldata = 0;
552
553 *props &= ~(PROP_WARNMAX | PROP_CRITMAX | PROP_WARNMIN);
554
555 iic_acquire_bus(sc->sc_tag, 0);
556
557 if (edata->sensor == ADMTEMP_INT)
558 cmd = ADM1032_INT_THERM;
559 else
560 cmd = ADM1032_EXT_THERM;
561
562 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &tdata) == 0 &&
563 tdata != ADMTEMP_LIM_INVAL) {
564 limits->sel_critmax = 273150000 + 1000000 * tdata;
565 *props |= PROP_CRITMAX;
566 }
567
568 if (edata->sensor == ADMTEMP_INT)
569 cmd = ADM1021_INT_HIGH_READ;
570 else
571 cmd = ADM1021_EXT_HIGH_READ;
572
573 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &hdata) == 0 &&
574 hdata != ADMTEMP_LIM_INVAL) {
575 limits->sel_warnmax = 273150000 + 1000000 * hdata;
576 *props |= PROP_WARNMAX;
577 }
578
579 if (edata->sensor == ADMTEMP_EXT) {
580 cmd = ADM1023_EXT_HIGH2;
581 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xhdata) == 0)
582 limits->sel_warnmax +=
583 (xhdata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK)
584 * 125000;
585 }
586
587 if (edata->sensor == ADMTEMP_INT)
588 cmd = ADM1021_INT_LOW_READ;
589 else
590 cmd = ADM1021_EXT_LOW_READ;
591
592 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &ldata) == 0 &&
593 ldata != ADMTEMP_LIM_INVAL) {
594 limits->sel_warnmin = 273150000 + 1000000 * ldata;
595 *props |= PROP_WARNMIN;
596 }
597
598 if (edata->sensor == ADMTEMP_EXT) {
599 cmd = ADM1023_EXT_LOW2;
600 if (admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &xldata) == 0)
601 limits->sel_warnmin +=
602 (xldata >> ADM1023_EXT2_SHIFT & ADM1023_EXT2_MASK)
603 * 125000;
604 }
605
606 iic_release_bus(sc->sc_tag, 0);
607
608 /* Save the values if this is the first time through. */
609 if (sc->sc_setdef[edata->sensor] == 0) {
610 sc->sc_setdef[edata->sensor] = 1;
611 sc->sc_thermlim[edata->sensor] = tdata;
612 sc->sc_highlim[edata->sensor] = hdata;
613 sc->sc_lowlim[edata->sensor] = ldata;
614 if (edata->sensor == ADMTEMP_EXT) {
615 sc->sc_highlim2 = xhdata;
616 sc->sc_lowlim2 = xldata;
617 }
618 }
619 }
620
621 void
622 admtemp_setlim_1021(struct sysmon_envsys *sme, envsys_data_t *edata,
623 sysmon_envsys_lim_t *limits, uint32_t *props)
624 {
625 struct admtemp_softc *sc = sme->sme_cookie;
626 uint8_t cmd;
627 int tmp;
628 int8_t sdata;
629
630 iic_acquire_bus(sc->sc_tag, 0);
631
632 if (*props & PROP_CRITMAX) {
633 if (edata->sensor == ADMTEMP_INT)
634 cmd = ADM1021_INT_HIGH_WRITE;
635 else
636 cmd = ADM1021_EXT_HIGH_WRITE;
637
638 if (limits == NULL) /* Restore defaults */
639 sdata = sc->sc_highlim[edata->sensor];
640 else {
641 tmp = (limits->sel_critmax - 273150000) / 1000000;
642 if (tmp > ADMTEMP_MAX_POS)
643 sdata = ADMTEMP_MAX_POS;
644 else if (tmp < 0 && sc->sc_noneg)
645 sdata = 0;
646 else if (tmp < ADMTEMP_MAX_NEG)
647 sdata = ADMTEMP_MAX_NEG;
648 else
649 sdata = tmp & 0xff;
650 }
651 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
652 }
653
654 if (*props & PROP_CRITMIN && sc->sc_nolow == 0) {
655 if (edata->sensor == ADMTEMP_INT)
656 cmd = ADM1021_INT_LOW_WRITE;
657 else
658 cmd = ADM1021_EXT_LOW_WRITE;
659 if (limits == NULL)
660 sdata = sc->sc_lowlim[edata->sensor];
661 else {
662 tmp = (limits->sel_critmin - 273150000) / 1000000;
663 if (tmp > ADMTEMP_MAX_POS)
664 sdata = ADMTEMP_MAX_POS;
665 else if (tmp < 0 && sc->sc_noneg)
666 sdata = 0;
667 else if (tmp < ADMTEMP_MAX_NEG)
668 sdata = ADMTEMP_MAX_NEG;
669 else
670 sdata = tmp & 0xff;
671 }
672 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
673 }
674
675 iic_release_bus(sc->sc_tag, 0);
676 }
677
678 static void
679 admtemp_encode_temp(const uint32_t val, int8_t *sdata, uint8_t *xdata,
680 const int ext11)
681 {
682 int32_t tmp;
683
684 if (ext11) {
685 /* Split temperature into high and low bytes */
686 tmp = (val - 273150000) / 125000;
687 *xdata = (tmp & ADM1023_EXT2_MASK) << ADM1023_EXT2_SHIFT;
688 tmp -= (int32_t) (*xdata >> ADM1023_EXT2_SHIFT);
689 tmp /= 8; /* 1000000 / 125000 */
690 } else {
691 *xdata = 0;
692 tmp = (val - 273150000) / 1000000;
693 }
694 if (tmp > ADMTEMP_MAX_POS)
695 *sdata = ADMTEMP_MAX_POS;
696 else if (tmp < 0)
697 *sdata = 0;
698 else
699 *sdata = tmp & 0xff;
700 }
701
702 void
703 admtemp_setlim_1023(struct sysmon_envsys *sme, envsys_data_t *edata,
704 sysmon_envsys_lim_t *limits, uint32_t *props)
705 {
706 struct admtemp_softc *sc = sme->sme_cookie;
707 int ext11;
708 uint8_t cmd, xdata;
709 int8_t sdata;
710
711 if (edata->sensor == ADMTEMP_INT)
712 ext11 = 0;
713 else
714 ext11 = 1;
715
716 iic_acquire_bus(sc->sc_tag, 0);
717
718 if (*props & PROP_CRITMAX) {
719 if (edata->sensor == ADMTEMP_INT)
720 cmd = ADM1021_INT_HIGH_WRITE;
721 else
722 cmd = ADM1021_EXT_HIGH_WRITE;
723
724 if (limits == NULL) { /* Restore defaults */
725 sdata = sc->sc_highlim[edata->sensor];
726 xdata = sc->sc_highlim2;
727 } else
728 admtemp_encode_temp(limits->sel_critmax, &sdata,
729 &xdata, ext11);
730
731 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
732 if (ext11) {
733 cmd = ADM1023_EXT_HIGH2;
734 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata);
735 }
736 }
737
738 if (*props & PROP_CRITMIN) {
739 if (edata->sensor == ADMTEMP_INT)
740 cmd = ADM1021_INT_LOW_WRITE;
741 else
742 cmd = ADM1021_EXT_LOW_WRITE;
743 if (limits == NULL) {
744 sdata = sc->sc_lowlim[edata->sensor];
745 xdata = sc->sc_lowlim2;
746 } else
747 admtemp_encode_temp(limits->sel_critmax, &sdata,
748 &xdata, ext11);
749 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
750 if (ext11) {
751 cmd = ADM1023_EXT_LOW2;
752 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata);
753 }
754 }
755
756 iic_release_bus(sc->sc_tag, 0);
757 }
758
759 void
760 admtemp_setlim_1032(struct sysmon_envsys *sme, envsys_data_t *edata,
761 sysmon_envsys_lim_t *limits, uint32_t *props)
762 {
763 struct admtemp_softc *sc = sme->sme_cookie;
764 int ext11;
765 uint8_t cmd, xdata;
766 int8_t sdata;
767
768 if (edata->sensor == ADMTEMP_INT)
769 ext11 = 0;
770 else
771 ext11 = 1;
772
773 iic_acquire_bus(sc->sc_tag, 0);
774
775 if (*props & PROP_CRITMAX) {
776 if (edata->sensor == ADMTEMP_INT)
777 cmd = ADM1032_INT_THERM;
778 else
779 cmd = ADM1032_EXT_THERM;
780 if (limits == NULL) /* Restore default */
781 sdata = sc->sc_thermlim[edata->sensor];
782 else
783 admtemp_encode_temp(limits->sel_critmax, &sdata,
784 &xdata, 0);
785 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
786 }
787
788 if (*props & PROP_WARNMAX) {
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_warnmax, &sdata,
799 &xdata, ext11);
800 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
801
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_WARNMIN) {
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_warnmin, &sdata,
818 &xdata, ext11);
819 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &sdata);
820
821 if (ext11) {
822 cmd = ADM1023_EXT_LOW2;
823 admtemp_exec(sc, I2C_OP_WRITE_WITH_STOP, &cmd, &xdata);
824 }
825 }
826
827 iic_release_bus(sc->sc_tag, 0);
828 }
829