1 /* $NetBSD: sht4x.c,v 1.3 2022/03/30 00:06:50 pgoyette Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Brad Spencer <brad@anduin.eldar.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/cdefs.h> 20 __KERNEL_RCSID(0, "$NetBSD: sht4x.c,v 1.3 2022/03/30 00:06:50 pgoyette Exp $"); 21 22 /* 23 Driver for the Sensirion SHT40/SHT41/SHT45 24 */ 25 26 #include <sys/param.h> 27 #include <sys/systm.h> 28 #include <sys/kernel.h> 29 #include <sys/device.h> 30 #include <sys/module.h> 31 #include <sys/sysctl.h> 32 #include <sys/mutex.h> 33 34 #include <dev/sysmon/sysmonvar.h> 35 #include <dev/i2c/i2cvar.h> 36 #include <dev/i2c/sht4xreg.h> 37 #include <dev/i2c/sht4xvar.h> 38 39 40 static uint8_t sht4x_crc(uint8_t *, size_t); 41 static int sht4x_poke(i2c_tag_t, i2c_addr_t, bool); 42 static int sht4x_match(device_t, cfdata_t, void *); 43 static void sht4x_attach(device_t, device_t, void *); 44 static int sht4x_detach(device_t, int); 45 static void sht4x_refresh(struct sysmon_envsys *, envsys_data_t *); 46 static int sht4x_verify_sysctl(SYSCTLFN_ARGS); 47 static int sht4x_verify_sysctl_resolution(SYSCTLFN_ARGS); 48 static int sht4x_verify_sysctl_heateron(SYSCTLFN_ARGS); 49 static int sht4x_verify_sysctl_heatervalue(SYSCTLFN_ARGS); 50 static int sht4x_verify_sysctl_heaterpulse(SYSCTLFN_ARGS); 51 52 #define SHT4X_DEBUG 53 #ifdef SHT4X_DEBUG 54 #define DPRINTF(s, l, x) \ 55 do { \ 56 if (l <= s->sc_sht4xdebug) \ 57 printf x; \ 58 } while (/*CONSTCOND*/0) 59 #else 60 #define DPRINTF(s, l, x) 61 #endif 62 63 CFATTACH_DECL_NEW(sht4xtemp, sizeof(struct sht4x_sc), 64 sht4x_match, sht4x_attach, sht4x_detach, NULL); 65 66 static struct sht4x_sensor sht4x_sensors[] = { 67 { 68 .desc = "humidity", 69 .type = ENVSYS_SRELHUMIDITY, 70 }, 71 { 72 .desc = "temperature", 73 .type = ENVSYS_STEMP, 74 } 75 }; 76 77 /* The typical delays are documented in the datasheet for the chip. 78 There is no need to be very accurate with these, just rough estimates 79 will work fine. 80 */ 81 82 static struct sht4x_timing sht4x_timings[] = { 83 { 84 .cmd = SHT4X_READ_SERIAL, 85 .typicaldelay = 5000, 86 }, 87 { 88 .cmd = SHT4X_SOFT_RESET, 89 .typicaldelay = 1000, 90 }, 91 { 92 .cmd = SHT4X_MEASURE_HIGH_PRECISION, 93 .typicaldelay = 8000, 94 }, 95 { 96 .cmd = SHT4X_MEASURE_MEDIUM_PRECISION, 97 .typicaldelay = 4000, 98 }, 99 { 100 .cmd = SHT4X_MEASURE_LOW_PRECISION, 101 .typicaldelay = 2000, 102 }, 103 { 104 .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_1_S, 105 .typicaldelay = 1000000, 106 }, 107 { 108 .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_1_S, 109 .typicaldelay = 1000000, 110 }, 111 { 112 .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_1_S, 113 .typicaldelay = 1000000, 114 }, 115 { 116 .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_TENTH_S, 117 .typicaldelay = 100000, 118 }, 119 { 120 .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_TENTH_S, 121 .typicaldelay = 100000, 122 }, 123 { 124 .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_TENTH_S, 125 .typicaldelay = 100000, 126 } 127 }; 128 129 /* Used when the heater is not on to find the command to use for the 130 * measurement. 131 */ 132 133 static struct sht4x_resolution sht4x_resolutions[] = { 134 { 135 .text = "high", 136 .cmd = SHT4X_MEASURE_HIGH_PRECISION, 137 }, 138 { 139 .text = "medium", 140 .cmd = SHT4X_MEASURE_MEDIUM_PRECISION, 141 }, 142 { 143 .text = "low", 144 .cmd = SHT4X_MEASURE_LOW_PRECISION, 145 } 146 }; 147 148 static const char sht4x_resolution_names[] = 149 "high, medium, low"; 150 151 static struct sht4x_heaterpulse sht4x_heaterpulses[] = { 152 { 153 .length = "short", 154 }, 155 { 156 .length = "long", 157 } 158 }; 159 160 /* This is consulted when the heater is on for which command is to be 161 used for the measurement. 162 */ 163 164 static struct sht4x_heateron_command sht4x_heateron_commands[] = { 165 { 166 .heatervalue = 1, 167 .pulselength = "short", 168 .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_TENTH_S, 169 }, 170 { 171 .heatervalue = 2, 172 .pulselength = "short", 173 .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_TENTH_S, 174 }, 175 { 176 .heatervalue = 3, 177 .pulselength = "short", 178 .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_TENTH_S, 179 }, 180 { 181 .heatervalue = 1, 182 .pulselength = "long", 183 .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_1_S, 184 }, 185 { 186 .heatervalue = 2, 187 .pulselength = "long", 188 .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_1_S, 189 }, 190 { 191 .heatervalue = 3, 192 .pulselength = "long", 193 .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_1_S, 194 } 195 }; 196 197 static const char sht4x_heaterpulse_names[] = 198 "short, long"; 199 200 int 201 sht4x_verify_sysctl(SYSCTLFN_ARGS) 202 { 203 int error, t; 204 struct sysctlnode node; 205 206 node = *rnode; 207 t = *(int *)rnode->sysctl_data; 208 node.sysctl_data = &t; 209 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 210 if (error || newp == NULL) 211 return error; 212 213 if (t < 0) 214 return EINVAL; 215 216 *(int *)rnode->sysctl_data = t; 217 218 return 0; 219 } 220 221 /* None of the heater and resolutions sysctls change anything on the chip in 222 real time. The values set are used to send different commands depending on 223 how they are set up. 224 225 What this implies is that the chip could be reset and the driver would not care. 226 227 */ 228 229 int 230 sht4x_verify_sysctl_resolution(SYSCTLFN_ARGS) 231 { 232 char buf[SHT4X_RES_NAME]; 233 struct sht4x_sc *sc; 234 struct sysctlnode node; 235 int error = 0; 236 size_t i; 237 238 node = *rnode; 239 sc = node.sysctl_data; 240 (void) memcpy(buf, sc->sc_resolution, SHT4X_RES_NAME); 241 node.sysctl_data = buf; 242 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 243 if (error || newp == NULL) 244 return error; 245 246 for (i = 0; i < __arraycount(sht4x_resolutions); i++) { 247 if (strncmp(node.sysctl_data, sht4x_resolutions[i].text, 248 SHT4X_RES_NAME) == 0) { 249 break; 250 } 251 } 252 253 if (i == __arraycount(sht4x_resolutions)) 254 return EINVAL; 255 (void) memcpy(sc->sc_resolution, node.sysctl_data, SHT4X_RES_NAME); 256 257 return error; 258 } 259 260 int 261 sht4x_verify_sysctl_heateron(SYSCTLFN_ARGS) 262 { 263 int error; 264 bool t; 265 struct sht4x_sc *sc; 266 struct sysctlnode node; 267 268 node = *rnode; 269 sc = node.sysctl_data; 270 t = sc->sc_heateron; 271 node.sysctl_data = &t; 272 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 273 if (error || newp == NULL) 274 return error; 275 276 sc->sc_heateron = t; 277 278 return error; 279 } 280 281 int 282 sht4x_verify_sysctl_heatervalue(SYSCTLFN_ARGS) 283 { 284 int error = 0, t; 285 struct sht4x_sc *sc; 286 struct sysctlnode node; 287 288 node = *rnode; 289 sc = node.sysctl_data; 290 t = sc->sc_heaterval; 291 node.sysctl_data = &t; 292 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 293 if (error || newp == NULL) 294 return (error); 295 296 if (t < 1 || t > 3) 297 return (EINVAL); 298 299 sc->sc_heaterval = t; 300 301 return error; 302 } 303 304 int 305 sht4x_verify_sysctl_heaterpulse(SYSCTLFN_ARGS) 306 { 307 char buf[SHT4X_PULSE_NAME]; 308 struct sht4x_sc *sc; 309 struct sysctlnode node; 310 int error = 0; 311 size_t i; 312 313 node = *rnode; 314 sc = node.sysctl_data; 315 (void) memcpy(buf, sc->sc_heaterpulse, SHT4X_PULSE_NAME); 316 node.sysctl_data = buf; 317 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 318 if (error || newp == NULL) 319 return error; 320 321 for (i = 0; i < __arraycount(sht4x_heaterpulses); i++) { 322 if (strncmp(node.sysctl_data, sht4x_heaterpulses[i].length, 323 SHT4X_RES_NAME) == 0) { 324 break; 325 } 326 } 327 328 if (i == __arraycount(sht4x_heaterpulses)) 329 return EINVAL; 330 (void) memcpy(sc->sc_heaterpulse, node.sysctl_data, SHT4X_PULSE_NAME); 331 332 return error; 333 } 334 335 static int 336 sht4x_cmddelay(uint8_t cmd) 337 { 338 int r = -1; 339 340 for(int i = 0;i < __arraycount(sht4x_timings);i++) { 341 if (cmd == sht4x_timings[i].cmd) { 342 r = sht4x_timings[i].typicaldelay; 343 break; 344 } 345 } 346 347 if (r == -1) { 348 panic("Bad command look up in cmd delay: cmd: %d\n",cmd); 349 } 350 351 return r; 352 } 353 354 static int 355 sht4x_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t *cmd, 356 uint8_t clen, uint8_t *buf, size_t blen, int readattempts) 357 { 358 int error; 359 int cmddelay; 360 361 error = iic_exec(tag,I2C_OP_WRITE_WITH_STOP,addr,cmd,clen,NULL,0,0); 362 363 /* Every command returns something except for the soft reset 364 which returns nothing. This chip is also nice in that pretty 365 much every command that returns something does it in the same way. 366 */ 367 if (error == 0 && cmd[0] != SHT4X_SOFT_RESET) { 368 cmddelay = sht4x_cmddelay(cmd[0]); 369 delay(cmddelay); 370 371 for (int aint = 0; aint < readattempts; aint++) { 372 error = iic_exec(tag,I2C_OP_READ_WITH_STOP,addr,NULL,0,buf,blen,0); 373 if (error == 0) 374 break; 375 delay(1000); 376 } 377 } 378 379 return error; 380 } 381 382 static int 383 sht4x_cmdr(struct sht4x_sc *sc, uint8_t cmd, uint8_t *buf, size_t blen) 384 { 385 return sht4x_cmd(sc->sc_tag, sc->sc_addr, &cmd, 1, buf, blen, sc->sc_readattempts); 386 } 387 388 static uint8_t 389 sht4x_crc(uint8_t * data, size_t size) 390 { 391 uint8_t crc = 0xFF; 392 393 for (size_t i = 0; i < size; i++) { 394 crc ^= data[i]; 395 for (size_t j = 8; j > 0; j--) { 396 if (crc & 0x80) 397 crc = (crc << 1) ^ 0x131; 398 else 399 crc <<= 1; 400 } 401 } 402 return crc; 403 } 404 405 static int 406 sht4x_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug) 407 { 408 uint8_t reg = SHT4X_READ_SERIAL; 409 uint8_t buf[6]; 410 int error; 411 412 error = sht4x_cmd(tag, addr, ®, 1, buf, 6, 10); 413 if (matchdebug) { 414 printf("poke X 1: %d\n", error); 415 } 416 return error; 417 } 418 419 static int 420 sht4x_sysctl_init(struct sht4x_sc *sc) 421 { 422 int error; 423 const struct sysctlnode *cnode; 424 int sysctlroot_num; 425 426 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 427 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 428 SYSCTL_DESCR("sht4x controls"), NULL, 0, NULL, 0, CTL_HW, 429 CTL_CREATE, CTL_EOL)) != 0) 430 return error; 431 432 sysctlroot_num = cnode->sysctl_num; 433 434 #ifdef SHT4X_DEBUG 435 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 436 CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 437 SYSCTL_DESCR("Debug level"), sht4x_verify_sysctl, 0, 438 &sc->sc_sht4xdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 439 CTL_EOL)) != 0) 440 return error; 441 442 #endif 443 444 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 445 CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts", 446 SYSCTL_DESCR("The number of times to attempt to read the values"), 447 sht4x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW, 448 sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 449 return error; 450 451 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 452 CTLFLAG_READONLY, CTLTYPE_STRING, "resolutions", 453 SYSCTL_DESCR("Valid resolutions"), 0, 0, 454 __UNCONST(sht4x_resolution_names), 455 sizeof(sht4x_resolution_names) + 1, 456 CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 457 return error; 458 459 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 460 CTLFLAG_READWRITE, CTLTYPE_STRING, "resolution", 461 SYSCTL_DESCR("Resolution of RH and Temp"), 462 sht4x_verify_sysctl_resolution, 0, (void *) sc, 463 SHT4X_RES_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 464 return error; 465 466 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 467 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc", 468 SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc, 469 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 470 return error; 471 472 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 473 CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron", 474 SYSCTL_DESCR("Heater on"), sht4x_verify_sysctl_heateron, 0, 475 (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 476 return error; 477 478 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 479 CTLFLAG_READWRITE, CTLTYPE_INT, "heaterstrength", 480 SYSCTL_DESCR("Heater strength 1 to 3"), 481 sht4x_verify_sysctl_heatervalue, 0, (void *)sc, 0, CTL_HW, 482 sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 483 return error; 484 485 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 486 CTLFLAG_READONLY, CTLTYPE_STRING, "heaterpulses", 487 SYSCTL_DESCR("Valid heater pulse lengths"), 0, 0, 488 __UNCONST(sht4x_heaterpulse_names), 489 sizeof(sht4x_heaterpulse_names) + 1, 490 CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 491 return error; 492 493 if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode, 494 CTLFLAG_READWRITE, CTLTYPE_STRING, "heaterpulse", 495 SYSCTL_DESCR("Heater pulse length"), 496 sht4x_verify_sysctl_heaterpulse, 0, (void *) sc, 497 SHT4X_RES_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 498 return error; 499 return 0; 500 } 501 502 static int 503 sht4x_match(device_t parent, cfdata_t match, void *aux) 504 { 505 struct i2c_attach_args *ia = aux; 506 int error, match_result; 507 const bool matchdebug = false; 508 509 if (iic_use_direct_match(ia, match, NULL, &match_result)) 510 return match_result; 511 512 /* indirect config - check for configured address */ 513 if (ia->ia_addr != SHT4X_TYPICAL_ADDR) 514 return 0; 515 516 /* 517 * Check to see if something is really at this i2c address. This will 518 * keep phantom devices from appearing 519 */ 520 if (iic_acquire_bus(ia->ia_tag, 0) != 0) { 521 if (matchdebug) 522 printf("in match acquire bus failed\n"); 523 return 0; 524 } 525 526 error = sht4x_poke(ia->ia_tag, ia->ia_addr, matchdebug); 527 iic_release_bus(ia->ia_tag, 0); 528 529 return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0; 530 } 531 532 static void 533 sht4x_attach(device_t parent, device_t self, void *aux) 534 { 535 struct sht4x_sc *sc; 536 struct i2c_attach_args *ia; 537 int error, i; 538 int ecount = 0; 539 uint8_t buf[6]; 540 uint8_t sncrcpt1, sncrcpt2; 541 542 ia = aux; 543 sc = device_private(self); 544 545 sc->sc_dev = self; 546 sc->sc_tag = ia->ia_tag; 547 sc->sc_addr = ia->ia_addr; 548 sc->sc_sht4xdebug = 0; 549 strlcpy(sc->sc_resolution,"high",SHT4X_RES_NAME); 550 sc->sc_readattempts = 10; 551 sc->sc_ignorecrc = false; 552 sc->sc_heateron = false; 553 sc->sc_heaterval = 1; 554 strlcpy(sc->sc_heaterpulse,"short",SHT4X_PULSE_NAME); 555 sc->sc_sme = NULL; 556 557 aprint_normal("\n"); 558 559 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 560 sc->sc_numsensors = __arraycount(sht4x_sensors); 561 562 if ((sc->sc_sme = sysmon_envsys_create()) == NULL) { 563 aprint_error_dev(self, 564 "Unable to create sysmon structure\n"); 565 sc->sc_sme = NULL; 566 return; 567 } 568 if ((error = sht4x_sysctl_init(sc)) != 0) { 569 aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error); 570 goto out; 571 } 572 573 error = iic_acquire_bus(sc->sc_tag, 0); 574 if (error) { 575 aprint_error_dev(self, "Could not acquire iic bus: %d\n", 576 error); 577 goto out; 578 } 579 580 error = sht4x_cmdr(sc, SHT4X_SOFT_RESET, NULL, 0); 581 if (error != 0) 582 aprint_error_dev(self, "Reset failed: %d\n", error); 583 584 delay(1000); /* 1 ms max */ 585 586 error = sht4x_cmdr(sc, SHT4X_READ_SERIAL, buf, 6); 587 if (error) { 588 aprint_error_dev(self, "Failed to read serial number: %d\n", 589 error); 590 ecount++; 591 } 592 593 sncrcpt1 = sht4x_crc(&buf[0],2); 594 sncrcpt2 = sht4x_crc(&buf[3],2); 595 596 DPRINTF(sc, 2, ("%s: read serial number values: %02x%02x - %02x, %02x%02x - %02x ; %02x %02x\n", 597 device_xname(sc->sc_dev), buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], sncrcpt1, sncrcpt2)); 598 599 iic_release_bus(sc->sc_tag, 0); 600 if (error != 0) { 601 aprint_error_dev(self, "Unable to setup device\n"); 602 goto out; 603 } 604 605 for (i = 0; i < sc->sc_numsensors; i++) { 606 strlcpy(sc->sc_sensors[i].desc, sht4x_sensors[i].desc, 607 sizeof(sc->sc_sensors[i].desc)); 608 609 sc->sc_sensors[i].units = sht4x_sensors[i].type; 610 sc->sc_sensors[i].state = ENVSYS_SINVALID; 611 612 DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i, 613 sc->sc_sensors[i].desc)); 614 615 error = sysmon_envsys_sensor_attach(sc->sc_sme, 616 &sc->sc_sensors[i]); 617 if (error) { 618 aprint_error_dev(self, 619 "Unable to attach sensor %d: %d\n", i, error); 620 goto out; 621 } 622 } 623 624 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 625 sc->sc_sme->sme_cookie = sc; 626 sc->sc_sme->sme_refresh = sht4x_refresh; 627 628 DPRINTF(sc, 2, ("sht4x_attach: registering with envsys\n")); 629 630 if (sysmon_envsys_register(sc->sc_sme)) { 631 aprint_error_dev(self, 632 "unable to register with sysmon\n"); 633 sysmon_envsys_destroy(sc->sc_sme); 634 sc->sc_sme = NULL; 635 return; 636 } 637 638 /* There is no documented way to ask the chip what version it is. This 639 is likely fine as the only apparent difference is in how precise the 640 measurements will be. The actual conversation with the chip is 641 identical no matter which one you are talking to. 642 */ 643 644 aprint_normal_dev(self, "Sensirion SHT40/SHT41/SHT45, " 645 "Serial number: %02x%02x%02x%02x%s", 646 buf[0], buf[1], buf[3], buf[4], 647 (sncrcpt1 == buf[2] && sncrcpt2 == buf[5]) ? "\n" : " (bad crc)\n"); 648 return; 649 out: 650 sysmon_envsys_destroy(sc->sc_sme); 651 sc->sc_sme = NULL; 652 } 653 654 /* If you use the heater on this chip, there is no documented choice but to use 655 the highest precision. If the heater is not in use one may select different 656 precisions or repeatability for the measurement. 657 658 Further, if the heater is used, it will only be active during the measurement. 659 The use of the heater will add delay to the measurement as chip will not 660 return anything until the heater pulse time is over. 661 */ 662 663 static uint8_t 664 sht4x_compute_measure_command(char *resolution, bool heateron, 665 int heatervalue, char *heaterpulse) 666 { 667 int i; 668 uint8_t r; 669 670 if (heateron == false) { 671 for (i = 0; i < __arraycount(sht4x_resolutions); i++) { 672 if (strncmp(resolution, sht4x_resolutions[i].text, 673 SHT4X_RES_NAME) == 0) { 674 r = sht4x_resolutions[i].cmd; 675 break; 676 } 677 } 678 679 if (i == __arraycount(sht4x_resolutions)) 680 panic("Heater off could not find command for resolution: %s\n",resolution); 681 } else { 682 for (i = 0; i < __arraycount(sht4x_heateron_commands); i++) { 683 if (heatervalue == sht4x_heateron_commands[i].heatervalue && 684 strncmp(heaterpulse, sht4x_heateron_commands[i].pulselength, 685 SHT4X_PULSE_NAME) == 0) { 686 r = sht4x_heateron_commands[i].cmd; 687 break; 688 } 689 } 690 691 if (i == __arraycount(sht4x_heateron_commands)) 692 panic("Heater on could not find command for heatervalue, heaterpulse: %d %s\n", 693 heatervalue,heaterpulse); 694 } 695 696 return r; 697 } 698 699 static void 700 sht4x_refresh(struct sysmon_envsys * sme, envsys_data_t * edata) 701 { 702 struct sht4x_sc *sc; 703 sc = sme->sme_cookie; 704 int error; 705 uint8_t rawdata[6]; 706 uint8_t measurement_command; 707 edata->state = ENVSYS_SINVALID; 708 709 mutex_enter(&sc->sc_mutex); 710 error = iic_acquire_bus(sc->sc_tag, 0); 711 if (error) { 712 DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", 713 device_xname(sc->sc_dev), error)); 714 goto out; 715 } 716 717 /* 718 The documented conversion calculations for the raw values are as follows: 719 720 %RH = (-6 + 125 * rawvalue / 65535) 721 722 T in Celsius = (-45 + 175 * rawvalue / 65535) 723 724 It follows then: 725 726 T in Kelvin = (228.15 + 175 * rawvalue / 65535) 727 728 given the relationship between Celsius and Kelvin. 729 730 What follows reorders the calculation a bit and scales it up to avoid 731 the use of any floating point. All that would really have to happen 732 is a scale up to 10^6 for the sysenv framework, which wants 733 temperature in micro-kelvin and percent relative humidity scaled up 734 10^6, but since this conversion uses 64 bits due to intermediate 735 values that are bigger than 32 bits the conversion first scales up to 736 10^9 and the scales back down by 10^3 at the end. This preserves some 737 precision in the conversion that would otherwise be lost. 738 */ 739 740 measurement_command = sht4x_compute_measure_command(sc->sc_resolution, 741 sc->sc_heateron, sc->sc_heaterval, sc->sc_heaterpulse); 742 DPRINTF(sc, 2, ("%s: Measurement command: %02x\n", 743 device_xname(sc->sc_dev), measurement_command)); 744 745 /* This chip is pretty nice in that all commands are the same length and 746 return the same result. What is not so nice is that you can not ask 747 for temperature and humidity independently. 748 749 The result will be 16 bits of raw temperature and a CRC byte followed 750 by 16 bits of humidity followed by a CRC byte. 751 */ 752 753 error = sht4x_cmdr(sc,measurement_command,rawdata,6); 754 755 if (error == 0) { 756 DPRINTF(sc, 2, ("%s: Raw data: %02x%02x %02x - %02x%02x %02x\n", 757 device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2], 758 rawdata[3], rawdata[4], rawdata[5])); 759 760 761 uint8_t *svalptr; 762 uint64_t svalue; 763 int64_t v1; 764 uint64_t v2; 765 uint64_t d1 = 65535; 766 uint64_t mul1; 767 uint64_t mul2; 768 uint64_t div1 = 10000; 769 uint64_t q; 770 771 switch (edata->sensor) { 772 case SHT4X_TEMP_SENSOR: 773 svalptr = &rawdata[0]; 774 v1 = 22815; /* this is scaled up already from 228.15 */ 775 v2 = 175; 776 mul1 = 10000000000; 777 mul2 = 100000000; 778 break; 779 case SHT4X_HUMIDITY_SENSOR: 780 svalptr = &rawdata[3]; 781 v1 = -6; 782 v2 = 125; 783 mul1 = 10000000000; 784 mul2 = 10000000000; 785 break; 786 default: 787 error = EINVAL; 788 break; 789 } 790 791 if (error == 0) { 792 uint8_t testcrc; 793 794 /* Fake out the CRC check if being asked to ignore CRC */ 795 if (sc->sc_ignorecrc) { 796 testcrc = *(svalptr + 2); 797 } else { 798 testcrc = sht4x_crc(svalptr,2); 799 } 800 801 if (*(svalptr + 2) == testcrc) { 802 svalue = *svalptr << 8 | *(svalptr + 1); 803 DPRINTF(sc, 2, ("%s: Raw sensor 16 bit: %#jx\n", 804 device_xname(sc->sc_dev), (uintmax_t)svalue)); 805 806 /* Scale up */ 807 svalue = svalue * mul1; 808 v1 = v1 * mul2; 809 /* Perform the conversion */ 810 q = ((v2 * (svalue / d1)) + v1) / div1; 811 812 DPRINTF(sc, 2, ("%s: Computed sensor: %#jx\n", 813 device_xname(sc->sc_dev), (uintmax_t)q)); 814 /* The results will fit in 32 bits, so nothing will be lost */ 815 edata->value_cur = (uint32_t) q; 816 edata->state = ENVSYS_SVALID; 817 } else { 818 error = EINVAL; 819 } 820 } 821 } 822 823 if (error) { 824 DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d\n", 825 device_xname(sc->sc_dev), error)); 826 } 827 828 iic_release_bus(sc->sc_tag, 0); 829 out: 830 mutex_exit(&sc->sc_mutex); 831 } 832 833 static int 834 sht4x_detach(device_t self, int flags) 835 { 836 struct sht4x_sc *sc; 837 838 sc = device_private(self); 839 840 mutex_enter(&sc->sc_mutex); 841 842 /* Remove the sensors */ 843 if (sc->sc_sme != NULL) { 844 sysmon_envsys_unregister(sc->sc_sme); 845 sc->sc_sme = NULL; 846 } 847 mutex_exit(&sc->sc_mutex); 848 849 /* Remove the sysctl tree */ 850 sysctl_teardown(&sc->sc_sht4xlog); 851 852 /* Remove the mutex */ 853 mutex_destroy(&sc->sc_mutex); 854 855 return 0; 856 } 857 858 MODULE(MODULE_CLASS_DRIVER, sht4xtemp, "iic,sysmon_envsys"); 859 860 #ifdef _MODULE 861 #include "ioconf.c" 862 #endif 863 864 static int 865 sht4xtemp_modcmd(modcmd_t cmd, void *opaque) 866 { 867 868 switch (cmd) { 869 case MODULE_CMD_INIT: 870 #ifdef _MODULE 871 return config_init_component(cfdriver_ioconf_sht4xtemp, 872 cfattach_ioconf_sht4xtemp, cfdata_ioconf_sht4xtemp); 873 #else 874 return 0; 875 #endif 876 case MODULE_CMD_FINI: 877 #ifdef _MODULE 878 return config_fini_component(cfdriver_ioconf_sht4xtemp, 879 cfattach_ioconf_sht4xtemp, cfdata_ioconf_sht4xtemp); 880 #else 881 return 0; 882 #endif 883 default: 884 return ENOTTY; 885 } 886 } 887