1 1.4 brad 2 1.10 brad /* $NetBSD: sht3x.c,v 1.10 2025/01/23 19:14:46 brad Exp $ */ 3 1.1 brad 4 1.1 brad /* 5 1.1 brad * Copyright (c) 2021 Brad Spencer <brad (at) anduin.eldar.org> 6 1.1 brad * 7 1.1 brad * Permission to use, copy, modify, and distribute this software for any 8 1.1 brad * purpose with or without fee is hereby granted, provided that the above 9 1.1 brad * copyright notice and this permission notice appear in all copies. 10 1.1 brad * 11 1.1 brad * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 1.1 brad * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 1.1 brad * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 1.1 brad * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 1.1 brad * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 1.1 brad * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 1.1 brad * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 1.1 brad */ 19 1.1 brad 20 1.1 brad #include <sys/cdefs.h> 21 1.10 brad __KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.10 2025/01/23 19:14:46 brad Exp $"); 22 1.1 brad 23 1.1 brad /* 24 1.1 brad Driver for the Sensirion SHT30/SHT31/SHT35 25 1.1 brad */ 26 1.1 brad 27 1.1 brad #include <sys/param.h> 28 1.1 brad #include <sys/systm.h> 29 1.1 brad #include <sys/kernel.h> 30 1.1 brad #include <sys/device.h> 31 1.1 brad #include <sys/module.h> 32 1.1 brad #include <sys/conf.h> 33 1.1 brad #include <sys/sysctl.h> 34 1.1 brad #include <sys/mutex.h> 35 1.1 brad #include <sys/condvar.h> 36 1.1 brad #include <sys/kthread.h> 37 1.1 brad #include <sys/pool.h> 38 1.1 brad #include <sys/kmem.h> 39 1.1 brad 40 1.1 brad #include <dev/sysmon/sysmonvar.h> 41 1.1 brad #include <dev/i2c/i2cvar.h> 42 1.1 brad #include <dev/i2c/sht3xreg.h> 43 1.1 brad #include <dev/i2c/sht3xvar.h> 44 1.1 brad 45 1.1 brad static int sht3x_take_break(void *, bool); 46 1.1 brad static int sht3x_get_status_register(void *, uint16_t *, bool); 47 1.1 brad static int sht3x_clear_status_register(void *, bool); 48 1.1 brad static uint8_t sht3x_crc(uint8_t *, size_t); 49 1.1 brad static int sht3x_cmdr(struct sht3x_sc *, uint16_t, uint8_t *, size_t); 50 1.1 brad static int sht3x_poke(i2c_tag_t, i2c_addr_t, bool); 51 1.1 brad static int sht3x_match(device_t, cfdata_t, void *); 52 1.1 brad static void sht3x_attach(device_t, device_t, void *); 53 1.1 brad static int sht3x_detach(device_t, int); 54 1.1 brad static void sht3x_refresh(struct sysmon_envsys *, envsys_data_t *); 55 1.1 brad static int sht3x_verify_sysctl(SYSCTLFN_ARGS); 56 1.1 brad static int sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS); 57 1.1 brad static int sht3x_verify_sysctl_modes(SYSCTLFN_ARGS); 58 1.1 brad static int sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS); 59 1.1 brad static int sht3x_verify_sysctl_rate(SYSCTLFN_ARGS); 60 1.1 brad static int sht3x_set_heater(struct sht3x_sc *); 61 1.1 brad static void sht3x_thread(void *); 62 1.1 brad static int sht3x_init_periodic_measurement(void *, int *); 63 1.1 brad static void sht3x_take_periodic_measurement(void *); 64 1.1 brad static void sht3x_start_thread(void *); 65 1.1 brad static void sht3x_stop_thread(void *); 66 1.1 brad static int sht3x_activate(device_t, enum devact); 67 1.1 brad 68 1.1 brad #define SHT3X_DEBUG 69 1.1 brad #ifdef SHT3X_DEBUG 70 1.1 brad #define DPRINTF(s, l, x) \ 71 1.1 brad do { \ 72 1.1 brad if (l <= s->sc_sht3xdebug) \ 73 1.1 brad printf x; \ 74 1.1 brad } while (/*CONSTCOND*/0) 75 1.1 brad #else 76 1.1 brad #define DPRINTF(s, l, x) 77 1.1 brad #endif 78 1.1 brad 79 1.1 brad CFATTACH_DECL_NEW(sht3xtemp, sizeof(struct sht3x_sc), 80 1.1 brad sht3x_match, sht3x_attach, sht3x_detach, sht3x_activate); 81 1.1 brad 82 1.1 brad extern struct cfdriver sht3xtemp_cd; 83 1.1 brad 84 1.1 brad static dev_type_open(sht3xopen); 85 1.1 brad static dev_type_read(sht3xread); 86 1.1 brad static dev_type_close(sht3xclose); 87 1.1 brad const struct cdevsw sht3x_cdevsw = { 88 1.1 brad .d_open = sht3xopen, 89 1.1 brad .d_close = sht3xclose, 90 1.1 brad .d_read = sht3xread, 91 1.1 brad .d_write = nowrite, 92 1.1 brad .d_ioctl = noioctl, 93 1.1 brad .d_stop = nostop, 94 1.1 brad .d_tty = notty, 95 1.1 brad .d_poll = nopoll, 96 1.1 brad .d_mmap = nommap, 97 1.1 brad .d_kqfilter = nokqfilter, 98 1.1 brad .d_discard = nodiscard, 99 1.1 brad .d_flag = D_OTHER 100 1.1 brad }; 101 1.1 brad 102 1.1 brad static struct sht3x_sensor sht3x_sensors[] = { 103 1.1 brad { 104 1.1 brad .desc = "humidity", 105 1.1 brad .type = ENVSYS_SRELHUMIDITY, 106 1.1 brad }, 107 1.1 brad { 108 1.1 brad .desc = "temperature", 109 1.1 brad .type = ENVSYS_STEMP, 110 1.1 brad } 111 1.1 brad }; 112 1.1 brad 113 1.1 brad /* The typical delays are MOSTLY documented in the datasheet for the chip. 114 1.1 brad There is no need to be very accurate with these, just rough estimates 115 1.1 brad will work fine. 116 1.1 brad */ 117 1.1 brad 118 1.1 brad static struct sht3x_timing sht3x_timings[] = { 119 1.1 brad { 120 1.1 brad .cmd = SHT3X_SOFT_RESET, 121 1.1 brad .typicaldelay = 3000, 122 1.1 brad }, 123 1.1 brad { 124 1.1 brad .cmd = SHT3X_GET_STATUS_REGISTER, 125 1.1 brad .typicaldelay = 100, 126 1.1 brad }, 127 1.1 brad { 128 1.1 brad .cmd = SHT3X_BREAK, 129 1.1 brad .typicaldelay = 100, 130 1.1 brad }, 131 1.1 brad { 132 1.1 brad .cmd = SHT3X_CLEAR_STATUS_REGISTER, 133 1.1 brad .typicaldelay = 100, 134 1.1 brad }, 135 1.1 brad { 136 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_CS_HIGH, 137 1.1 brad .typicaldelay = 15000, 138 1.1 brad }, 139 1.1 brad { 140 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM, 141 1.1 brad .typicaldelay = 6000, 142 1.1 brad }, 143 1.1 brad { 144 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_CS_LOW, 145 1.1 brad .typicaldelay = 4000, 146 1.1 brad }, 147 1.1 brad { 148 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH, 149 1.1 brad .typicaldelay = 15000, 150 1.1 brad }, 151 1.1 brad { 152 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM, 153 1.1 brad .typicaldelay = 6000, 154 1.1 brad }, 155 1.1 brad { 156 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW, 157 1.1 brad .typicaldelay = 4000, 158 1.1 brad }, 159 1.1 brad { 160 1.1 brad .cmd = SHT3X_WRITE_HIGH_ALERT_SET, 161 1.1 brad .typicaldelay = 5000, 162 1.1 brad }, 163 1.1 brad { 164 1.1 brad .cmd = SHT3X_WRITE_HIGH_ALERT_CLEAR, 165 1.1 brad .typicaldelay = 5000, 166 1.1 brad }, 167 1.1 brad { 168 1.1 brad .cmd = SHT3X_WRITE_LOW_ALERT_SET, 169 1.1 brad .typicaldelay = 5000, 170 1.1 brad }, 171 1.1 brad { 172 1.1 brad .cmd = SHT3X_WRITE_LOW_ALERT_CLEAR, 173 1.1 brad .typicaldelay = 5000, 174 1.8 brad }, 175 1.8 brad { 176 1.8 brad .cmd = SHT3X_READ_SERIAL_NUMBER, 177 1.8 brad .typicaldelay = 500, 178 1.1 brad } 179 1.1 brad }; 180 1.1 brad 181 1.1 brad /* In single shot mode, find the command */ 182 1.1 brad 183 1.1 brad static struct sht3x_repeatability sht3x_repeatability_ss[] = { 184 1.1 brad { 185 1.1 brad .text = "high", 186 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH, 187 1.10 brad .cscmd = SHT3X_MEASURE_REPEATABILITY_CS_HIGH, 188 1.1 brad }, 189 1.1 brad { 190 1.1 brad .text = "medium", 191 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM, 192 1.10 brad .cscmd = SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM, 193 1.1 brad }, 194 1.1 brad { 195 1.1 brad .text = "low", 196 1.1 brad .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW, 197 1.10 brad .cscmd = SHT3X_MEASURE_REPEATABILITY_CS_LOW, 198 1.1 brad } 199 1.1 brad }; 200 1.1 brad 201 1.1 brad 202 1.1 brad /* For periodic, look at the repeatability and the rate. 203 1.1 brad * ART is a bit fake here, as the repeatability is not really 204 1.1 brad * used. 205 1.1 brad */ 206 1.1 brad 207 1.1 brad static struct sht3x_periodic sht3x_periodic_rate[] = { 208 1.1 brad { 209 1.1 brad .repeatability = "high", 210 1.1 brad .rate = "0.5mps", 211 1.1 brad .sdelay = 1000, 212 1.1 brad .cmd = SHT3X_HALF_MPS_HIGH, 213 1.1 brad }, 214 1.1 brad { 215 1.1 brad .repeatability = "medium", 216 1.1 brad .rate = "0.5mps", 217 1.1 brad .sdelay = 1000, 218 1.1 brad .cmd = SHT3X_HALF_MPS_MEDIUM, 219 1.1 brad }, 220 1.1 brad { 221 1.1 brad .repeatability = "low", 222 1.1 brad .rate = "0.5mps", 223 1.1 brad .sdelay = 1000, 224 1.1 brad .cmd = SHT3X_HALF_MPS_LOW, 225 1.1 brad }, 226 1.1 brad { 227 1.1 brad .repeatability = "high", 228 1.1 brad .rate = "1.0mps", 229 1.1 brad .sdelay = 500, 230 1.1 brad .cmd = SHT3X_ONE_MPS_HIGH, 231 1.1 brad }, 232 1.1 brad { 233 1.1 brad .repeatability = "medium", 234 1.1 brad .rate = "1.0mps", 235 1.1 brad .sdelay = 500, 236 1.1 brad .cmd = SHT3X_ONE_MPS_MEDIUM, 237 1.1 brad }, 238 1.1 brad { 239 1.1 brad .repeatability = "low", 240 1.1 brad .rate = "1.0mps", 241 1.1 brad .sdelay = 500, 242 1.1 brad .cmd = SHT3X_ONE_MPS_LOW, 243 1.1 brad }, 244 1.1 brad { 245 1.1 brad .repeatability = "high", 246 1.1 brad .rate = "2.0mps", 247 1.1 brad .sdelay = 250, 248 1.1 brad .cmd = SHT3X_TWO_MPS_HIGH, 249 1.1 brad }, 250 1.1 brad { 251 1.1 brad .repeatability = "medium", 252 1.1 brad .rate = "2.0mps", 253 1.1 brad .sdelay = 250, 254 1.1 brad .cmd = SHT3X_TWO_MPS_MEDIUM, 255 1.1 brad }, 256 1.1 brad { 257 1.1 brad .repeatability = "low", 258 1.1 brad .rate = "2.0mps", 259 1.1 brad .sdelay = 250, 260 1.1 brad .cmd = SHT3X_TWO_MPS_LOW, 261 1.1 brad }, 262 1.1 brad { 263 1.1 brad .repeatability = "high", 264 1.1 brad .rate = "4.0mps", 265 1.1 brad .sdelay = 100, 266 1.1 brad .cmd = SHT3X_FOUR_MPS_HIGH, 267 1.1 brad }, 268 1.1 brad { 269 1.1 brad .repeatability = "medium", 270 1.1 brad .rate = "4.0mps", 271 1.1 brad .sdelay = 100, 272 1.1 brad .cmd = SHT3X_FOUR_MPS_MEDIUM, 273 1.1 brad }, 274 1.1 brad { 275 1.1 brad .repeatability = "low", 276 1.1 brad .rate = "4.0mps", 277 1.1 brad .sdelay = 100, 278 1.1 brad .cmd = SHT3X_FOUR_MPS_LOW, 279 1.1 brad }, 280 1.1 brad { 281 1.1 brad .repeatability = "high", 282 1.1 brad .rate = "10.0mps", 283 1.1 brad .sdelay = 50, 284 1.1 brad .cmd = SHT3X_TEN_MPS_HIGH, 285 1.1 brad }, 286 1.1 brad { 287 1.1 brad .repeatability = "medium", 288 1.1 brad .rate = "10.0mps", 289 1.1 brad .sdelay = 50, 290 1.1 brad .cmd = SHT3X_FOUR_MPS_MEDIUM, 291 1.1 brad }, 292 1.1 brad { 293 1.1 brad .repeatability = "low", 294 1.1 brad .rate = "10.0mps", 295 1.1 brad .sdelay = 50, 296 1.1 brad .cmd = SHT3X_FOUR_MPS_LOW, 297 1.1 brad }, 298 1.1 brad { 299 1.1 brad .repeatability = "high", 300 1.1 brad .rate = "ART", 301 1.1 brad .sdelay = 100, 302 1.1 brad .cmd = SHT3X_ART_ENABLE, 303 1.1 brad }, 304 1.1 brad { 305 1.1 brad .repeatability = "medium", 306 1.1 brad .rate = "ART", 307 1.1 brad .sdelay = 100, 308 1.1 brad .cmd = SHT3X_ART_ENABLE, 309 1.1 brad }, 310 1.1 brad { 311 1.1 brad .repeatability = "low", 312 1.1 brad .rate = "ART", 313 1.1 brad .sdelay = 100, 314 1.1 brad .cmd = SHT3X_ART_ENABLE, 315 1.1 brad } 316 1.1 brad }; 317 1.1 brad 318 1.1 brad static const char sht3x_rate_names[] = 319 1.1 brad "0.5mps, 1.0mps, 2.0mps, 4.0mps, 10.0mps, ART"; 320 1.1 brad 321 1.1 brad static const char sht3x_mode_names[] = 322 1.1 brad "single-shot, periodic"; 323 1.1 brad 324 1.1 brad static const char sht3x_repeatability_names[] = 325 1.1 brad "high, medium, low"; 326 1.1 brad 327 1.1 brad static int 328 1.1 brad sht3x_take_break(void *aux, bool have_bus) 329 1.1 brad { 330 1.1 brad struct sht3x_sc *sc; 331 1.1 brad sc = aux; 332 1.1 brad int error = 0; 333 1.1 brad 334 1.1 brad if (! have_bus) { 335 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 336 1.1 brad if (error) { 337 1.2 christos DPRINTF(sc, 2, ("%s: Could not acquire iic bus for " 338 1.2 christos "breaking %d\n", device_xname(sc->sc_dev), error)); 339 1.1 brad goto out; 340 1.1 brad } 341 1.1 brad } 342 1.1 brad error = sht3x_cmdr(sc, SHT3X_BREAK, NULL, 0); 343 1.1 brad if (error) { 344 1.1 brad DPRINTF(sc, 2, ("%s: Error breaking: %d\n", 345 1.1 brad device_xname(sc->sc_dev), error)); 346 1.1 brad } 347 1.2 christos out: 348 1.1 brad if (! have_bus) { 349 1.1 brad iic_release_bus(sc->sc_tag, 0); 350 1.1 brad } 351 1.1 brad 352 1.1 brad sc->sc_isperiodic = false; 353 1.2 christos strlcpy(sc->sc_mode, "single-shot", SHT3X_MODE_NAME); 354 1.1 brad 355 1.1 brad return error; 356 1.1 brad } 357 1.1 brad 358 1.1 brad static int 359 1.1 brad sht3x_get_status_register(void *aux, uint16_t *reg, bool have_bus) 360 1.1 brad { 361 1.2 christos struct sht3x_sc *sc = aux; 362 1.1 brad uint8_t buf[3]; 363 1.2 christos int error; 364 1.1 brad 365 1.1 brad if (! have_bus) { 366 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 367 1.1 brad if (error) { 368 1.2 christos DPRINTF(sc, 2, ("%s: Could not acquire iic bus for " 369 1.2 christos "getting status %d\n", device_xname(sc->sc_dev), 370 1.2 christos error)); 371 1.2 christos return error; 372 1.1 brad } 373 1.1 brad } 374 1.1 brad error = sht3x_cmdr(sc, SHT3X_GET_STATUS_REGISTER, buf, 3); 375 1.1 brad if (error) { 376 1.1 brad DPRINTF(sc, 2, ("%s: Error getting status: %d\n", 377 1.1 brad device_xname(sc->sc_dev), error)); 378 1.2 christos goto out; 379 1.1 brad } 380 1.2 christos 381 1.2 christos uint8_t c = sht3x_crc(&buf[0], 2); 382 1.2 christos if (c == buf[2]) { 383 1.2 christos *reg = buf[0] << 8 | buf[1]; 384 1.2 christos } else { 385 1.2 christos error = EINVAL; 386 1.2 christos } 387 1.2 christos out: 388 1.1 brad if (! have_bus) { 389 1.1 brad iic_release_bus(sc->sc_tag, 0); 390 1.1 brad } 391 1.1 brad 392 1.1 brad return error; 393 1.1 brad } 394 1.1 brad 395 1.1 brad static int 396 1.1 brad sht3x_clear_status_register(void *aux, bool have_bus) 397 1.1 brad { 398 1.2 christos struct sht3x_sc *sc = aux; 399 1.2 christos int error; 400 1.1 brad 401 1.1 brad if (! have_bus) { 402 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 403 1.1 brad if (error) { 404 1.2 christos DPRINTF(sc, 2, ("%s: Could not acquire iic bus for " 405 1.2 christos "clearing status %d\n", device_xname(sc->sc_dev), 406 1.2 christos error)); 407 1.2 christos return error; 408 1.1 brad } 409 1.1 brad } 410 1.1 brad error = sht3x_cmdr(sc, SHT3X_CLEAR_STATUS_REGISTER, NULL, 0); 411 1.1 brad if (error) { 412 1.1 brad DPRINTF(sc, 2, ("%s: Error clear status register: %d\n", 413 1.1 brad device_xname(sc->sc_dev), error)); 414 1.1 brad } 415 1.1 brad if (! have_bus) { 416 1.1 brad iic_release_bus(sc->sc_tag, 0); 417 1.1 brad } 418 1.1 brad 419 1.1 brad return error; 420 1.1 brad } 421 1.1 brad 422 1.1 brad void 423 1.1 brad sht3x_thread(void *aux) 424 1.1 brad { 425 1.1 brad struct sht3x_sc *sc = aux; 426 1.1 brad int error, rv; 427 1.1 brad int sdelay = 100; 428 1.1 brad 429 1.1 brad mutex_enter(&sc->sc_threadmutex); 430 1.1 brad 431 1.1 brad while (!sc->sc_stopping && !sc->sc_dying) { 432 1.1 brad if (sc->sc_initperiodic) { 433 1.2 christos error = sht3x_init_periodic_measurement(sc, &sdelay); 434 1.1 brad if (error) { 435 1.2 christos DPRINTF(sc, 2, ("%s: Error initing periodic " 436 1.2 christos "measurement in thread: %d\n", 437 1.2 christos device_xname(sc->sc_dev), error)); 438 1.1 brad } 439 1.1 brad sc->sc_initperiodic = false; 440 1.1 brad } 441 1.1 brad rv = cv_timedwait(&sc->sc_condvar, &sc->sc_threadmutex, 442 1.1 brad mstohz(sdelay)); 443 1.2 christos if (rv == EWOULDBLOCK && !sc->sc_stopping && 444 1.2 christos !sc->sc_initperiodic && !sc->sc_dying) { 445 1.1 brad sht3x_take_periodic_measurement(sc); 446 1.1 brad } 447 1.1 brad } 448 1.1 brad mutex_exit(&sc->sc_threadmutex); 449 1.1 brad kthread_exit(0); 450 1.1 brad } 451 1.1 brad 452 1.1 brad int 453 1.1 brad sht3x_init_periodic_measurement(void *aux, int *sdelay) 454 1.1 brad { 455 1.2 christos struct sht3x_sc *sc = aux; 456 1.2 christos size_t i; 457 1.2 christos int error; 458 1.2 christos uint16_t r; 459 1.1 brad 460 1.1 brad for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) { 461 1.2 christos if (strncmp(sc->sc_repeatability, 462 1.2 christos sht3x_periodic_rate[i].repeatability, SHT3X_REP_NAME) == 0 && 463 1.2 christos strncmp(sc->sc_periodic_rate, sht3x_periodic_rate[i].rate, 464 1.2 christos SHT3X_RATE_NAME) == 0) 465 1.2 christos { 466 1.1 brad r = sht3x_periodic_rate[i].cmd; 467 1.1 brad *sdelay = sht3x_periodic_rate[i].sdelay; 468 1.1 brad break; 469 1.1 brad } 470 1.1 brad } 471 1.1 brad 472 1.1 brad if (i == __arraycount(sht3x_periodic_rate)) { 473 1.1 brad *sdelay = 100; 474 1.2 christos return ENODEV; 475 1.1 brad } 476 1.1 brad 477 1.1 brad DPRINTF(sc, 2, ("%s: Would init with: %x\n", 478 1.1 brad device_xname(sc->sc_dev), r)); 479 1.1 brad 480 1.2 christos mutex_enter(&sc->sc_mutex); 481 1.2 christos 482 1.2 christos error = iic_acquire_bus(sc->sc_tag, 0); 483 1.2 christos if (error) { 484 1.2 christos DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: " 485 1.2 christos " %d\n", device_xname(sc->sc_dev), error)); 486 1.4 brad goto outm; 487 1.2 christos } 488 1.1 brad 489 1.2 christos error = sht3x_take_break(sc, true); 490 1.2 christos if (error) { 491 1.2 christos DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: " 492 1.2 christos " %d\n", device_xname(sc->sc_dev), error)); 493 1.2 christos goto out; 494 1.2 christos } 495 1.1 brad 496 1.2 christos error = sht3x_cmdr(sc, r, NULL, 0); 497 1.2 christos if (error) { 498 1.2 christos DPRINTF(sc, 2, 499 1.2 christos ("%s: Error sending periodic measurement command: %d\n", 500 1.2 christos device_xname(sc->sc_dev), error)); 501 1.2 christos goto out; 502 1.1 brad } 503 1.1 brad 504 1.2 christos sc->sc_isperiodic = true; 505 1.2 christos strlcpy(sc->sc_mode, "periodic", SHT3X_MODE_NAME); 506 1.2 christos 507 1.2 christos out: 508 1.2 christos iic_release_bus(sc->sc_tag, 0); 509 1.4 brad outm: 510 1.2 christos mutex_exit(&sc->sc_mutex); 511 1.1 brad return error; 512 1.1 brad } 513 1.1 brad 514 1.1 brad static void 515 1.1 brad sht3x_take_periodic_measurement(void *aux) 516 1.1 brad { 517 1.2 christos struct sht3x_sc *sc = aux; 518 1.2 christos int error; 519 1.1 brad struct sht3x_read_q *pp; 520 1.2 christos uint8_t rawbuf[MAX(sizeof(sc->sc_pbuffer), sizeof(pp->measurement))]; 521 1.2 christos uint16_t status_reg; 522 1.1 brad 523 1.1 brad mutex_enter(&sc->sc_mutex); 524 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 525 1.1 brad if (error) { 526 1.1 brad DPRINTF(sc, 2, ("%s: Could not acquire iic bus for getting " 527 1.1 brad "periodic data: %d\n", device_xname(sc->sc_dev), error)); 528 1.2 christos goto out; 529 1.2 christos } 530 1.2 christos 531 1.2 christos error = sht3x_get_status_register(sc, &status_reg, true); 532 1.2 christos if (error) { 533 1.2 christos DPRINTF(sc, 2, 534 1.2 christos ("%s: Error getting status register periodic: %d\n", 535 1.2 christos device_xname(sc->sc_dev), error)); 536 1.2 christos goto err; 537 1.2 christos } 538 1.2 christos 539 1.2 christos if (status_reg & SHT3X_RESET_DETECTED) { 540 1.2 christos aprint_error_dev(sc->sc_dev, "Reset detected in periodic mode. " 541 1.2 christos "Heater may have been reset.\n"); 542 1.2 christos delay(3000); 543 1.2 christos sht3x_take_break(sc, true); 544 1.2 christos sht3x_clear_status_register(sc, true); 545 1.2 christos sc->sc_heateron = status_reg & SHT3X_HEATER_STATUS; 546 1.2 christos sc->sc_initperiodic = true; 547 1.1 brad } else { 548 1.2 christos int data_error = sht3x_cmdr(sc, SHT3X_PERIODIC_FETCH_DATA, 549 1.2 christos rawbuf, sizeof(rawbuf)); 550 1.2 christos /* 551 1.2 christos * EIO is actually expected if the poll interval is faster 552 1.9 andvar * than the rate that the sensor is set to. Unfortunately, 553 1.2 christos * this will also mess with the ability to detect an actual 554 1.2 christos * problem with the sensor in periodic mode, so we do the best 555 1.2 christos * we can here. 556 1.2 christos */ 557 1.2 christos if (data_error) { 558 1.2 christos if (data_error != EIO) { 559 1.2 christos DPRINTF(sc, 2, ("%s: Error sending periodic " 560 1.2 christos "fetch command: %d\n", 561 1.2 christos device_xname(sc->sc_dev), data_error)); 562 1.1 brad } 563 1.2 christos goto err; 564 1.1 brad } 565 1.2 christos } 566 1.2 christos 567 1.2 christos iic_release_bus(sc->sc_tag, 0); 568 1.2 christos /* 569 1.2 christos * If there was no errors from anything then the data should be 570 1.2 christos * valid. 571 1.2 christos */ 572 1.2 christos DPRINTF(sc, 2, ("%s: Raw periodic: %x%x - %x -- %x%x - %x\n", 573 1.2 christos device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], rawbuf[2], 574 1.2 christos rawbuf[3], rawbuf[4], rawbuf[5])); 575 1.2 christos memcpy(sc->sc_pbuffer, rawbuf, sizeof(sc->sc_pbuffer)); 576 1.1 brad 577 1.2 christos if (sc->sc_opened) { 578 1.2 christos mutex_enter(&sc->sc_read_mutex); 579 1.2 christos pp = pool_cache_get(sc->sc_readpool, PR_NOWAIT); 580 1.2 christos if (pp == NULL) { 581 1.2 christos aprint_error_dev(sc->sc_dev, 582 1.2 christos "Could not allocate memory for pool read\n"); 583 1.1 brad } else { 584 1.2 christos memcpy(pp->measurement, rawbuf, sizeof(pp->measurement)); 585 1.2 christos DPRINTF(sc, 4, ("%s: Queue insert\n", 586 1.2 christos device_xname(sc->sc_dev))); 587 1.2 christos SIMPLEQ_INSERT_HEAD(&sc->sc_read_queue, pp, read_q); 588 1.1 brad } 589 1.2 christos cv_signal(&sc->sc_condreadready); 590 1.2 christos mutex_exit(&sc->sc_read_mutex); 591 1.1 brad } 592 1.2 christos out: 593 1.2 christos mutex_exit(&sc->sc_mutex); 594 1.2 christos return; 595 1.2 christos err: 596 1.2 christos /* 597 1.2 christos * We are only going to worry about errors when it was not related 598 1.2 christos * to actually getting data. That is a likely indicator of a problem 599 1.2 christos * with the sensor. 600 1.2 christos */ 601 1.2 christos DPRINTF(sc, 2, ("%s: Raw periodic with error: %x%x - %x -- " 602 1.2 christos "%x%x - %x -- %d\n", device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], 603 1.2 christos rawbuf[2], rawbuf[3], rawbuf[4], rawbuf[5], error)); 604 1.2 christos iic_release_bus(sc->sc_tag, 0); 605 1.4 brad if (error != 0) { 606 1.4 brad memcpy(sc->sc_pbuffer, "dedbef", sizeof(sc->sc_pbuffer)); 607 1.4 brad } 608 1.1 brad mutex_exit(&sc->sc_mutex); 609 1.1 brad } 610 1.1 brad 611 1.1 brad static void 612 1.1 brad sht3x_stop_thread(void *aux) 613 1.1 brad { 614 1.1 brad struct sht3x_sc *sc; 615 1.1 brad sc = aux; 616 1.1 brad 617 1.1 brad if (!sc->sc_isperiodic) { 618 1.1 brad return; 619 1.1 brad } 620 1.1 brad 621 1.1 brad mutex_enter(&sc->sc_threadmutex); 622 1.1 brad sc->sc_stopping = true; 623 1.1 brad cv_signal(&sc->sc_condvar); 624 1.1 brad mutex_exit(&sc->sc_threadmutex); 625 1.1 brad 626 1.1 brad /* wait for the thread to exit */ 627 1.1 brad kthread_join(sc->sc_thread); 628 1.1 brad 629 1.1 brad mutex_enter(&sc->sc_mutex); 630 1.1 brad sht3x_take_break(sc,false); 631 1.1 brad mutex_exit(&sc->sc_mutex); 632 1.1 brad } 633 1.1 brad 634 1.1 brad static void 635 1.1 brad sht3x_start_thread(void *aux) 636 1.1 brad { 637 1.1 brad struct sht3x_sc *sc; 638 1.1 brad sc = aux; 639 1.1 brad int error; 640 1.1 brad 641 1.1 brad error = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL, 642 1.1 brad sht3x_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev)); 643 1.1 brad if (error) { 644 1.1 brad DPRINTF(sc, 2, ("%s: Unable to create measurement thread: %d\n", 645 1.1 brad device_xname(sc->sc_dev), error)); 646 1.1 brad } 647 1.1 brad } 648 1.1 brad 649 1.1 brad int 650 1.1 brad sht3x_verify_sysctl(SYSCTLFN_ARGS) 651 1.1 brad { 652 1.1 brad int error, t; 653 1.1 brad struct sysctlnode node; 654 1.1 brad 655 1.1 brad node = *rnode; 656 1.1 brad t = *(int *)rnode->sysctl_data; 657 1.1 brad node.sysctl_data = &t; 658 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 659 1.1 brad if (error || newp == NULL) 660 1.1 brad return error; 661 1.1 brad 662 1.1 brad if (t < 0) 663 1.1 brad return EINVAL; 664 1.1 brad 665 1.1 brad *(int *)rnode->sysctl_data = t; 666 1.1 brad 667 1.1 brad return 0; 668 1.1 brad } 669 1.1 brad 670 1.1 brad int 671 1.1 brad sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS) 672 1.1 brad { 673 1.1 brad int error; 674 1.1 brad bool t; 675 1.1 brad struct sht3x_sc *sc; 676 1.1 brad struct sysctlnode node; 677 1.1 brad 678 1.1 brad node = *rnode; 679 1.1 brad sc = node.sysctl_data; 680 1.1 brad t = sc->sc_heateron; 681 1.1 brad node.sysctl_data = &t; 682 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 683 1.1 brad if (error || newp == NULL) 684 1.1 brad return error; 685 1.1 brad 686 1.1 brad sc->sc_heateron = t; 687 1.1 brad error = sht3x_set_heater(sc); 688 1.1 brad 689 1.1 brad return error; 690 1.1 brad } 691 1.1 brad 692 1.1 brad static int 693 1.1 brad sht3x_set_heater(struct sht3x_sc *sc) 694 1.1 brad { 695 1.1 brad int error = 0; 696 1.1 brad uint16_t cmd; 697 1.1 brad 698 1.1 brad mutex_enter(&sc->sc_mutex); 699 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 700 1.1 brad if (error) { 701 1.1 brad DPRINTF(sc, 2, ("%s:%s: Failed to acquire bus: %d\n", 702 1.1 brad device_xname(sc->sc_dev), __func__, error)); 703 1.2 christos goto out; 704 1.1 brad } 705 1.1 brad 706 1.1 brad if (sc->sc_heateron) { 707 1.1 brad cmd = SHT3X_HEATER_ENABLE; 708 1.1 brad } else { 709 1.1 brad cmd = SHT3X_HEATER_DISABLE; 710 1.1 brad } 711 1.1 brad 712 1.1 brad error = sht3x_cmdr(sc, cmd, NULL, 0); 713 1.1 brad 714 1.1 brad iic_release_bus(sc->sc_tag,0); 715 1.2 christos out: 716 1.1 brad mutex_exit(&sc->sc_mutex); 717 1.1 brad 718 1.1 brad return error; 719 1.1 brad } 720 1.1 brad 721 1.1 brad int 722 1.1 brad sht3x_verify_sysctl_modes(SYSCTLFN_ARGS) 723 1.1 brad { 724 1.1 brad char buf[SHT3X_MODE_NAME]; 725 1.1 brad struct sht3x_sc *sc; 726 1.1 brad struct sysctlnode node; 727 1.1 brad bool is_ss = false; 728 1.1 brad bool is_periodic = false; 729 1.2 christos int error; 730 1.1 brad 731 1.1 brad node = *rnode; 732 1.1 brad sc = node.sysctl_data; 733 1.1 brad (void) memcpy(buf, sc->sc_mode, SHT3X_MODE_NAME); 734 1.1 brad node.sysctl_data = buf; 735 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 736 1.1 brad if (error || newp == NULL) 737 1.1 brad return error; 738 1.1 brad 739 1.1 brad if (sc->sc_opened) { 740 1.1 brad return EINVAL; 741 1.1 brad } 742 1.1 brad 743 1.2 christos is_ss = strncmp(node.sysctl_data, "single-shot", SHT3X_MODE_NAME) == 0; 744 1.2 christos is_periodic = strncmp(node.sysctl_data, "periodic", SHT3X_MODE_NAME) 745 1.2 christos == 0; 746 1.1 brad 747 1.2 christos if (!is_ss && !is_periodic) { 748 1.2 christos return EINVAL; 749 1.2 christos } 750 1.2 christos 751 1.2 christos (void) memcpy(sc->sc_mode, node.sysctl_data, SHT3X_MODE_NAME); 752 1.2 christos if (is_ss) { 753 1.2 christos sht3x_stop_thread(sc); 754 1.2 christos sc->sc_stopping = false; 755 1.2 christos sc->sc_initperiodic = false; 756 1.2 christos sc->sc_isperiodic = false; 757 1.1 brad } 758 1.1 brad 759 1.2 christos if (is_periodic) { 760 1.2 christos sc->sc_stopping = false; 761 1.2 christos sc->sc_initperiodic = true; 762 1.2 christos sc->sc_isperiodic = true; 763 1.2 christos sht3x_start_thread(sc); 764 1.1 brad } 765 1.1 brad 766 1.2 christos return 0; 767 1.1 brad } 768 1.1 brad 769 1.1 brad int 770 1.1 brad sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS) 771 1.1 brad { 772 1.1 brad char buf[SHT3X_REP_NAME]; 773 1.1 brad struct sht3x_sc *sc; 774 1.1 brad struct sysctlnode node; 775 1.2 christos int error; 776 1.1 brad size_t i; 777 1.1 brad 778 1.1 brad node = *rnode; 779 1.1 brad sc = node.sysctl_data; 780 1.1 brad (void) memcpy(buf, sc->sc_repeatability, SHT3X_REP_NAME); 781 1.1 brad node.sysctl_data = buf; 782 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 783 1.1 brad if (error || newp == NULL) 784 1.1 brad return error; 785 1.1 brad 786 1.1 brad for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) { 787 1.1 brad if (strncmp(node.sysctl_data, sht3x_repeatability_ss[i].text, 788 1.1 brad SHT3X_REP_NAME) == 0) { 789 1.1 brad break; 790 1.1 brad } 791 1.1 brad } 792 1.1 brad 793 1.1 brad if (i == __arraycount(sht3x_repeatability_ss)) 794 1.1 brad return EINVAL; 795 1.1 brad (void) memcpy(sc->sc_repeatability, node.sysctl_data, SHT3X_REP_NAME); 796 1.1 brad 797 1.1 brad if (sc->sc_isperiodic) { 798 1.1 brad sc->sc_initperiodic = true; 799 1.1 brad } 800 1.1 brad 801 1.1 brad return error; 802 1.1 brad } 803 1.1 brad 804 1.1 brad int 805 1.1 brad sht3x_verify_sysctl_rate(SYSCTLFN_ARGS) 806 1.1 brad { 807 1.1 brad char buf[SHT3X_RATE_NAME]; 808 1.1 brad struct sht3x_sc *sc; 809 1.1 brad struct sysctlnode node; 810 1.2 christos int error; 811 1.1 brad size_t i; 812 1.1 brad 813 1.1 brad node = *rnode; 814 1.1 brad sc = node.sysctl_data; 815 1.1 brad (void) memcpy(buf, sc->sc_periodic_rate, SHT3X_RATE_NAME); 816 1.1 brad node.sysctl_data = buf; 817 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 818 1.1 brad if (error || newp == NULL) 819 1.1 brad return error; 820 1.1 brad 821 1.1 brad for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) { 822 1.1 brad if (strncmp(node.sysctl_data, sht3x_periodic_rate[i].rate, 823 1.1 brad SHT3X_RATE_NAME) == 0) { 824 1.1 brad break; 825 1.1 brad } 826 1.1 brad } 827 1.1 brad 828 1.1 brad if (i == __arraycount(sht3x_periodic_rate)) 829 1.1 brad return EINVAL; 830 1.2 christos 831 1.1 brad (void) memcpy(sc->sc_periodic_rate, node.sysctl_data, SHT3X_RATE_NAME); 832 1.1 brad 833 1.1 brad if (sc->sc_isperiodic) { 834 1.1 brad sc->sc_initperiodic = true; 835 1.1 brad } 836 1.1 brad 837 1.1 brad return error; 838 1.1 brad } 839 1.1 brad 840 1.1 brad static int 841 1.1 brad sht3x_cmddelay(uint16_t cmd) 842 1.1 brad { 843 1.2 christos size_t i; 844 1.1 brad 845 1.2 christos for (i = 0; i < __arraycount(sht3x_timings); i++) { 846 1.1 brad if (cmd == sht3x_timings[i].cmd) { 847 1.1 brad break; 848 1.1 brad } 849 1.1 brad } 850 1.1 brad 851 1.2 christos if (i == __arraycount(sht3x_timings)) { 852 1.2 christos return -1; 853 1.1 brad } 854 1.2 christos return sht3x_timings[i].typicaldelay; 855 1.1 brad } 856 1.1 brad 857 1.1 brad static int 858 1.1 brad sht3x_cmd(i2c_tag_t tag, i2c_addr_t addr, uint16_t *cmd, 859 1.1 brad uint8_t clen, uint8_t *buf, size_t blen, int readattempts) 860 1.1 brad { 861 1.1 brad int error; 862 1.1 brad int cmddelay; 863 1.1 brad uint8_t cmd8[2]; 864 1.1 brad 865 1.1 brad /* All commands are two bytes and must be in a proper order */ 866 1.1 brad KASSERT(clen == 2); 867 1.1 brad 868 1.1 brad cmd8[0] = cmd[0] >> 8; 869 1.1 brad cmd8[1] = cmd[0] & 0x00ff; 870 1.1 brad 871 1.10 brad if (cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_HIGH || 872 1.10 brad cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM || 873 1.10 brad cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_LOW) { 874 1.10 brad error = iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, &cmd8[0], clen, 875 1.10 brad buf, blen, 0); 876 1.10 brad } else { 877 1.10 brad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd8[0], clen, 878 1.10 brad NULL, 0, 0); 879 1.10 brad if (error) 880 1.10 brad return error; 881 1.2 christos 882 1.10 brad cmddelay = sht3x_cmddelay(cmd[0]); 883 1.10 brad if (cmddelay != -1) { 884 1.10 brad delay(cmddelay); 885 1.10 brad } 886 1.1 brad 887 1.10 brad /* Not all commands return anything */ 888 1.10 brad if (blen == 0) { 889 1.10 brad return 0; 890 1.10 brad } 891 1.1 brad 892 1.10 brad for (int aint = 0; aint < readattempts; aint++) { 893 1.10 brad error = iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0, buf, 894 1.10 brad blen, 0); 895 1.10 brad if (error == 0) 896 1.10 brad break; 897 1.10 brad delay(1000); 898 1.10 brad } 899 1.1 brad } 900 1.1 brad 901 1.1 brad return error; 902 1.1 brad } 903 1.1 brad 904 1.1 brad static int 905 1.1 brad sht3x_cmdr(struct sht3x_sc *sc, uint16_t cmd, uint8_t *buf, size_t blen) 906 1.1 brad { 907 1.2 christos return sht3x_cmd(sc->sc_tag, sc->sc_addr, &cmd, 2, buf, blen, 908 1.2 christos sc->sc_readattempts); 909 1.1 brad } 910 1.1 brad 911 1.1 brad static uint8_t 912 1.2 christos sht3x_crc(uint8_t *data, size_t size) 913 1.1 brad { 914 1.1 brad uint8_t crc = 0xFF; 915 1.1 brad 916 1.1 brad for (size_t i = 0; i < size; i++) { 917 1.1 brad crc ^= data[i]; 918 1.1 brad for (size_t j = 8; j > 0; j--) { 919 1.1 brad if (crc & 0x80) 920 1.1 brad crc = (crc << 1) ^ 0x31; 921 1.1 brad else 922 1.1 brad crc <<= 1; 923 1.1 brad } 924 1.1 brad } 925 1.1 brad return crc; 926 1.1 brad } 927 1.1 brad 928 1.1 brad static int 929 1.1 brad sht3x_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug) 930 1.1 brad { 931 1.1 brad uint16_t reg = SHT3X_GET_STATUS_REGISTER; 932 1.1 brad uint8_t buf[3]; 933 1.1 brad int error; 934 1.1 brad 935 1.1 brad error = sht3x_cmd(tag, addr, ®, 2, buf, 3, 10); 936 1.1 brad if (matchdebug) { 937 1.1 brad printf("poke X 1: %d\n", error); 938 1.1 brad } 939 1.1 brad return error; 940 1.1 brad } 941 1.1 brad 942 1.1 brad static int 943 1.1 brad sht3x_sysctl_init(struct sht3x_sc *sc) 944 1.1 brad { 945 1.1 brad int error; 946 1.1 brad const struct sysctlnode *cnode; 947 1.1 brad int sysctlroot_num; 948 1.1 brad 949 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 950 1.1 brad 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 951 1.1 brad SYSCTL_DESCR("sht3x controls"), NULL, 0, NULL, 0, CTL_HW, 952 1.1 brad CTL_CREATE, CTL_EOL)) != 0) 953 1.1 brad return error; 954 1.1 brad 955 1.1 brad sysctlroot_num = cnode->sysctl_num; 956 1.1 brad 957 1.1 brad #ifdef SHT3X_DEBUG 958 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 959 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 960 1.1 brad SYSCTL_DESCR("Debug level"), sht3x_verify_sysctl, 0, 961 1.1 brad &sc->sc_sht3xdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 962 1.1 brad CTL_EOL)) != 0) 963 1.1 brad return error; 964 1.1 brad 965 1.1 brad #endif 966 1.1 brad 967 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 968 1.10 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "clockstretch", 969 1.10 brad SYSCTL_DESCR("Use clock stretch commands for measurements"), NULL, 0, 970 1.10 brad &sc->sc_clockstretch, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 971 1.10 brad CTL_EOL)) != 0) 972 1.10 brad return error; 973 1.10 brad 974 1.10 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 975 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts", 976 1.1 brad SYSCTL_DESCR("The number of times to attempt to read the values"), 977 1.1 brad sht3x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW, 978 1.1 brad sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 979 1.1 brad return error; 980 1.1 brad 981 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 982 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "modes", 983 1.1 brad SYSCTL_DESCR("Valid modes"), 0, 0, 984 1.1 brad __UNCONST(sht3x_mode_names), 985 1.1 brad sizeof(sht3x_mode_names) + 1, 986 1.1 brad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 987 1.1 brad return error; 988 1.1 brad 989 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 990 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "mode", 991 1.1 brad SYSCTL_DESCR("Mode for measurement collection"), 992 1.1 brad sht3x_verify_sysctl_modes, 0, (void *) sc, 993 1.1 brad SHT3X_MODE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 994 1.1 brad return error; 995 1.1 brad 996 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 997 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "repeatabilities", 998 1.1 brad SYSCTL_DESCR("Valid repeatability values"), 0, 0, 999 1.1 brad __UNCONST(sht3x_repeatability_names), 1000 1.1 brad sizeof(sht3x_repeatability_names) + 1, 1001 1.1 brad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1002 1.1 brad return error; 1003 1.1 brad 1004 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 1005 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "repeatability", 1006 1.1 brad SYSCTL_DESCR("Repeatability of RH and Temp"), 1007 1.1 brad sht3x_verify_sysctl_repeatability, 0, (void *) sc, 1008 1.1 brad SHT3X_REP_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1009 1.1 brad return error; 1010 1.1 brad 1011 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 1012 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "rates", 1013 1.9 andvar SYSCTL_DESCR("Valid periodic rates"), 0, 0, 1014 1.1 brad __UNCONST(sht3x_rate_names), 1015 1.1 brad sizeof(sht3x_rate_names) + 1, 1016 1.1 brad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1017 1.1 brad return error; 1018 1.1 brad 1019 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 1020 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "rate", 1021 1.1 brad SYSCTL_DESCR("Rate for periodic measurements"), 1022 1.1 brad sht3x_verify_sysctl_rate, 0, (void *) sc, 1023 1.1 brad SHT3X_RATE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1024 1.1 brad return error; 1025 1.1 brad 1026 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 1027 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc", 1028 1.1 brad SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc, 1029 1.1 brad 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1030 1.1 brad return error; 1031 1.1 brad 1032 1.1 brad if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode, 1033 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron", 1034 1.1 brad SYSCTL_DESCR("Heater on"), sht3x_verify_sysctl_heateron, 0, 1035 1.1 brad (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1036 1.1 brad return error; 1037 1.1 brad 1038 1.1 brad return 0; 1039 1.1 brad } 1040 1.1 brad 1041 1.1 brad static int 1042 1.1 brad sht3x_match(device_t parent, cfdata_t match, void *aux) 1043 1.1 brad { 1044 1.1 brad struct i2c_attach_args *ia = aux; 1045 1.1 brad int error, match_result; 1046 1.1 brad const bool matchdebug = false; 1047 1.1 brad 1048 1.1 brad if (iic_use_direct_match(ia, match, NULL, &match_result)) 1049 1.1 brad return match_result; 1050 1.1 brad 1051 1.1 brad if (matchdebug) { 1052 1.1 brad printf("Looking at ia_addr: %x\n",ia->ia_addr); 1053 1.1 brad } 1054 1.1 brad 1055 1.1 brad /* indirect config - check for configured address */ 1056 1.2 christos if (ia->ia_addr != SHT3X_TYPICAL_ADDR_1 && 1057 1.2 christos ia->ia_addr != SHT3X_TYPICAL_ADDR_2) 1058 1.2 christos return 0; 1059 1.1 brad 1060 1.2 christos /* 1061 1.2 christos * Check to see if something is really at this i2c address. 1062 1.2 christos * This will keep phantom devices from appearing 1063 1.2 christos */ 1064 1.2 christos if (iic_acquire_bus(ia->ia_tag, 0) != 0) { 1065 1.2 christos if (matchdebug) 1066 1.2 christos printf("in match acquire bus failed\n"); 1067 1.1 brad return 0; 1068 1.1 brad } 1069 1.2 christos 1070 1.2 christos error = sht3x_poke(ia->ia_tag, ia->ia_addr, matchdebug); 1071 1.2 christos iic_release_bus(ia->ia_tag, 0); 1072 1.2 christos 1073 1.2 christos return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0; 1074 1.1 brad } 1075 1.1 brad 1076 1.1 brad static void 1077 1.1 brad sht3x_attach(device_t parent, device_t self, void *aux) 1078 1.1 brad { 1079 1.1 brad struct sht3x_sc *sc; 1080 1.1 brad struct i2c_attach_args *ia; 1081 1.1 brad int error, i; 1082 1.1 brad int ecount = 0; 1083 1.1 brad uint8_t buf[6]; 1084 1.1 brad uint32_t serialnumber; 1085 1.1 brad uint8_t sncrcpt1, sncrcpt2; 1086 1.1 brad 1087 1.1 brad ia = aux; 1088 1.1 brad sc = device_private(self); 1089 1.1 brad 1090 1.1 brad sc->sc_dev = self; 1091 1.1 brad sc->sc_tag = ia->ia_tag; 1092 1.1 brad sc->sc_addr = ia->ia_addr; 1093 1.1 brad sc->sc_sht3xdebug = 0; 1094 1.2 christos strlcpy(sc->sc_mode, "single-shot", SHT3X_MODE_NAME); 1095 1.1 brad sc->sc_isperiodic = false; 1096 1.2 christos strlcpy(sc->sc_repeatability, "high", SHT3X_REP_NAME); 1097 1.2 christos strlcpy(sc->sc_periodic_rate, "1.0mps", SHT3X_RATE_NAME); 1098 1.1 brad sc->sc_readattempts = 10; 1099 1.1 brad sc->sc_ignorecrc = false; 1100 1.1 brad sc->sc_heateron = false; 1101 1.1 brad sc->sc_sme = NULL; 1102 1.1 brad sc->sc_stopping = false; 1103 1.1 brad sc->sc_initperiodic = false; 1104 1.1 brad sc->sc_opened = false; 1105 1.10 brad sc->sc_clockstretch = false; 1106 1.1 brad sc->sc_dying = false; 1107 1.1 brad sc->sc_readpoolname = NULL; 1108 1.1 brad 1109 1.1 brad aprint_normal("\n"); 1110 1.1 brad 1111 1.1 brad mutex_init(&sc->sc_dying_mutex, MUTEX_DEFAULT, IPL_NONE); 1112 1.1 brad mutex_init(&sc->sc_read_mutex, MUTEX_DEFAULT, IPL_NONE); 1113 1.1 brad mutex_init(&sc->sc_threadmutex, MUTEX_DEFAULT, IPL_NONE); 1114 1.1 brad mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 1115 1.1 brad cv_init(&sc->sc_condvar, "sht3xcv"); 1116 1.1 brad cv_init(&sc->sc_condreadready, "sht3xread"); 1117 1.1 brad cv_init(&sc->sc_cond_dying, "sht3xdie"); 1118 1.1 brad sc->sc_numsensors = __arraycount(sht3x_sensors); 1119 1.1 brad 1120 1.1 brad if ((sc->sc_sme = sysmon_envsys_create()) == NULL) { 1121 1.1 brad aprint_error_dev(self, 1122 1.1 brad "Unable to create sysmon structure\n"); 1123 1.1 brad sc->sc_sme = NULL; 1124 1.1 brad return; 1125 1.1 brad } 1126 1.1 brad if ((error = sht3x_sysctl_init(sc)) != 0) { 1127 1.1 brad aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error); 1128 1.1 brad goto out; 1129 1.1 brad } 1130 1.1 brad 1131 1.1 brad sc->sc_readpoolname = kmem_asprintf("sht3xrp%d",device_unit(self)); 1132 1.2 christos sc->sc_readpool = pool_cache_init(sizeof(struct sht3x_read_q), 0, 0, 0, 1133 1.2 christos sc->sc_readpoolname, NULL, IPL_VM, NULL, NULL, NULL); 1134 1.1 brad pool_cache_sethiwat(sc->sc_readpool,100); 1135 1.1 brad 1136 1.1 brad SIMPLEQ_INIT(&sc->sc_read_queue); 1137 1.1 brad 1138 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 1139 1.1 brad if (error) { 1140 1.1 brad aprint_error_dev(self, "Could not acquire iic bus: %d\n", 1141 1.1 brad error); 1142 1.1 brad goto out; 1143 1.1 brad } 1144 1.1 brad 1145 1.1 brad error = sht3x_cmdr(sc, SHT3X_SOFT_RESET, NULL, 0); 1146 1.1 brad if (error != 0) 1147 1.1 brad aprint_error_dev(self, "Reset failed: %d\n", error); 1148 1.1 brad 1149 1.1 brad error = sht3x_clear_status_register(sc, true); 1150 1.1 brad if (error) { 1151 1.1 brad aprint_error_dev(self, "Failed to clear status register: %d\n", 1152 1.1 brad error); 1153 1.1 brad ecount++; 1154 1.1 brad } 1155 1.1 brad 1156 1.1 brad uint16_t status_reg; 1157 1.1 brad error = sht3x_get_status_register(sc, &status_reg, true); 1158 1.1 brad if (error) { 1159 1.1 brad aprint_error_dev(self, "Failed to read status register: %d\n", 1160 1.1 brad error); 1161 1.1 brad ecount++; 1162 1.1 brad } 1163 1.1 brad 1164 1.1 brad DPRINTF(sc, 2, ("%s: read status register values: %04x\n", 1165 1.1 brad device_xname(sc->sc_dev), status_reg)); 1166 1.1 brad 1167 1.1 brad error = sht3x_cmdr(sc, SHT3X_READ_SERIAL_NUMBER, buf, 6); 1168 1.1 brad if (error) { 1169 1.1 brad aprint_error_dev(self, "Failed to read serial number: %d\n", 1170 1.1 brad error); 1171 1.1 brad ecount++; 1172 1.1 brad } 1173 1.1 brad 1174 1.1 brad sncrcpt1 = sht3x_crc(&buf[0],2); 1175 1.1 brad sncrcpt2 = sht3x_crc(&buf[3],2); 1176 1.1 brad serialnumber = (buf[0] << 24) | (buf[1] << 16) | (buf[3] << 8) | buf[4]; 1177 1.1 brad 1178 1.2 christos DPRINTF(sc, 2, ("%s: read serial number values: %02x%02x - %02x - " 1179 1.2 christos "%02x%02x - %02x -- %02x %02x\n", device_xname(sc->sc_dev), buf[0], 1180 1.2 christos buf[1], buf[2], buf[3], buf[4], buf[5], sncrcpt1, sncrcpt2)); 1181 1.1 brad 1182 1.1 brad iic_release_bus(sc->sc_tag, 0); 1183 1.1 brad if (error != 0) { 1184 1.1 brad aprint_error_dev(self, "Unable to setup device\n"); 1185 1.1 brad goto out; 1186 1.1 brad } 1187 1.1 brad 1188 1.1 brad for (i = 0; i < sc->sc_numsensors; i++) { 1189 1.1 brad strlcpy(sc->sc_sensors[i].desc, sht3x_sensors[i].desc, 1190 1.1 brad sizeof(sc->sc_sensors[i].desc)); 1191 1.1 brad 1192 1.1 brad sc->sc_sensors[i].units = sht3x_sensors[i].type; 1193 1.1 brad sc->sc_sensors[i].state = ENVSYS_SINVALID; 1194 1.1 brad 1195 1.1 brad DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i, 1196 1.1 brad sc->sc_sensors[i].desc)); 1197 1.1 brad 1198 1.1 brad error = sysmon_envsys_sensor_attach(sc->sc_sme, 1199 1.1 brad &sc->sc_sensors[i]); 1200 1.1 brad if (error) { 1201 1.1 brad aprint_error_dev(self, 1202 1.1 brad "Unable to attach sensor %d: %d\n", i, error); 1203 1.1 brad goto out; 1204 1.1 brad } 1205 1.1 brad } 1206 1.1 brad 1207 1.1 brad sc->sc_sme->sme_name = device_xname(sc->sc_dev); 1208 1.1 brad sc->sc_sme->sme_cookie = sc; 1209 1.1 brad sc->sc_sme->sme_refresh = sht3x_refresh; 1210 1.1 brad 1211 1.1 brad DPRINTF(sc, 2, ("sht3x_attach: registering with envsys\n")); 1212 1.1 brad 1213 1.1 brad if (sysmon_envsys_register(sc->sc_sme)) { 1214 1.2 christos aprint_error_dev(self, "unable to register with sysmon\n"); 1215 1.1 brad sysmon_envsys_destroy(sc->sc_sme); 1216 1.1 brad sc->sc_sme = NULL; 1217 1.1 brad return; 1218 1.1 brad } 1219 1.1 brad 1220 1.2 christos /* 1221 1.2 christos * There is no documented way to ask the chip what version it is. This 1222 1.2 christos * is likely fine as the only apparent difference is in how precise the 1223 1.2 christos * measurements will be. The actual conversation with the chip is 1224 1.2 christos * identical no matter which one you are talking to. 1225 1.2 christos */ 1226 1.1 brad 1227 1.1 brad aprint_normal_dev(self, "Sensirion SHT30/SHT31/SHT35, " 1228 1.2 christos "Serial number: %x%s", serialnumber, 1229 1.1 brad (sncrcpt1 == buf[2] && sncrcpt2 == buf[5]) ? "\n" : " (bad crc)\n"); 1230 1.1 brad return; 1231 1.1 brad out: 1232 1.1 brad sysmon_envsys_destroy(sc->sc_sme); 1233 1.1 brad sc->sc_sme = NULL; 1234 1.1 brad } 1235 1.1 brad 1236 1.1 brad static uint16_t 1237 1.10 brad sht3x_compute_measure_command_ss(const char *repeatability, bool clockstretch) 1238 1.1 brad { 1239 1.1 brad int i; 1240 1.1 brad uint16_t r; 1241 1.1 brad 1242 1.1 brad for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) { 1243 1.1 brad if (strncmp(repeatability, sht3x_repeatability_ss[i].text, 1244 1.1 brad SHT3X_REP_NAME) == 0) { 1245 1.10 brad if (clockstretch) 1246 1.10 brad r = sht3x_repeatability_ss[i].cscmd; 1247 1.10 brad else 1248 1.10 brad r = sht3x_repeatability_ss[i].cmd; 1249 1.1 brad break; 1250 1.1 brad } 1251 1.1 brad } 1252 1.1 brad 1253 1.1 brad if (i == __arraycount(sht3x_repeatability_ss)) 1254 1.2 christos panic("Single-shot could not find command for " 1255 1.2 christos "repeatability: %s\n", repeatability); 1256 1.1 brad 1257 1.1 brad return r; 1258 1.1 brad } 1259 1.1 brad 1260 1.1 brad /* 1261 1.2 christos * The documented conversion calculations for the raw values are as follows: 1262 1.2 christos * 1263 1.2 christos * %RH = (-6 + 125 * rawvalue / 65535) 1264 1.2 christos * 1265 1.2 christos * T in Celsius = (-45 + 175 * rawvalue / 65535) 1266 1.2 christos * 1267 1.2 christos * It follows then: 1268 1.2 christos * 1269 1.2 christos * T in Kelvin = (228.15 + 175 * rawvalue / 65535) 1270 1.2 christos * 1271 1.2 christos * given the relationship between Celsius and Kelvin 1272 1.2 christos * 1273 1.2 christos * What follows reorders the calculation a bit and scales it up to avoid 1274 1.2 christos * the use of any floating point. All that would really have to happen 1275 1.2 christos * is a scale up to 10^6 for the sysenv framework, which wants 1276 1.2 christos * temperature in micro-kelvin and percent relative humidity scaled up 1277 1.2 christos * 10^6, but since this conversion uses 64 bits due to intermediate 1278 1.2 christos * values that are bigger than 32 bits the conversion first scales up to 1279 1.2 christos * 10^9 and the scales back down by 10^3 at the end. This preserves some 1280 1.2 christos * precision in the conversion that would otherwise be lost. 1281 1.2 christos */ 1282 1.1 brad 1283 1.1 brad static uint64_t 1284 1.1 brad sht3x_compute_temp_from_raw(uint8_t msb, uint8_t lsb) { 1285 1.1 brad uint64_t svalue; 1286 1.1 brad int64_t v1; 1287 1.1 brad uint64_t v2; 1288 1.1 brad uint64_t d1 = 65535; 1289 1.1 brad uint64_t mul1; 1290 1.1 brad uint64_t mul2; 1291 1.1 brad uint64_t div1 = 10000; 1292 1.1 brad uint64_t q; 1293 1.1 brad 1294 1.1 brad svalue = msb << 8 | lsb; 1295 1.1 brad 1296 1.1 brad v1 = 22815; /* this is scaled up already from 228.15 */ 1297 1.1 brad v2 = 175; 1298 1.1 brad mul1 = 10000000000; 1299 1.1 brad mul2 = 100000000; 1300 1.1 brad 1301 1.1 brad svalue = svalue * mul1; 1302 1.1 brad v1 = v1 * mul2; 1303 1.1 brad /* Perform the conversion */ 1304 1.1 brad q = ((v2 * (svalue / d1)) + v1) / div1; 1305 1.1 brad 1306 1.1 brad return q; 1307 1.1 brad } 1308 1.1 brad 1309 1.1 brad static uint64_t 1310 1.1 brad sht3x_compute_rh_from_raw(uint8_t msb, uint8_t lsb) { 1311 1.1 brad uint64_t svalue; 1312 1.1 brad int64_t v1; 1313 1.1 brad uint64_t v2; 1314 1.1 brad uint64_t d1 = 65535; 1315 1.1 brad uint64_t mul1; 1316 1.1 brad uint64_t mul2; 1317 1.1 brad uint64_t div1 = 10000; 1318 1.1 brad uint64_t q; 1319 1.1 brad 1320 1.1 brad svalue = msb << 8 | lsb; 1321 1.1 brad 1322 1.1 brad v1 = 0; 1323 1.1 brad v2 = 100; 1324 1.1 brad mul1 = 10000000000; 1325 1.1 brad mul2 = 10000000000; 1326 1.1 brad 1327 1.1 brad svalue = svalue * mul1; 1328 1.1 brad v1 = v1 * mul2; 1329 1.1 brad /* Perform the conversion */ 1330 1.1 brad q = ((v2 * (svalue / d1)) + v1) / div1; 1331 1.1 brad 1332 1.1 brad return q; 1333 1.1 brad } 1334 1.1 brad 1335 1.2 christos static int 1336 1.2 christos sht3x_parse_data(struct sht3x_sc *sc, envsys_data_t *edata, uint8_t *rawdata) 1337 1.1 brad { 1338 1.1 brad uint64_t current_value; 1339 1.1 brad uint8_t *svalptr; 1340 1.1 brad 1341 1.2 christos DPRINTF(sc, 2, ("%s: Raw data: %02x%02x %02x - %02x%02x %02x\n", 1342 1.2 christos device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2], 1343 1.2 christos rawdata[3], rawdata[4], rawdata[5])); 1344 1.1 brad 1345 1.1 brad switch (edata->sensor) { 1346 1.1 brad case SHT3X_TEMP_SENSOR: 1347 1.2 christos current_value = sht3x_compute_temp_from_raw(rawdata[0], 1348 1.2 christos rawdata[1]); 1349 1.2 christos svalptr = &rawdata[0]; 1350 1.1 brad break; 1351 1.1 brad case SHT3X_HUMIDITY_SENSOR: 1352 1.2 christos current_value = sht3x_compute_rh_from_raw(rawdata[3], 1353 1.2 christos rawdata[4]); 1354 1.2 christos svalptr = &rawdata[3]; 1355 1.1 brad break; 1356 1.1 brad default: 1357 1.2 christos DPRINTF(sc, 2, ("%s: bad sensor type %d\n", 1358 1.2 christos device_xname(sc->sc_dev), edata->sensor)); 1359 1.2 christos return EINTR; 1360 1.2 christos } 1361 1.2 christos uint8_t testcrc; 1362 1.2 christos /* Fake out the CRC check if being asked to ignore CRC */ 1363 1.2 christos if (sc->sc_ignorecrc) { 1364 1.2 christos testcrc = *(svalptr + 2); 1365 1.2 christos } else { 1366 1.2 christos testcrc = sht3x_crc(svalptr, 2); 1367 1.1 brad } 1368 1.1 brad 1369 1.2 christos if (*(svalptr + 2) != testcrc) { 1370 1.2 christos DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d != %d\n", 1371 1.2 christos device_xname(sc->sc_dev), (*svalptr + 2), testcrc)); 1372 1.2 christos return EINVAL; 1373 1.1 brad } 1374 1.2 christos edata->value_cur = (uint32_t) current_value; 1375 1.2 christos edata->state = ENVSYS_SVALID; 1376 1.2 christos return 0; 1377 1.1 brad } 1378 1.1 brad 1379 1.2 christos static int 1380 1.2 christos sht3x_refresh_periodic(struct sysmon_envsys *sme, envsys_data_t *edata) 1381 1.1 brad { 1382 1.2 christos struct sht3x_sc *sc = sme->sme_cookie; 1383 1.2 christos uint8_t rawdata[sizeof(sc->sc_pbuffer)]; 1384 1.1 brad 1385 1.2 christos memcpy(rawdata, sc->sc_pbuffer, sizeof(rawdata)); 1386 1.1 brad 1387 1.2 christos return sht3x_parse_data(sc, edata, rawdata); 1388 1.1 brad 1389 1.1 brad } 1390 1.1 brad 1391 1.2 christos static int 1392 1.2 christos sht3x_refresh_oneshot(struct sysmon_envsys *sme, envsys_data_t *edata) 1393 1.1 brad { 1394 1.1 brad struct sht3x_sc *sc = sme->sme_cookie; 1395 1.2 christos uint16_t measurement_command_ss; 1396 1.2 christos uint8_t rawdata[sizeof(sc->sc_pbuffer)]; 1397 1.1 brad int error; 1398 1.1 brad 1399 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 1400 1.1 brad if (error) { 1401 1.1 brad DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", 1402 1.1 brad device_xname(sc->sc_dev), error)); 1403 1.2 christos return error; 1404 1.1 brad } 1405 1.1 brad 1406 1.2 christos measurement_command_ss = sht3x_compute_measure_command_ss( 1407 1.10 brad sc->sc_repeatability, sc->sc_clockstretch); 1408 1.2 christos error = sht3x_cmdr(sc, measurement_command_ss, rawdata, sizeof(rawdata)); 1409 1.4 brad DPRINTF(sc, 2, ("%s: Status for single-shot measurement cmd %04x " 1410 1.4 brad "Error %d\n", device_xname(sc->sc_dev), measurement_command_ss, error)); 1411 1.2 christos if (error == 0) { 1412 1.4 brad error = sht3x_parse_data(sc, edata, rawdata); 1413 1.1 brad } 1414 1.1 brad 1415 1.2 christos uint16_t sbuf; 1416 1.2 christos int status_error = sht3x_get_status_register(sc, &sbuf, true); 1417 1.1 brad 1418 1.2 christos if (!status_error) { 1419 1.2 christos DPRINTF(sc, 2, ("%s: read status register single-shot: %04x\n", 1420 1.2 christos device_xname(sc->sc_dev), sbuf)); 1421 1.1 brad 1422 1.2 christos if (sbuf & SHT3X_RESET_DETECTED) { 1423 1.2 christos aprint_error_dev(sc->sc_dev, 1424 1.2 christos "Reset detected in single shot mode. " 1425 1.2 christos "Heater may have been reset\n"); 1426 1.2 christos sht3x_clear_status_register(sc, true); 1427 1.2 christos } 1428 1.1 brad 1429 1.2 christos sc->sc_heateron = sbuf & SHT3X_HEATER_STATUS; 1430 1.1 brad } 1431 1.1 brad 1432 1.2 christos iic_release_bus(sc->sc_tag, 0); 1433 1.4 brad 1434 1.4 brad return error; 1435 1.2 christos } 1436 1.1 brad 1437 1.2 christos static void 1438 1.2 christos sht3x_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 1439 1.2 christos { 1440 1.2 christos struct sht3x_sc *sc = sme->sme_cookie; 1441 1.1 brad 1442 1.2 christos edata->state = ENVSYS_SINVALID; 1443 1.1 brad 1444 1.2 christos mutex_enter(&sc->sc_mutex); 1445 1.1 brad 1446 1.2 christos if (sc->sc_isperiodic) { 1447 1.2 christos sht3x_refresh_periodic(sme, edata); 1448 1.2 christos } else { 1449 1.2 christos sht3x_refresh_oneshot(sme, edata); 1450 1.1 brad } 1451 1.1 brad 1452 1.1 brad mutex_exit(&sc->sc_mutex); 1453 1.1 brad } 1454 1.1 brad 1455 1.1 brad static int 1456 1.1 brad sht3xopen(dev_t dev, int flags, int fmt, struct lwp *l) 1457 1.1 brad { 1458 1.1 brad struct sht3x_sc *sc; 1459 1.1 brad 1460 1.1 brad sc = device_lookup_private(&sht3xtemp_cd, minor(dev)); 1461 1.1 brad if (!sc) 1462 1.2 christos return ENXIO; 1463 1.1 brad 1464 1.1 brad if (sc->sc_opened) 1465 1.2 christos return EBUSY; 1466 1.1 brad 1467 1.1 brad mutex_enter(&sc->sc_mutex); 1468 1.1 brad sc->sc_opened = true; 1469 1.1 brad 1470 1.1 brad sc->sc_wassingleshot = false; 1471 1.1 brad if (!sc->sc_isperiodic) { 1472 1.1 brad sc->sc_stopping = false; 1473 1.1 brad sc->sc_initperiodic = true; 1474 1.1 brad sc->sc_isperiodic = true; 1475 1.1 brad sc->sc_wassingleshot = true; 1476 1.1 brad sht3x_start_thread(sc); 1477 1.1 brad } 1478 1.1 brad mutex_exit(&sc->sc_mutex); 1479 1.1 brad 1480 1.2 christos return 0; 1481 1.1 brad } 1482 1.1 brad 1483 1.1 brad static int 1484 1.1 brad sht3xread(dev_t dev, struct uio *uio, int flags) 1485 1.1 brad { 1486 1.1 brad struct sht3x_sc *sc; 1487 1.1 brad struct sht3x_read_q *pp; 1488 1.1 brad int error,any; 1489 1.1 brad 1490 1.1 brad sc = device_lookup_private(&sht3xtemp_cd, minor(dev)); 1491 1.1 brad if (!sc) 1492 1.2 christos return ENXIO; 1493 1.1 brad 1494 1.1 brad while (uio->uio_resid) { 1495 1.1 brad any = 0; 1496 1.1 brad error = 0; 1497 1.1 brad mutex_enter(&sc->sc_read_mutex); 1498 1.1 brad 1499 1.1 brad while (any == 0) { 1500 1.1 brad pp = SIMPLEQ_FIRST(&sc->sc_read_queue); 1501 1.1 brad if (pp != NULL) { 1502 1.1 brad SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q); 1503 1.1 brad any = 1; 1504 1.1 brad break; 1505 1.1 brad } 1506 1.2 christos error = cv_wait_sig(&sc->sc_condreadready, 1507 1.2 christos &sc->sc_read_mutex); 1508 1.2 christos if (sc->sc_dying) 1509 1.2 christos error = EIO; 1510 1.2 christos if (error == 0) 1511 1.2 christos continue; 1512 1.2 christos break; 1513 1.1 brad } 1514 1.1 brad 1515 1.1 brad if (any == 1 && error == 0) { 1516 1.2 christos uint8_t *p = pp->measurement; 1517 1.1 brad mutex_exit(&sc->sc_read_mutex); 1518 1.1 brad pool_cache_put(sc->sc_readpool,pp); 1519 1.1 brad 1520 1.2 christos DPRINTF(sc,2, ("%s: sending %02x%02x %02x -- %02x%02x " 1521 1.2 christos "%02x -- %x\n", device_xname(sc->sc_dev), p[0], 1522 1.2 christos p[1], p[2], p[3], p[4], p[5], 1523 1.2 christos mutex_owned(&sc->sc_read_mutex))); 1524 1.2 christos if ((error = uiomove(pp->measurement, 1525 1.2 christos sizeof(pp->measurement), uio)) != 0) { 1526 1.2 christos DPRINTF(sc,2, ("%s: send error %d\n", 1527 1.2 christos device_xname(sc->sc_dev), error)); 1528 1.1 brad break; 1529 1.1 brad } 1530 1.1 brad } else { 1531 1.1 brad mutex_exit(&sc->sc_read_mutex); 1532 1.1 brad if (error) { 1533 1.1 brad break; 1534 1.1 brad } 1535 1.1 brad } 1536 1.1 brad } 1537 1.1 brad 1538 1.1 brad DPRINTF(sc,2, ("%s: loop done: %d\n",device_xname(sc->sc_dev),error)); 1539 1.1 brad if (sc->sc_dying) { 1540 1.1 brad DPRINTF(sc, 2, ("%s: Telling all we are almost dead\n", 1541 1.1 brad device_xname(sc->sc_dev))); 1542 1.1 brad mutex_enter(&sc->sc_dying_mutex); 1543 1.1 brad cv_signal(&sc->sc_cond_dying); 1544 1.1 brad mutex_exit(&sc->sc_dying_mutex); 1545 1.1 brad } 1546 1.1 brad return error; 1547 1.1 brad } 1548 1.1 brad 1549 1.1 brad static int 1550 1.1 brad sht3xclose(dev_t dev, int flags, int fmt, struct lwp *l) 1551 1.1 brad { 1552 1.1 brad struct sht3x_sc *sc; 1553 1.1 brad struct sht3x_read_q *pp; 1554 1.1 brad 1555 1.1 brad sc = device_lookup_private(&sht3xtemp_cd, minor(dev)); 1556 1.1 brad 1557 1.1 brad if (sc->sc_wassingleshot) { 1558 1.1 brad sht3x_stop_thread(sc); 1559 1.1 brad sc->sc_stopping = false; 1560 1.1 brad sc->sc_initperiodic = false; 1561 1.1 brad sc->sc_isperiodic = false; 1562 1.1 brad } 1563 1.1 brad 1564 1.1 brad mutex_enter(&sc->sc_mutex); 1565 1.1 brad /* Drain any read pools */ 1566 1.1 brad while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) { 1567 1.1 brad SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q); 1568 1.1 brad pool_cache_put(sc->sc_readpool,pp); 1569 1.1 brad } 1570 1.1 brad 1571 1.1 brad /* Say that the device is now free */ 1572 1.1 brad sc->sc_opened = false; 1573 1.1 brad mutex_exit(&sc->sc_mutex); 1574 1.1 brad 1575 1.1 brad return(0); 1576 1.1 brad } 1577 1.1 brad 1578 1.1 brad static int 1579 1.1 brad sht3x_detach(device_t self, int flags) 1580 1.1 brad { 1581 1.1 brad struct sht3x_sc *sc; 1582 1.1 brad struct sht3x_read_q *pp; 1583 1.1 brad 1584 1.1 brad sc = device_private(self); 1585 1.1 brad 1586 1.1 brad if (sc->sc_isperiodic) { 1587 1.1 brad sht3x_stop_thread(sc); 1588 1.1 brad } 1589 1.1 brad 1590 1.1 brad mutex_enter(&sc->sc_mutex); 1591 1.1 brad 1592 1.1 brad sc->sc_dying = true; 1593 1.1 brad 1594 1.1 brad /* If this is true we are still open, destroy the condvar */ 1595 1.1 brad if (sc->sc_opened) { 1596 1.1 brad mutex_enter(&sc->sc_dying_mutex); 1597 1.1 brad mutex_enter(&sc->sc_read_mutex); 1598 1.1 brad cv_signal(&sc->sc_condreadready); 1599 1.1 brad mutex_exit(&sc->sc_read_mutex); 1600 1.1 brad DPRINTF(sc, 2, ("%s: Will wait for anything to exit\n", 1601 1.1 brad device_xname(sc->sc_dev))); 1602 1.4 brad /* In the worst case this will time out after 5 seconds. 1603 1.4 brad * It really should not take that long for the drain / whatever 1604 1.4 brad * to happen 1605 1.4 brad */ 1606 1.2 christos cv_timedwait_sig(&sc->sc_cond_dying, 1607 1.2 christos &sc->sc_dying_mutex, mstohz(5000)); 1608 1.1 brad mutex_exit(&sc->sc_dying_mutex); 1609 1.1 brad cv_destroy(&sc->sc_condreadready); 1610 1.1 brad cv_destroy(&sc->sc_cond_dying); 1611 1.1 brad } 1612 1.1 brad 1613 1.1 brad /* Drain any read pools */ 1614 1.1 brad while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) { 1615 1.1 brad SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q); 1616 1.1 brad pool_cache_put(sc->sc_readpool,pp); 1617 1.1 brad } 1618 1.1 brad 1619 1.1 brad /* Destroy the pool cache now that nothing is using it */ 1620 1.1 brad pool_cache_destroy(sc->sc_readpool); 1621 1.1 brad 1622 1.1 brad /* Remove the sensors */ 1623 1.1 brad if (sc->sc_sme != NULL) { 1624 1.1 brad sysmon_envsys_unregister(sc->sc_sme); 1625 1.1 brad sc->sc_sme = NULL; 1626 1.1 brad } 1627 1.1 brad mutex_exit(&sc->sc_mutex); 1628 1.1 brad 1629 1.1 brad /* Remove the sysctl tree */ 1630 1.1 brad sysctl_teardown(&sc->sc_sht3xlog); 1631 1.1 brad 1632 1.1 brad /* Remove the mutex */ 1633 1.1 brad mutex_destroy(&sc->sc_mutex); 1634 1.1 brad mutex_destroy(&sc->sc_threadmutex); 1635 1.1 brad mutex_destroy(&sc->sc_read_mutex); 1636 1.1 brad mutex_destroy(&sc->sc_dying_mutex); 1637 1.1 brad 1638 1.1 brad /* Free the poolname string */ 1639 1.1 brad if (sc->sc_readpoolname != NULL) { 1640 1.1 brad kmem_free(sc->sc_readpoolname,strlen(sc->sc_readpoolname) + 1); 1641 1.1 brad } 1642 1.1 brad 1643 1.1 brad return 0; 1644 1.1 brad } 1645 1.1 brad 1646 1.1 brad int 1647 1.1 brad sht3x_activate(device_t self, enum devact act) 1648 1.1 brad { 1649 1.1 brad struct sht3x_sc *sc = device_private(self); 1650 1.1 brad 1651 1.1 brad switch (act) { 1652 1.1 brad case DVACT_DEACTIVATE: 1653 1.1 brad sc->sc_dying = true; 1654 1.1 brad return 0; 1655 1.1 brad default: 1656 1.1 brad return EOPNOTSUPP; 1657 1.1 brad } 1658 1.1 brad } 1659 1.1 brad 1660 1.5 pgoyette MODULE(MODULE_CLASS_DRIVER, sht3xtemp, "iic,sysmon_envsys"); 1661 1.1 brad 1662 1.1 brad #ifdef _MODULE 1663 1.1 brad #include "ioconf.c" 1664 1.1 brad #endif 1665 1.1 brad 1666 1.1 brad static int 1667 1.1 brad sht3xtemp_modcmd(modcmd_t cmd, void *opaque) 1668 1.1 brad { 1669 1.1 brad int error; 1670 1.1 brad #ifdef _MODULE 1671 1.1 brad int bmaj = -1, cmaj = -1; 1672 1.1 brad #endif 1673 1.1 brad 1674 1.1 brad switch (cmd) { 1675 1.1 brad case MODULE_CMD_INIT: 1676 1.1 brad #ifdef _MODULE 1677 1.1 brad error = devsw_attach("sht3xtemp", NULL, &bmaj, 1678 1.1 brad &sht3x_cdevsw, &cmaj); 1679 1.1 brad if (error) { 1680 1.1 brad aprint_error("%s: unable to attach devsw\n", 1681 1.1 brad sht3xtemp_cd.cd_name); 1682 1.6 pgoyette return error; 1683 1.6 pgoyette } 1684 1.6 pgoyette 1685 1.6 pgoyette error = config_init_component(cfdriver_ioconf_sht3xtemp, 1686 1.6 pgoyette cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp); 1687 1.6 pgoyette if (error) { 1688 1.6 pgoyette aprint_error("%s: unable to init component\n", 1689 1.6 pgoyette sht3xtemp_cd.cd_name); 1690 1.6 pgoyette devsw_detach(NULL, &sht3x_cdevsw); 1691 1.1 brad } 1692 1.1 brad return error; 1693 1.1 brad #else 1694 1.1 brad return 0; 1695 1.1 brad #endif 1696 1.1 brad case MODULE_CMD_FINI: 1697 1.1 brad #ifdef _MODULE 1698 1.6 pgoyette error = config_fini_component(cfdriver_ioconf_sht3xtemp, 1699 1.6 pgoyette cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp); 1700 1.1 brad devsw_detach(NULL, &sht3x_cdevsw); 1701 1.6 pgoyette return error; 1702 1.1 brad #else 1703 1.1 brad return 0; 1704 1.1 brad #endif 1705 1.1 brad default: 1706 1.1 brad return ENOTTY; 1707 1.1 brad } 1708 1.1 brad } 1709