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