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