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