1 /* $NetBSD: lm75.c,v 1.34 2019/02/20 18:19:46 macallan 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.34 2019/02/20 18:19:46 macallan 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 { "lm75", 0 }, 107 { "ds1775", 0 }, 108 /* 109 * see XXX in _attach() below: add code once non-lm75 matches are 110 * added here! 111 */ 112 { NULL, 0 } 113 }; 114 115 enum { 116 lmtemp_lm75 = 0, 117 lmtemp_ds75, 118 lmtemp_lm77, 119 }; 120 static const struct { 121 int lmtemp_type; 122 const char *lmtemp_name; 123 int lmtemp_addrmask; 124 int lmtemp_addr; 125 uint32_t (*lmtemp_decode)(const uint8_t *, int); 126 void (*lmtemp_encode)(const uint32_t, uint8_t *, int); 127 void (*lmtemp_getlim)(struct sysmon_envsys *, envsys_data_t *, 128 sysmon_envsys_lim_t *, uint32_t *); 129 void (*lmtemp_setlim)(struct sysmon_envsys *, envsys_data_t *, 130 sysmon_envsys_lim_t *, uint32_t *); 131 } lmtemptbl[] = { 132 { lmtemp_lm75, "LM75", LM75_ADDRMASK, LM75_ADDR, 133 lmtemp_decode_lm75, lmtemp_encode_lm75, 134 lmtemp_getlim_lm75, lmtemp_setlim_lm75 }, 135 { lmtemp_ds75, "DS75", LM75_ADDRMASK, LM75_ADDR, 136 lmtemp_decode_ds75, lmtemp_encode_ds75, 137 lmtemp_getlim_lm75, lmtemp_setlim_lm75 }, 138 { lmtemp_lm77, "LM77", LM77_ADDRMASK, LM77_ADDR, 139 lmtemp_decode_lm77, lmtemp_encode_lm77, 140 lmtemp_getlim_lm77, lmtemp_setlim_lm77 }, 141 { -1, NULL, 0, 0, 142 NULL, NULL, 143 NULL, NULL } 144 }; 145 146 static int 147 lmtemp_match(device_t parent, cfdata_t cf, void *aux) 148 { 149 struct i2c_attach_args *ia = aux; 150 int i, match_result; 151 152 if (iic_use_direct_match(ia, cf, compat_data, &match_result)) 153 return match_result; 154 155 /* 156 * Indirect config - not much we can do! 157 */ 158 for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++) 159 if (lmtemptbl[i].lmtemp_type == cf->cf_flags) 160 break; 161 if (lmtemptbl[i].lmtemp_type == -1) 162 return 0; 163 164 if ((ia->ia_addr & lmtemptbl[i].lmtemp_addrmask) == 165 lmtemptbl[i].lmtemp_addr) 166 return I2C_MATCH_ADDRESS_ONLY; 167 168 return 0; 169 } 170 171 static void 172 lmtemp_attach(device_t parent, device_t self, void *aux) 173 { 174 struct lmtemp_softc *sc = device_private(self); 175 struct i2c_attach_args *ia = aux; 176 char name[64]; 177 int i; 178 179 sc->sc_dev = self; 180 if (ia->ia_name == NULL) { 181 for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++) 182 if (lmtemptbl[i].lmtemp_type == 183 device_cfdata(self)->cf_flags) 184 break; 185 } else { 186 if (strcmp(ia->ia_name, "ds1775") == 0) { 187 i = 1; /* LMTYPE_DS75 */ 188 } else { 189 /* XXX - add code when adding other direct matches! */ 190 i = 0; 191 } 192 } 193 194 sc->sc_tag = ia->ia_tag; 195 sc->sc_address = ia->ia_addr; 196 197 aprint_naive(": Temperature Sensor\n"); 198 if (ia->ia_name) { 199 aprint_normal(": %s %s Temperature Sensor\n", ia->ia_name, 200 lmtemptbl[i].lmtemp_name); 201 } else { 202 aprint_normal(": %s Temperature Sensor\n", 203 lmtemptbl[i].lmtemp_name); 204 } 205 206 sc->sc_lmtemp_decode = lmtemptbl[i].lmtemp_decode; 207 sc->sc_lmtemp_encode = lmtemptbl[i].lmtemp_encode; 208 209 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 210 211 /* Read temperature limit(s) and remember initial value(s). */ 212 if (i == lmtemp_lm77) { 213 if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT, 214 &sc->sc_scrit, 1) != 0) { 215 aprint_error_dev(self, 216 "unable to read low register\n"); 217 iic_release_bus(sc->sc_tag, I2C_F_POLL); 218 return; 219 } 220 if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT, 221 &sc->sc_smin, 1) != 0) { 222 aprint_error_dev(self, 223 "unable to read low register\n"); 224 iic_release_bus(sc->sc_tag, I2C_F_POLL); 225 return; 226 } 227 if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT, 228 &sc->sc_smax, 1) != 0) { 229 aprint_error_dev(self, 230 "unable to read high register\n"); 231 iic_release_bus(sc->sc_tag, I2C_F_POLL); 232 return; 233 } 234 } else { /* LM75 or compatible */ 235 if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, 236 &sc->sc_smax, 1) != 0) { 237 aprint_error_dev(self, "unable to read Tos register\n"); 238 iic_release_bus(sc->sc_tag, I2C_F_POLL); 239 return; 240 } 241 } 242 sc->sc_tmax = sc->sc_smax; 243 244 if (i == lmtemp_lm75) 245 lmtemp_setup_sysctl(sc); 246 247 /* Set the configuration of the LM75 to defaults. */ 248 if (lmtemp_config_write(sc, LM75_CONFIG_FAULT_QUEUE_4) != 0) { 249 aprint_error_dev(self, "unable to write config register\n"); 250 iic_release_bus(sc->sc_tag, I2C_F_POLL); 251 return; 252 } 253 iic_release_bus(sc->sc_tag, I2C_F_POLL); 254 255 sc->sc_sme = sysmon_envsys_create(); 256 /* Initialize sensor data. */ 257 sc->sc_sensor.units = ENVSYS_STEMP; 258 sc->sc_sensor.state = ENVSYS_SINVALID; 259 sc->sc_sensor.flags = ENVSYS_FMONLIMITS; 260 261 (void)strlcpy(name, 262 ia->ia_name? ia->ia_name : device_xname(self), 263 sizeof(sc->sc_sensor.desc)); 264 #ifdef HAVE_OF 265 int ch; 266 ch = OF_child(ia->ia_cookie); 267 if (ch != 0) { 268 OF_getprop(ch, "location", name, 64); 269 } 270 #endif 271 (void)strlcpy(sc->sc_sensor.desc, name, 272 sizeof(sc->sc_sensor.desc)); 273 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor)) { 274 sysmon_envsys_destroy(sc->sc_sme); 275 return; 276 } 277 278 /* Hook into system monitor. */ 279 sc->sc_sme->sme_name = device_xname(self); 280 sc->sc_sme->sme_cookie = sc; 281 sc->sc_sme->sme_refresh = lmtemp_refresh; 282 sc->sc_sme->sme_get_limits = lmtemptbl[i].lmtemp_getlim; 283 sc->sc_sme->sme_set_limits = lmtemptbl[i].lmtemp_setlim; 284 285 if (sysmon_envsys_register(sc->sc_sme)) { 286 aprint_error_dev(self, "unable to register with sysmon\n"); 287 sysmon_envsys_destroy(sc->sc_sme); 288 } 289 } 290 291 static int 292 lmtemp_config_write(struct lmtemp_softc *sc, uint8_t val) 293 { 294 uint8_t cmdbuf[2]; 295 296 cmdbuf[0] = LM75_REG_CONFIG; 297 cmdbuf[1] = val; 298 299 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 300 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL); 301 } 302 303 static int 304 lmtemp_temp_write(struct lmtemp_softc *sc, uint8_t reg, uint32_t val, int degc) 305 { 306 uint8_t cmdbuf[3]; 307 308 cmdbuf[0] = reg; 309 sc->sc_lmtemp_encode(val, &cmdbuf[1], degc); 310 311 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 312 sc->sc_address, cmdbuf, 1, &cmdbuf[1], 2, I2C_F_POLL); 313 } 314 315 static int 316 lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, uint32_t *valp, 317 int degc) 318 { 319 int error; 320 uint8_t cmdbuf[1]; 321 uint8_t buf[LM75_TEMP_LEN]; 322 323 cmdbuf[0] = which; 324 325 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 326 sc->sc_address, cmdbuf, 1, buf, LM75_TEMP_LEN, 0); 327 if (error) 328 return error; 329 330 *valp = sc->sc_lmtemp_decode(buf, degc); 331 return 0; 332 } 333 334 static void 335 lmtemp_refresh_sensor_data(struct lmtemp_softc *sc) 336 { 337 uint32_t val; 338 int error; 339 340 error = lmtemp_temp_read(sc, LM75_REG_TEMP, &val, 0); 341 if (error) { 342 #if 0 343 aprint_error_dev(sc->sc_dev, "unable to read temperature, error = %d\n", 344 error); 345 #endif 346 sc->sc_sensor.state = ENVSYS_SINVALID; 347 return; 348 } 349 350 sc->sc_sensor.value_cur = val; 351 sc->sc_sensor.state = ENVSYS_SVALID; 352 } 353 354 static void 355 lmtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 356 { 357 struct lmtemp_softc *sc = sme->sme_cookie; 358 359 iic_acquire_bus(sc->sc_tag, 0); /* also locks our instance */ 360 lmtemp_refresh_sensor_data(sc); 361 iic_release_bus(sc->sc_tag, 0); /* also unlocks our instance */ 362 } 363 364 static void 365 lmtemp_getlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata, 366 sysmon_envsys_lim_t *limits, uint32_t *props) 367 { 368 struct lmtemp_softc *sc = sme->sme_cookie; 369 uint32_t val; 370 371 *props &= ~(PROP_CRITMAX); 372 373 iic_acquire_bus(sc->sc_tag, 0); 374 if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &val, 0) == 0) { 375 limits->sel_critmax = val; 376 *props |= PROP_CRITMAX; 377 } 378 iic_release_bus(sc->sc_tag, 0); 379 } 380 381 static void 382 lmtemp_getlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata, 383 sysmon_envsys_lim_t *limits, uint32_t *props) 384 { 385 struct lmtemp_softc *sc = sme->sme_cookie; 386 uint32_t val; 387 388 *props &= ~(PROP_CRITMAX | PROP_WARNMAX | PROP_WARNMIN); 389 390 iic_acquire_bus(sc->sc_tag, 0); 391 if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT, &val, 0) == 0) { 392 limits->sel_critmax = val; 393 *props |= PROP_CRITMAX; 394 } 395 if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT, &val, 0) == 0) { 396 limits->sel_warnmax = val; 397 *props |= PROP_WARNMAX; 398 } 399 if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT, &val, 0) == 0) { 400 limits->sel_warnmin = val; 401 *props |= PROP_WARNMIN; 402 } 403 iic_release_bus(sc->sc_tag, 0); 404 } 405 406 static void 407 lmtemp_setlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata, 408 sysmon_envsys_lim_t *limits, uint32_t *props) 409 { 410 struct lmtemp_softc *sc = sme->sme_cookie; 411 int32_t limit; 412 413 if (*props & PROP_CRITMAX) { 414 if (limits == NULL) /* Restore defaults */ 415 limit = sc->sc_smax; 416 else 417 limit = limits->sel_critmax; 418 iic_acquire_bus(sc->sc_tag, 0); 419 lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT, 420 limit - 5000000, 0); 421 lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, limit, 0); 422 iic_release_bus(sc->sc_tag, 0); 423 424 /* Synchronise sysctl */ 425 sc->sc_tmax = (limit - 273150000) / 1000000; 426 } 427 } 428 429 static void 430 lmtemp_setlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata, 431 sysmon_envsys_lim_t *limits, uint32_t *props) 432 { 433 struct lmtemp_softc *sc = sme->sme_cookie; 434 int32_t limit; 435 436 iic_acquire_bus(sc->sc_tag, 0); 437 if (*props & PROP_CRITMAX) { 438 if (limits == NULL) /* Restore defaults */ 439 limit = sc->sc_scrit; 440 else 441 limit = limits->sel_critmax; 442 lmtemp_temp_write(sc, LM77_REG_TCRIT_SET_POINT, limit, 0); 443 } 444 if (*props & PROP_WARNMAX) { 445 if (limits == NULL) /* Restore defaults */ 446 limit = sc->sc_smax; 447 else 448 limit = limits->sel_warnmax; 449 lmtemp_temp_write(sc, LM77_REG_THIGH_SET_POINT, limit, 0); 450 } 451 if (*props & PROP_WARNMIN) { 452 if (limits == NULL) /* Restore defaults */ 453 limit = sc->sc_smin; 454 else 455 limit = limits->sel_warnmin; 456 lmtemp_temp_write(sc, LM77_REG_TLOW_SET_POINT, limit, 0); 457 } 458 iic_release_bus(sc->sc_tag, 0); 459 } 460 461 static uint32_t 462 lmtemp_decode_lm75(const uint8_t *buf, int degc) 463 { 464 int temp; 465 uint32_t val; 466 467 /* 468 * LM75 temps are the most-significant 9 bits of a 16-bit reg. 469 * sign-extend the MSB and add in the 0.5 from the LSB 470 */ 471 temp = (int8_t) buf[0]; 472 temp = (temp << 1) + ((buf[1] >> 7) & 0x1); 473 474 /* Temp is given in 1/2 deg. C, we convert to C or uK. */ 475 if (degc) 476 val = temp / 2; 477 else 478 val = temp * 500000 + 273150000; 479 480 return val; 481 } 482 483 static uint32_t 484 lmtemp_decode_ds75(const uint8_t *buf, int degc) 485 { 486 int temp; 487 488 /* 489 * Sign-extend the MSB byte, and add in the fractions of a 490 * degree contained in the LSB (precision 1/16th DegC). 491 */ 492 temp = (int8_t)buf[0]; 493 temp = (temp << 4) | ((buf[1] >> 4) & 0xf); 494 495 /* 496 * Conversion to C or uK is simple. 497 */ 498 if (degc) 499 return temp / 16; 500 else 501 return (temp * 62500 + 273150000); 502 } 503 504 static uint32_t 505 lmtemp_decode_lm77(const uint8_t *buf, int degc) 506 { 507 int temp; 508 uint32_t val; 509 510 /* 511 * Describe each bits of temperature registers on LM77. 512 * D15 - D12: Sign 513 * D11 - D3 : Bit8(MSB) - Bit0 514 */ 515 temp = (int8_t)buf[0]; 516 temp = (temp << 5) | ((buf[1] >> 3) & 0x1f); 517 518 /* Temp is given in 1/2 deg. C, we convert to C or uK. */ 519 if (degc) 520 val = temp / 2; 521 else 522 val = temp * 500000 + 273150000; 523 524 return val; 525 } 526 527 static void lmtemp_encode_lm75(const uint32_t val, uint8_t *buf, int degc) 528 { 529 int temp; 530 531 /* Convert from C or uK to register format */ 532 if (degc) 533 temp = val * 2; 534 else 535 temp = (val - 273150000) / 500000; 536 buf[0] = (temp >> 1) & 0xff; 537 buf[1] = (temp & 1) << 7; 538 } 539 540 static void lmtemp_encode_ds75(const uint32_t val, uint8_t *buf, int degc) 541 { 542 int temp; 543 544 /* Convert from C or uK to register format */ 545 if (degc) 546 temp = val * 16; 547 else 548 temp = (val - 273150000) / 62500; 549 buf[0] = (temp >> 4) & 0xff; 550 buf[1] = (temp & 0xf) << 4; 551 } 552 553 static void lmtemp_encode_lm77(const uint32_t val, uint8_t *buf, int degc) 554 { 555 int temp; 556 557 /* Convert from C or uK to register format */ 558 if (degc) 559 temp = val * 2; 560 else 561 temp = (val - 273150000) / 500000; 562 buf[0] = (temp >> 5) & 0xff; 563 buf[1] = (temp & 0x1f) << 3; 564 } 565 566 static void 567 lmtemp_setup_sysctl(struct lmtemp_softc *sc) 568 { 569 const struct sysctlnode *me = NULL, *node = NULL; 570 571 sysctl_createv(NULL, 0, NULL, &me, 572 CTLFLAG_READWRITE, 573 CTLTYPE_NODE, device_xname(sc->sc_dev), NULL, 574 NULL, 0, NULL, 0, 575 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 576 577 sysctl_createv(NULL, 0, NULL, &node, 578 CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 579 CTLTYPE_INT, "temp", "Threshold temperature", 580 sysctl_lm75_temp, 1, (void *)sc, 0, 581 CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL); 582 } 583 584 static int 585 sysctl_lm75_temp(SYSCTLFN_ARGS) 586 { 587 struct sysctlnode node = *rnode; 588 struct lmtemp_softc *sc = node.sysctl_data; 589 int temp; 590 591 if (newp) { 592 593 /* we're asked to write */ 594 node.sysctl_data = &sc->sc_tmax; 595 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { 596 597 temp = *(int *)node.sysctl_data; 598 sc->sc_tmax = temp; 599 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 600 lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT, 601 sc->sc_tmax - 5, 1); 602 lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, 603 sc->sc_tmax, 1); 604 iic_release_bus(sc->sc_tag, I2C_F_POLL); 605 606 /* Synchronise envsys - calls lmtemp_getlim_lm75() */ 607 sysmon_envsys_update_limits(sc->sc_sme, &sc->sc_sensor); 608 return 0; 609 } 610 return EINVAL; 611 } else { 612 613 node.sysctl_data = &sc->sc_tmax; 614 node.sysctl_size = 4; 615 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 616 } 617 618 return 0; 619 } 620 621 SYSCTL_SETUP(sysctl_lmtemp_setup, "sysctl lmtemp subtree setup") 622 { 623 624 sysctl_createv(NULL, 0, NULL, NULL, 625 CTLFLAG_PERMANENT, 626 CTLTYPE_NODE, "machdep", NULL, 627 NULL, 0, NULL, 0, 628 CTL_MACHDEP, CTL_EOL); 629 } 630 631 632