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