lm75.c revision 1.33 1 /* $NetBSD: lm75.c,v 1.33 2018/06/26 06:03:57 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 2003 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: lm75.c,v 1.33 2018/06/26 06:03:57 thorpej Exp $");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/device.h>
44 #include <sys/kernel.h>
45 #include <sys/sysctl.h>
46
47 #include <dev/sysmon/sysmonvar.h>
48
49 #include <dev/i2c/i2cvar.h>
50 #include <dev/i2c/lm75reg.h>
51
52 #ifdef macppc
53 #define HAVE_OF 1
54 #endif
55
56 #ifdef HAVE_OF
57 #include <dev/ofw/openfirm.h>
58 #endif
59
60 struct lmtemp_softc {
61 device_t sc_dev;
62 i2c_tag_t sc_tag;
63 int sc_address;
64
65 struct sysmon_envsys *sc_sme;
66 envsys_data_t sc_sensor;
67 int sc_tmax;
68 uint32_t sc_smax, sc_smin, sc_scrit;
69
70 uint32_t (*sc_lmtemp_decode)(const uint8_t *, int);
71 void (*sc_lmtemp_encode)(const uint32_t, uint8_t *, int);
72 };
73
74 static int lmtemp_match(device_t, cfdata_t, void *);
75 static void lmtemp_attach(device_t, device_t, void *);
76
77 CFATTACH_DECL_NEW(lmtemp, sizeof(struct lmtemp_softc),
78 lmtemp_match, lmtemp_attach, NULL, NULL);
79
80 static void lmtemp_refresh(struct sysmon_envsys *, envsys_data_t *);
81 static int lmtemp_config_write(struct lmtemp_softc *, uint8_t);
82 static int lmtemp_temp_write(struct lmtemp_softc *, uint8_t, uint32_t,
83 int);
84 static int lmtemp_temp_read(struct lmtemp_softc *, uint8_t, uint32_t *,
85 int);
86 static uint32_t lmtemp_decode_lm75(const uint8_t *, int);
87 static uint32_t lmtemp_decode_ds75(const uint8_t *, int);
88 static uint32_t lmtemp_decode_lm77(const uint8_t *, int);
89 static void lmtemp_encode_lm75(const uint32_t, uint8_t *, int);
90 static void lmtemp_encode_ds75(const uint32_t, uint8_t *, int);
91 static void lmtemp_encode_lm77(const uint32_t, uint8_t *, int);
92 static void lmtemp_getlim_lm75(struct sysmon_envsys *, envsys_data_t *,
93 sysmon_envsys_lim_t *, uint32_t *);
94 static void lmtemp_getlim_lm77(struct sysmon_envsys *, envsys_data_t *,
95 sysmon_envsys_lim_t *, uint32_t *);
96 static void lmtemp_setlim_lm75(struct sysmon_envsys *, envsys_data_t *,
97 sysmon_envsys_lim_t *, uint32_t *);
98 static void lmtemp_setlim_lm77(struct sysmon_envsys *, envsys_data_t *,
99 sysmon_envsys_lim_t *, uint32_t *);
100
101 static void lmtemp_setup_sysctl(struct lmtemp_softc *);
102 static int sysctl_lm75_temp(SYSCTLFN_ARGS);
103
104 static const struct device_compatible_entry compat_data[] = {
105 { "i2c-lm75", 0 },
106 { "ds1775", 0 },
107 /*
108 * see XXX in _attach() below: add code once non-lm75 matches are
109 * added here!
110 */
111 { NULL, 0 }
112 };
113
114 enum {
115 lmtemp_lm75 = 0,
116 lmtemp_ds75,
117 lmtemp_lm77,
118 };
119 static const struct {
120 int lmtemp_type;
121 const char *lmtemp_name;
122 int lmtemp_addrmask;
123 int lmtemp_addr;
124 uint32_t (*lmtemp_decode)(const uint8_t *, int);
125 void (*lmtemp_encode)(const uint32_t, uint8_t *, int);
126 void (*lmtemp_getlim)(struct sysmon_envsys *, envsys_data_t *,
127 sysmon_envsys_lim_t *, uint32_t *);
128 void (*lmtemp_setlim)(struct sysmon_envsys *, envsys_data_t *,
129 sysmon_envsys_lim_t *, uint32_t *);
130 } lmtemptbl[] = {
131 { lmtemp_lm75, "LM75", LM75_ADDRMASK, LM75_ADDR,
132 lmtemp_decode_lm75, lmtemp_encode_lm75,
133 lmtemp_getlim_lm75, lmtemp_setlim_lm75 },
134 { lmtemp_ds75, "DS75", LM75_ADDRMASK, LM75_ADDR,
135 lmtemp_decode_ds75, lmtemp_encode_ds75,
136 lmtemp_getlim_lm75, lmtemp_setlim_lm75 },
137 { lmtemp_lm77, "LM77", LM77_ADDRMASK, LM77_ADDR,
138 lmtemp_decode_lm77, lmtemp_encode_lm77,
139 lmtemp_getlim_lm77, lmtemp_setlim_lm77 },
140 { -1, NULL, 0, 0,
141 NULL, NULL,
142 NULL, NULL }
143 };
144
145 static int
146 lmtemp_match(device_t parent, cfdata_t cf, void *aux)
147 {
148 struct i2c_attach_args *ia = aux;
149 int i, match_result;
150
151 if (iic_use_direct_match(ia, cf, compat_data, &match_result))
152 return match_result;
153
154 /*
155 * Indirect config - not much we can do!
156 */
157 for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++)
158 if (lmtemptbl[i].lmtemp_type == cf->cf_flags)
159 break;
160 if (lmtemptbl[i].lmtemp_type == -1)
161 return 0;
162
163 if ((ia->ia_addr & lmtemptbl[i].lmtemp_addrmask) ==
164 lmtemptbl[i].lmtemp_addr)
165 return I2C_MATCH_ADDRESS_ONLY;
166
167 return 0;
168 }
169
170 static void
171 lmtemp_attach(device_t parent, device_t self, void *aux)
172 {
173 struct lmtemp_softc *sc = device_private(self);
174 struct i2c_attach_args *ia = aux;
175 char name[64];
176 int i;
177
178 sc->sc_dev = self;
179 if (ia->ia_name == NULL) {
180 for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++)
181 if (lmtemptbl[i].lmtemp_type ==
182 device_cfdata(self)->cf_flags)
183 break;
184 } else {
185 if (strcmp(ia->ia_name, "ds1775") == 0) {
186 i = 1; /* LMTYPE_DS75 */
187 } else {
188 /* XXX - add code when adding other direct matches! */
189 i = 0;
190 }
191 }
192
193 sc->sc_tag = ia->ia_tag;
194 sc->sc_address = ia->ia_addr;
195
196 aprint_naive(": Temperature Sensor\n");
197 if (ia->ia_name) {
198 aprint_normal(": %s %s Temperature Sensor\n", ia->ia_name,
199 lmtemptbl[i].lmtemp_name);
200 } else {
201 aprint_normal(": %s Temperature Sensor\n",
202 lmtemptbl[i].lmtemp_name);
203 }
204
205 sc->sc_lmtemp_decode = lmtemptbl[i].lmtemp_decode;
206 sc->sc_lmtemp_encode = lmtemptbl[i].lmtemp_encode;
207
208 iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
209
210 /* Read temperature limit(s) and remember initial value(s). */
211 if (i == lmtemp_lm77) {
212 if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT,
213 &sc->sc_scrit, 1) != 0) {
214 aprint_error_dev(self,
215 "unable to read low register\n");
216 iic_release_bus(sc->sc_tag, I2C_F_POLL);
217 return;
218 }
219 if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT,
220 &sc->sc_smin, 1) != 0) {
221 aprint_error_dev(self,
222 "unable to read low register\n");
223 iic_release_bus(sc->sc_tag, I2C_F_POLL);
224 return;
225 }
226 if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT,
227 &sc->sc_smax, 1) != 0) {
228 aprint_error_dev(self,
229 "unable to read high register\n");
230 iic_release_bus(sc->sc_tag, I2C_F_POLL);
231 return;
232 }
233 } else { /* LM75 or compatible */
234 if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT,
235 &sc->sc_smax, 1) != 0) {
236 aprint_error_dev(self, "unable to read Tos register\n");
237 iic_release_bus(sc->sc_tag, I2C_F_POLL);
238 return;
239 }
240 }
241 sc->sc_tmax = sc->sc_smax;
242
243 if (i == lmtemp_lm75)
244 lmtemp_setup_sysctl(sc);
245
246 /* Set the configuration of the LM75 to defaults. */
247 if (lmtemp_config_write(sc, LM75_CONFIG_FAULT_QUEUE_4) != 0) {
248 aprint_error_dev(self, "unable to write config register\n");
249 iic_release_bus(sc->sc_tag, I2C_F_POLL);
250 return;
251 }
252 iic_release_bus(sc->sc_tag, I2C_F_POLL);
253
254 sc->sc_sme = sysmon_envsys_create();
255 /* Initialize sensor data. */
256 sc->sc_sensor.units = ENVSYS_STEMP;
257 sc->sc_sensor.state = ENVSYS_SINVALID;
258 sc->sc_sensor.flags = ENVSYS_FMONLIMITS;
259
260 (void)strlcpy(name,
261 ia->ia_name? ia->ia_name : device_xname(self),
262 sizeof(sc->sc_sensor.desc));
263 #ifdef HAVE_OF
264 int ch;
265 ch = OF_child(ia->ia_cookie);
266 if (ch != 0) {
267 OF_getprop(ch, "location", name, 64);
268 }
269 #endif
270 (void)strlcpy(sc->sc_sensor.desc, name,
271 sizeof(sc->sc_sensor.desc));
272 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor)) {
273 sysmon_envsys_destroy(sc->sc_sme);
274 return;
275 }
276
277 /* Hook into system monitor. */
278 sc->sc_sme->sme_name = device_xname(self);
279 sc->sc_sme->sme_cookie = sc;
280 sc->sc_sme->sme_refresh = lmtemp_refresh;
281 sc->sc_sme->sme_get_limits = lmtemptbl[i].lmtemp_getlim;
282 sc->sc_sme->sme_set_limits = lmtemptbl[i].lmtemp_setlim;
283
284 if (sysmon_envsys_register(sc->sc_sme)) {
285 aprint_error_dev(self, "unable to register with sysmon\n");
286 sysmon_envsys_destroy(sc->sc_sme);
287 }
288 }
289
290 static int
291 lmtemp_config_write(struct lmtemp_softc *sc, uint8_t val)
292 {
293 uint8_t cmdbuf[2];
294
295 cmdbuf[0] = LM75_REG_CONFIG;
296 cmdbuf[1] = val;
297
298 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
299 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL);
300 }
301
302 static int
303 lmtemp_temp_write(struct lmtemp_softc *sc, uint8_t reg, uint32_t val, int degc)
304 {
305 uint8_t cmdbuf[3];
306
307 cmdbuf[0] = reg;
308 sc->sc_lmtemp_encode(val, &cmdbuf[1], degc);
309
310 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
311 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 2, I2C_F_POLL);
312 }
313
314 static int
315 lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, uint32_t *valp,
316 int degc)
317 {
318 int error;
319 uint8_t cmdbuf[1];
320 uint8_t buf[LM75_TEMP_LEN];
321
322 cmdbuf[0] = which;
323
324 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
325 sc->sc_address, cmdbuf, 1, buf, LM75_TEMP_LEN, 0);
326 if (error)
327 return error;
328
329 *valp = sc->sc_lmtemp_decode(buf, degc);
330 return 0;
331 }
332
333 static void
334 lmtemp_refresh_sensor_data(struct lmtemp_softc *sc)
335 {
336 uint32_t val;
337 int error;
338
339 error = lmtemp_temp_read(sc, LM75_REG_TEMP, &val, 0);
340 if (error) {
341 #if 0
342 aprint_error_dev(sc->sc_dev, "unable to read temperature, error = %d\n",
343 error);
344 #endif
345 sc->sc_sensor.state = ENVSYS_SINVALID;
346 return;
347 }
348
349 sc->sc_sensor.value_cur = val;
350 sc->sc_sensor.state = ENVSYS_SVALID;
351 }
352
353 static void
354 lmtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
355 {
356 struct lmtemp_softc *sc = sme->sme_cookie;
357
358 iic_acquire_bus(sc->sc_tag, 0); /* also locks our instance */
359 lmtemp_refresh_sensor_data(sc);
360 iic_release_bus(sc->sc_tag, 0); /* also unlocks our instance */
361 }
362
363 static void
364 lmtemp_getlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata,
365 sysmon_envsys_lim_t *limits, uint32_t *props)
366 {
367 struct lmtemp_softc *sc = sme->sme_cookie;
368 uint32_t val;
369
370 *props &= ~(PROP_CRITMAX);
371
372 iic_acquire_bus(sc->sc_tag, 0);
373 if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &val, 0) == 0) {
374 limits->sel_critmax = val;
375 *props |= PROP_CRITMAX;
376 }
377 iic_release_bus(sc->sc_tag, 0);
378 }
379
380 static void
381 lmtemp_getlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata,
382 sysmon_envsys_lim_t *limits, uint32_t *props)
383 {
384 struct lmtemp_softc *sc = sme->sme_cookie;
385 uint32_t val;
386
387 *props &= ~(PROP_CRITMAX | PROP_WARNMAX | PROP_WARNMIN);
388
389 iic_acquire_bus(sc->sc_tag, 0);
390 if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT, &val, 0) == 0) {
391 limits->sel_critmax = val;
392 *props |= PROP_CRITMAX;
393 }
394 if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT, &val, 0) == 0) {
395 limits->sel_warnmax = val;
396 *props |= PROP_WARNMAX;
397 }
398 if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT, &val, 0) == 0) {
399 limits->sel_warnmin = val;
400 *props |= PROP_WARNMIN;
401 }
402 iic_release_bus(sc->sc_tag, 0);
403 }
404
405 static void
406 lmtemp_setlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata,
407 sysmon_envsys_lim_t *limits, uint32_t *props)
408 {
409 struct lmtemp_softc *sc = sme->sme_cookie;
410 int32_t limit;
411
412 if (*props & PROP_CRITMAX) {
413 if (limits == NULL) /* Restore defaults */
414 limit = sc->sc_smax;
415 else
416 limit = limits->sel_critmax;
417 iic_acquire_bus(sc->sc_tag, 0);
418 lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT,
419 limit - 5000000, 0);
420 lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, limit, 0);
421 iic_release_bus(sc->sc_tag, 0);
422
423 /* Synchronise sysctl */
424 sc->sc_tmax = (limit - 273150000) / 1000000;
425 }
426 }
427
428 static void
429 lmtemp_setlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata,
430 sysmon_envsys_lim_t *limits, uint32_t *props)
431 {
432 struct lmtemp_softc *sc = sme->sme_cookie;
433 int32_t limit;
434
435 iic_acquire_bus(sc->sc_tag, 0);
436 if (*props & PROP_CRITMAX) {
437 if (limits == NULL) /* Restore defaults */
438 limit = sc->sc_scrit;
439 else
440 limit = limits->sel_critmax;
441 lmtemp_temp_write(sc, LM77_REG_TCRIT_SET_POINT, limit, 0);
442 }
443 if (*props & PROP_WARNMAX) {
444 if (limits == NULL) /* Restore defaults */
445 limit = sc->sc_smax;
446 else
447 limit = limits->sel_warnmax;
448 lmtemp_temp_write(sc, LM77_REG_THIGH_SET_POINT, limit, 0);
449 }
450 if (*props & PROP_WARNMIN) {
451 if (limits == NULL) /* Restore defaults */
452 limit = sc->sc_smin;
453 else
454 limit = limits->sel_warnmin;
455 lmtemp_temp_write(sc, LM77_REG_TLOW_SET_POINT, limit, 0);
456 }
457 iic_release_bus(sc->sc_tag, 0);
458 }
459
460 static uint32_t
461 lmtemp_decode_lm75(const uint8_t *buf, int degc)
462 {
463 int temp;
464 uint32_t val;
465
466 /*
467 * LM75 temps are the most-significant 9 bits of a 16-bit reg.
468 * sign-extend the MSB and add in the 0.5 from the LSB
469 */
470 temp = (int8_t) buf[0];
471 temp = (temp << 1) + ((buf[1] >> 7) & 0x1);
472
473 /* Temp is given in 1/2 deg. C, we convert to C or uK. */
474 if (degc)
475 val = temp / 2;
476 else
477 val = temp * 500000 + 273150000;
478
479 return val;
480 }
481
482 static uint32_t
483 lmtemp_decode_ds75(const uint8_t *buf, int degc)
484 {
485 int temp;
486
487 /*
488 * Sign-extend the MSB byte, and add in the fractions of a
489 * degree contained in the LSB (precision 1/16th DegC).
490 */
491 temp = (int8_t)buf[0];
492 temp = (temp << 4) | ((buf[1] >> 4) & 0xf);
493
494 /*
495 * Conversion to C or uK is simple.
496 */
497 if (degc)
498 return temp / 16;
499 else
500 return (temp * 62500 + 273150000);
501 }
502
503 static uint32_t
504 lmtemp_decode_lm77(const uint8_t *buf, int degc)
505 {
506 int temp;
507 uint32_t val;
508
509 /*
510 * Describe each bits of temperature registers on LM77.
511 * D15 - D12: Sign
512 * D11 - D3 : Bit8(MSB) - Bit0
513 */
514 temp = (int8_t)buf[0];
515 temp = (temp << 5) | ((buf[1] >> 3) & 0x1f);
516
517 /* Temp is given in 1/2 deg. C, we convert to C or uK. */
518 if (degc)
519 val = temp / 2;
520 else
521 val = temp * 500000 + 273150000;
522
523 return val;
524 }
525
526 static void lmtemp_encode_lm75(const uint32_t val, uint8_t *buf, int degc)
527 {
528 int temp;
529
530 /* Convert from C or uK to register format */
531 if (degc)
532 temp = val * 2;
533 else
534 temp = (val - 273150000) / 500000;
535 buf[0] = (temp >> 1) & 0xff;
536 buf[1] = (temp & 1) << 7;
537 }
538
539 static void lmtemp_encode_ds75(const uint32_t val, uint8_t *buf, int degc)
540 {
541 int temp;
542
543 /* Convert from C or uK to register format */
544 if (degc)
545 temp = val * 16;
546 else
547 temp = (val - 273150000) / 62500;
548 buf[0] = (temp >> 4) & 0xff;
549 buf[1] = (temp & 0xf) << 4;
550 }
551
552 static void lmtemp_encode_lm77(const uint32_t val, uint8_t *buf, int degc)
553 {
554 int temp;
555
556 /* Convert from C or uK to register format */
557 if (degc)
558 temp = val * 2;
559 else
560 temp = (val - 273150000) / 500000;
561 buf[0] = (temp >> 5) & 0xff;
562 buf[1] = (temp & 0x1f) << 3;
563 }
564
565 static void
566 lmtemp_setup_sysctl(struct lmtemp_softc *sc)
567 {
568 const struct sysctlnode *me = NULL, *node = NULL;
569
570 sysctl_createv(NULL, 0, NULL, &me,
571 CTLFLAG_READWRITE,
572 CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
573 NULL, 0, NULL, 0,
574 CTL_MACHDEP, CTL_CREATE, CTL_EOL);
575
576 sysctl_createv(NULL, 0, NULL, &node,
577 CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
578 CTLTYPE_INT, "temp", "Threshold temperature",
579 sysctl_lm75_temp, 1, (void *)sc, 0,
580 CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
581 }
582
583 static int
584 sysctl_lm75_temp(SYSCTLFN_ARGS)
585 {
586 struct sysctlnode node = *rnode;
587 struct lmtemp_softc *sc = node.sysctl_data;
588 int temp;
589
590 if (newp) {
591
592 /* we're asked to write */
593 node.sysctl_data = &sc->sc_tmax;
594 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
595
596 temp = *(int *)node.sysctl_data;
597 sc->sc_tmax = temp;
598 iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
599 lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT,
600 sc->sc_tmax - 5, 1);
601 lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT,
602 sc->sc_tmax, 1);
603 iic_release_bus(sc->sc_tag, I2C_F_POLL);
604
605 /* Synchronise envsys - calls lmtemp_getlim_lm75() */
606 sysmon_envsys_update_limits(sc->sc_sme, &sc->sc_sensor);
607 return 0;
608 }
609 return EINVAL;
610 } else {
611
612 node.sysctl_data = &sc->sc_tmax;
613 node.sysctl_size = 4;
614 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
615 }
616
617 return 0;
618 }
619
620 SYSCTL_SETUP(sysctl_lmtemp_setup, "sysctl lmtemp subtree setup")
621 {
622
623 sysctl_createv(NULL, 0, NULL, NULL,
624 CTLFLAG_PERMANENT,
625 CTLTYPE_NODE, "machdep", NULL,
626 NULL, 0, NULL, 0,
627 CTL_MACHDEP, CTL_EOL);
628 }
629
630
631