Module Name:    src
Committed By:   brad
Date:           Mon Nov 21 21:24:02 UTC 2022

Modified Files:
        src/distrib/sets/lists/debug: module.mi
        src/distrib/sets/lists/man: mi
        src/distrib/sets/lists/modules: mi
        src/share/man/man4: Makefile
        src/sys/dev/i2c: files.i2c
        src/sys/dev/sysmon: sysmon_envsys_tables.c
        src/sys/modules: Makefile
        src/sys/sys: envsys.h
        src/usr.sbin/envstat: envstat.8 envstat.c
Added Files:
        src/share/man/man4: bmx280thp.4
        src/sys/dev/i2c: bmx280.c bmx280reg.h bmx280var.h
        src/sys/modules/bmx280thp: Makefile bmx280thp.ioconf

Log Message:
A driver for the Bosch BMP280 / BME280 temperature, humidity and
atmospheric pressure sensor.  This is an inexpensive to moderately
expensive chip available from a large number of places.  The driver
supports all aspects of the two chips, except for the repeating read
mode which would allow for sub-second queries, such as fall detection
or perhaps even as an altimeter.  This driver also only supports the
I2C interface and not the SPI interface.

The BME280, the one with humidity, is not fully tested at this point,
awaiting upon a breakout board and may not show proper humidity.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/distrib/sets/lists/debug/module.mi
cvs rdiff -u -r1.1755 -r1.1756 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.155 -r1.156 src/distrib/sets/lists/modules/mi
cvs rdiff -u -r1.729 -r1.730 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/bmx280thp.4
cvs rdiff -u -r0 -r1.1 src/sys/dev/i2c/bmx280.c src/sys/dev/i2c/bmx280reg.h \
    src/sys/dev/i2c/bmx280var.h
cvs rdiff -u -r1.124 -r1.125 src/sys/dev/i2c/files.i2c
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/sysmon/sysmon_envsys_tables.c
cvs rdiff -u -r1.272 -r1.273 src/sys/modules/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/modules/bmx280thp/Makefile \
    src/sys/modules/bmx280thp/bmx280thp.ioconf
cvs rdiff -u -r1.38 -r1.39 src/sys/sys/envsys.h
cvs rdiff -u -r1.66 -r1.67 src/usr.sbin/envstat/envstat.8
cvs rdiff -u -r1.102 -r1.103 src/usr.sbin/envstat/envstat.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/debug/module.mi
diff -u src/distrib/sets/lists/debug/module.mi:1.21 src/distrib/sets/lists/debug/module.mi:1.22
--- src/distrib/sets/lists/debug/module.mi:1.21	Thu Nov 17 19:20:06 2022
+++ src/distrib/sets/lists/debug/module.mi	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-# $NetBSD: module.mi,v 1.21 2022/11/17 19:20:06 brad Exp $
+# $NetBSD: module.mi,v 1.22 2022/11/21 21:24:01 brad Exp $
 ./usr/libdata/debug/@MODULEDIR@					modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/accf_dataready			modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/accf_dataready/accf_dataready.kmod.debug	modules-base-kernel	kmod,debug
@@ -22,6 +22,8 @@
 ./usr/libdata/debug/@MODULEDIR@/blake2s/blake2s.kmod.debug		modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/blowfish				modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/blowfish/blowfish.kmod.debug		modules-base-kernel	kmod,debug
+./usr/libdata/debug/@MODULEDIR@/bmx280thp				modules-base-kernel	kmod,debug
+./usr/libdata/debug/@MODULEDIR@/bmx280thp/bmx280thp.kmod.debug		modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/bpf				modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/bpf/bpf.kmod.debug			modules-base-kernel	kmod,debug
 ./usr/libdata/debug/@MODULEDIR@/bpf_filter			modules-base-kernel	kmod,debug

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1755 src/distrib/sets/lists/man/mi:1.1756
--- src/distrib/sets/lists/man/mi:1.1755	Thu Nov 17 19:20:06 2022
+++ src/distrib/sets/lists/man/mi	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1755 2022/11/17 19:20:06 brad Exp $
+# $NetBSD: mi,v 1.1756 2022/11/21 21:24:01 brad Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -965,6 +965,7 @@
 ./usr/share/man/cat4/bio.0			man-sys-catman		.cat
 ./usr/share/man/cat4/bktr.0			man-sys-catman		.cat
 ./usr/share/man/cat4/bluetooth.0		man-sys-catman		.cat
+./usr/share/man/cat4/bmx280thp.0		man-sys-catman		.cat
 ./usr/share/man/cat4/bmtphy.0			man-sys-catman		.cat
 ./usr/share/man/cat4/bnx.0			man-sys-catman		.cat
 ./usr/share/man/cat4/boca.0			man-sys-catman		.cat
@@ -4237,6 +4238,7 @@
 ./usr/share/man/html4/bio.html			man-sys-htmlman		html
 ./usr/share/man/html4/bktr.html			man-sys-htmlman		html
 ./usr/share/man/html4/bluetooth.html		man-sys-htmlman		html
+./usr/share/man/html4/bmx280thp.html		man-sys-htmlman		html
 ./usr/share/man/html4/bmtphy.html		man-sys-htmlman		html
 ./usr/share/man/html4/bnx.html			man-sys-htmlman		html
 ./usr/share/man/html4/boca.html			man-sys-htmlman		html
@@ -7275,6 +7277,7 @@
 ./usr/share/man/man4/bio.4			man-sys-man		.man
 ./usr/share/man/man4/bktr.4			man-sys-man		.man
 ./usr/share/man/man4/bluetooth.4		man-sys-man		.man
+./usr/share/man/man4/bmx280thp.4		man-sys-man		.man
 ./usr/share/man/man4/bmtphy.4			man-sys-man		.man
 ./usr/share/man/man4/bnx.4			man-sys-man		.man
 ./usr/share/man/man4/boca.4			man-sys-man		.man

Index: src/distrib/sets/lists/modules/mi
diff -u src/distrib/sets/lists/modules/mi:1.155 src/distrib/sets/lists/modules/mi:1.156
--- src/distrib/sets/lists/modules/mi:1.155	Thu Nov 17 19:20:06 2022
+++ src/distrib/sets/lists/modules/mi	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.155 2022/11/17 19:20:06 brad Exp $
+# $NetBSD: mi,v 1.156 2022/11/21 21:24:01 brad Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -31,6 +31,8 @@
 ./@MODULEDIR@/blake2s/blake2s.kmod		modules-base-kernel	kmod
 ./@MODULEDIR@/blowfish				modules-base-kernel	kmod
 ./@MODULEDIR@/blowfish/blowfish.kmod		modules-base-kernel	kmod
+./@MODULEDIR@/bmx280thp				modules-base-kernel	kmod
+./@MODULEDIR@/bmx280thp/bmx280thp.kmod		modules-base-kernel	kmod
 ./@MODULEDIR@/bpf				modules-base-kernel	kmod
 ./@MODULEDIR@/bpf/bpf.kmod			modules-base-kernel	kmod
 ./@MODULEDIR@/bpf_filter			modules-base-kernel	kmod

Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.729 src/share/man/man4/Makefile:1.730
--- src/share/man/man4/Makefile:1.729	Thu Nov 17 19:20:05 2022
+++ src/share/man/man4/Makefile	Mon Nov 21 21:24:00 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.729 2022/11/17 19:20:05 brad Exp $
+#	$NetBSD: Makefile,v 1.730 2022/11/21 21:24:00 brad Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 
 MAN=	aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -11,7 +11,7 @@ MAN=	aac.4 ac97.4 acardide.4 aceride.4 a
 	auacer.4 audio.4 audiocs.4 auich.4 \
 	auixp.4 autri.4 auvia.4 awi.4 \
 	battery_pmu.4 bba.4 bce.4 bcsp.4 be.4 bge.4 bnx.4 bha.4 \
-	bio.4 bktr.4 bluetooth.4 bmtphy.4 bpf.4 bpfjit.4 \
+	bio.4 bktr.4 bluetooth.4 bmx280thp.4 bmtphy.4 bpf.4 bpfjit.4 \
 	brgphy.4 bridge.4 bthidev.4 bthub.4 btkbd.4 \
 	btmagic.4 btms.4 btsco.4 btuart.4 \
 	bwfm.4 bwi.4 \

Index: src/sys/dev/i2c/files.i2c
diff -u src/sys/dev/i2c/files.i2c:1.124 src/sys/dev/i2c/files.i2c:1.125
--- src/sys/dev/i2c/files.i2c:1.124	Thu Nov 17 19:20:06 2022
+++ src/sys/dev/i2c/files.i2c	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i2c,v 1.124 2022/11/17 19:20:06 brad Exp $
+#	$NetBSD: files.i2c,v 1.125 2022/11/21 21:24:01 brad Exp $
 
 obsolete defflag	opt_i2cbus.h		I2C_SCAN
 define	i2cbus { }
@@ -435,3 +435,8 @@ file	dev/i2c/scmdi2c.c			scmdi2c
 device aht20temp
 attach aht20temp at iic
 file dev/i2c/aht20.c				aht20temp
+
+# Bosch Sensortec BMP280/BME280 Temperature, Humidity and Pressure sensor
+device bmx280thp
+attach bmx280thp at iic
+file dev/i2c/bmx280.c				bmx280thp

Index: src/sys/dev/sysmon/sysmon_envsys_tables.c
diff -u src/sys/dev/sysmon/sysmon_envsys_tables.c:1.13 src/sys/dev/sysmon/sysmon_envsys_tables.c:1.14
--- src/sys/dev/sysmon/sysmon_envsys_tables.c:1.13	Sun May 27 01:39:00 2018
+++ src/sys/dev/sysmon/sysmon_envsys_tables.c	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsys_tables.c,v 1.13 2018/05/27 01:39:00 thorpej Exp $ */
+/* $NetBSD: sysmon_envsys_tables.c,v 1.14 2022/11/21 21:24:01 brad Exp $ */
 
 /*-
  * Copyright (c) 2007 Juan Romero Pardines.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_tables.c,v 1.13 2018/05/27 01:39:00 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_tables.c,v 1.14 2022/11/21 21:24:01 brad Exp $");
 
 #include <sys/types.h>
 
@@ -53,6 +53,7 @@ static const struct sme_descr_entry sme_
 	{ ENVSYS_BATTERY_CHARGE, -1,			"Battery charge" },
 	{ ENVSYS_SRELHUMIDITY,	-1,			"relative Humidity" },
 	{ ENVSYS_LUX,		-1,			"Illuminance" },
+	{ ENVSYS_PRESSURE,	-1,			"pressure" },
 	{ -1,			-1,			"unknown" }
 };
 

Index: src/sys/modules/Makefile
diff -u src/sys/modules/Makefile:1.272 src/sys/modules/Makefile:1.273
--- src/sys/modules/Makefile:1.272	Thu Nov 17 19:20:05 2022
+++ src/sys/modules/Makefile	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.272 2022/11/17 19:20:05 brad Exp $
+#	$NetBSD: Makefile,v 1.273 2022/11/21 21:24:01 brad Exp $
 
 .include <bsd.own.mk>
 
@@ -33,6 +33,7 @@ SUBDIR+=	blake2s
 SUBDIR+=	blowfish
 SUBDIR+=	bpf
 SUBDIR+=	bpf_filter
+SUBDIR+=	bmx280thp
 SUBDIR+=	bufq_disksort
 SUBDIR+=	bufq_fcfs
 SUBDIR+=	bufq_priocscan

Index: src/sys/sys/envsys.h
diff -u src/sys/sys/envsys.h:1.38 src/sys/sys/envsys.h:1.39
--- src/sys/sys/envsys.h:1.38	Sun May 27 06:40:31 2018
+++ src/sys/sys/envsys.h	Mon Nov 21 21:24:01 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: envsys.h,v 1.38 2018/05/27 06:40:31 wiz Exp $ */
+/* $NetBSD: envsys.h,v 1.39 2022/11/21 21:24:01 brad Exp $ */
 
 /*-
  * Copyright (c) 1999, 2007, 2014 The NetBSD Foundation, Inc.
@@ -65,6 +65,7 @@ enum envsys_units {
 	ENVSYS_BATTERY_CHARGE,		/* Battery charging/discharging */
 	ENVSYS_SRELHUMIDITY,		/* relative humidity */
 	ENVSYS_LUX,			/* illuminance in lux */
+	ENVSYS_PRESSURE,		/* pressure in hPa */
 	ENVSYS_NSENSORS
 };
 

Index: src/usr.sbin/envstat/envstat.8
diff -u src/usr.sbin/envstat/envstat.8:1.66 src/usr.sbin/envstat/envstat.8:1.67
--- src/usr.sbin/envstat/envstat.8:1.66	Sat Nov 14 20:07:13 2020
+++ src/usr.sbin/envstat/envstat.8	Mon Nov 21 21:24:02 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: envstat.8,v 1.66 2020/11/14 20:07:13 wiz Exp $
+.\"	$NetBSD: envstat.8,v 1.67 2022/11/21 21:24:02 brad Exp $
 .\"
 .\" Copyright (c) 2000, 2007, 2008, 2009, 2014 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -190,6 +190,8 @@ Watts
 Watt-hours
 .It %rH
 relative Humidity
+.It hPa
+Hectopascals
 .El
 .Sh EXAMPLES
 To display the

Index: src/usr.sbin/envstat/envstat.c
diff -u src/usr.sbin/envstat/envstat.c:1.102 src/usr.sbin/envstat/envstat.c:1.103
--- src/usr.sbin/envstat/envstat.c:1.102	Sat May 28 10:36:24 2022
+++ src/usr.sbin/envstat/envstat.c	Mon Nov 21 21:24:02 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: envstat.c,v 1.102 2022/05/28 10:36:24 andvar Exp $ */
+/* $NetBSD: envstat.c,v 1.103 2022/11/21 21:24:02 brad Exp $ */
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: envstat.c,v 1.102 2022/05/28 10:36:24 andvar Exp $");
+__RCSID("$NetBSD: envstat.c,v 1.103 2022/11/21 21:24:02 brad Exp $");
 #endif /* not lint */
 
 #include <stdio.h>
@@ -1174,6 +1174,53 @@ do {									\
 			if (!nflag)
 				(void)printf(" %*s", (int)ilen - 3, stype);
 
+		/* Pressure */
+		} else if (strcmp(sensor->type, "pressure") == 0) {
+			stype = "hPa";
+
+			(void)printf("%s%*.3f", sep, flen,
+			    sensor->cur_value / 10000.0);
+
+			ilen = 8;
+			if (statistics) {
+				/* show statistics if flag set */
+				(void)printf("  %.3f  %.3f  %.3f",
+				    stats->max / 10000.0, stats->min / 10000.0, stats->avg / 10000.0);
+				ilen += 2;
+			} else if (!nflag) {
+				if (sensor->critmax_value) {
+					(void)printf(" %*u", (int)ilen,
+					    sensor->critmax_value);
+					ilen = 8;
+				} else
+					ilen += 9;
+
+				if (sensor->warnmax_value) {
+					(void)printf(" %*u", (int)ilen,
+					    sensor->warnmax_value);
+					ilen = 8;
+				} else
+					ilen += 9;
+
+				if (sensor->warnmin_value) {
+					(void)printf(" %*u", (int)ilen,
+					    sensor->warnmin_value);
+					ilen = 8;
+				} else
+					ilen += 9;
+
+				if (sensor->critmin_value) {
+					(void)printf( " %*u", (int)ilen,
+					    sensor->critmin_value);
+					ilen = 8;
+				} else
+					ilen += 9;
+
+			}
+
+			if (!nflag)
+				(void)printf(" %*s", (int)ilen - 3, stype);
+
 		/* everything else */
 		} else {
 			if (strcmp(sensor->type, "Voltage DC") == 0)

Added files:

Index: src/share/man/man4/bmx280thp.4
diff -u /dev/null src/share/man/man4/bmx280thp.4:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/share/man/man4/bmx280thp.4	Mon Nov 21 21:24:00 2022
@@ -0,0 +1,89 @@
+.\" $NetBSD: bmx280thp.4,v 1.1 2022/11/21 21:24:00 brad Exp $
+.\"
+.\" Copyright (c) 2022 Brad Spencer <b...@anduin.eldar.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd November 19, 2022
+.Dt BMX280THP 4
+.Os
+.Sh NAME
+.Nm bmx280thp
+.Nd Driver for Bosch BMP280/BME280 sensor chip via I2C bus
+.Sh SYNOPSIS
+.Cd "bmx280thp* at iic? addr 0x76"
+.Cd "bmx280thp* at iic? addr 0x77"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides measurements from the BMP280 and BME280 temperature,
+humidity and barometric pressure sensors via the
+.Xr envsys 4
+framework.
+The
+.Nm
+.Ar addr
+argument selects the address at the
+.Xr iic 4
+bus.
+The percision of the measurement can be changed through
+.Xr sysctl 8
+nodes.
+.Sh SYSCTL VARIABLES
+The following
+.Xr sysctl 3
+variables are provided:
+.Bl -tag -width indent
+.It Li hw.bmx280thp0.osrs_t
+.It Li hw.bmx280thp0.osrs_p
+.It Li hw.bmx280thp0.osrs_h
+These control oversampling of temperature, pressure and humidity.  The
+valid values are 1, 2, 4, 8, and 16 times oversample.  Humidity is only
+available if the chip is a BME280.
+.It Li hw.bmx280thp0.irr_samples
+IRR is a filter that can be used to reduce the noise in the
+measurement.  The value values are 1 (or off), 2, 5, 11 and 22 samples
+to reach >= 75% of the step response.
+.It Li hw.bmx280thp0.debug
+.It Li hw.bmx280thp0.dump_calibration
+If the driver is compiled with
+.Dv BMX280_DEBUG ,
+these nodes will appear and can be used to set the debugging level and
+provide the calibration constants, upon refresh, that are stored in the
+chip.  Since the constants are fixed, this is a boolean node and will
+reset back to false once one dump has been performed.
+.It Li hw.bmx280thp0.readattempts
+A status register tells the driver if the chip is busy with a measurement.
+This status register must be polled and readattempts is the number of times
+that this poll will be performed.
+The default is 25 which should be more than enough for most purposes.
+.El
+.Sh SEE ALSO
+.Xr envsys 4 ,
+.Xr iic 4 ,
+.Xr envstat 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Nx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Brad Spencer Aq Mt b...@anduin.eldar.org .
+.Sh BUGS
+The driver does not support the continuous read mode that the BMP280
+and BME280 has.  This driver does not support the SPI interface.

Index: src/sys/dev/i2c/bmx280.c
diff -u /dev/null src/sys/dev/i2c/bmx280.c:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/sys/dev/i2c/bmx280.c	Mon Nov 21 21:24:01 2022
@@ -0,0 +1,1074 @@
+/*	$NetBSD: bmx280.c,v 1.1 2022/11/21 21:24:01 brad Exp $	*/
+
+/*
+ * Copyright (c) 2022 Brad Spencer <b...@anduin.eldar.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: bmx280.c,v 1.1 2022/11/21 21:24:01 brad Exp $");
+
+/*
+  Driver for the Bosch BMP280/BME280 temperature, humidity (sometimes) and
+  (usually barometric) pressure sensor
+*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/bmx280reg.h>
+#include <dev/i2c/bmx280var.h>
+
+
+static int	bmx280_write_register(i2c_tag_t, i2c_addr_t,
+    uint8_t *, size_t);
+static int	bmx280_read_register(i2c_tag_t, i2c_addr_t, uint8_t *,
+    uint8_t *, size_t);
+static void	bmx280_store_raw_blob_tp(struct bmx280_sc *, uint8_t *);
+static void	bmx280_store_raw_blob_h(struct bmx280_sc *, uint8_t *);
+static int 	bmx280_poke(i2c_tag_t, i2c_addr_t, bool);
+static int 	bmx280_match(device_t, cfdata_t, void *);
+static void 	bmx280_attach(device_t, device_t, void *);
+static int 	bmx280_detach(device_t, int);
+static void 	bmx280_refresh(struct sysmon_envsys *, envsys_data_t *);
+static int 	bmx280_verify_sysctl(SYSCTLFN_ARGS);
+static int 	bmx280_verify_sysctl_osrs(SYSCTLFN_ARGS);
+static int 	bmx280_verify_sysctl_irr(SYSCTLFN_ARGS);
+
+#define BMX280_DEBUG
+#ifdef BMX280_DEBUG
+#define DPRINTF(s, l, x) \
+    do { \
+	if (l <= s->sc_bmx280debug) \
+	    printf x; \
+    } while (/*CONSTCOND*/0)
+#else
+#define DPRINTF(s, l, x)
+#endif
+
+CFATTACH_DECL_NEW(bmx280thp, sizeof(struct bmx280_sc),
+    bmx280_match, bmx280_attach, bmx280_detach, NULL);
+
+static struct bmx280_sensor bmx280_sensors[] = {
+	{
+		.desc = "temperature",
+		.type = ENVSYS_STEMP,
+	},
+	{
+		.desc = "pressure",
+		.type = ENVSYS_PRESSURE,
+	},
+	{
+		.desc = "humidity",
+		.type = ENVSYS_SRELHUMIDITY,
+	}
+};
+
+static struct bmx280_osrs_list bmx280_osrs[] = {
+	{
+		.text = 1,
+		.mask = BMX280_OSRS_TP_VALUE_X1,
+	},
+	{
+		.text = 2,
+		.mask = BMX280_OSRS_TP_VALUE_X2,
+	},
+	{
+		.text = 4,
+		.mask = BMX280_OSRS_TP_VALUE_X4,
+	},
+	{
+		.text = 8,
+		.mask = BMX280_OSRS_TP_VALUE_X8,
+	},
+	{
+		.text = 16,
+		.mask = BMX280_OSRS_TP_VALUE_X16,
+	}
+};
+
+static struct bmx280_irr_list bmx280_irr[] = {
+	{
+		.text = 1,
+		.mask = BMX280_FILTER_VALUE_OFF,
+	},
+	{
+		.text = 2,
+		.mask = BMX280_FILTER_VALUE_2,
+	},
+	{
+		.text = 5,
+		.mask = BMX280_FILTER_VALUE_5,
+	},
+	{
+		.text = 11,
+		.mask = BMX280_FILTER_VALUE_11,
+	},
+	{
+		.text = 22,
+		.mask = BMX280_FILTER_VALUE_22,
+	}
+};
+
+static uint8_t
+bmx280_osrs_text_to_mask(int t)
+{
+	int i;
+	uint8_t m = 0;
+
+	for (i = 0; i < __arraycount(bmx280_osrs); i++) {
+		if (t == bmx280_osrs[i].text) {
+			m = bmx280_osrs[i].mask;
+			break;
+		}
+	}
+
+	return m;
+}
+
+static uint8_t
+bmx280_irr_text_to_mask(int t)
+{
+	int i;
+	uint8_t m = 0;
+
+	for (i = 0; i < __arraycount(bmx280_irr); i++) {
+		if (t == bmx280_irr[i].text) {
+			m = bmx280_irr[i].mask;
+			break;
+		}
+	}
+
+	return m;
+}
+
+int
+bmx280_verify_sysctl(SYSCTLFN_ARGS)
+{
+	int error, t;
+	struct sysctlnode node;
+
+	node = *rnode;
+	t = *(int *)rnode->sysctl_data;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (t < 0)
+		return EINVAL;
+
+	*(int *)rnode->sysctl_data = t;
+
+	return 0;
+}
+
+int
+bmx280_verify_sysctl_osrs(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error = 0, t;
+	size_t i;
+
+	node = *rnode;
+	t = *(int *)rnode->sysctl_data;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	for (i = 0; i < __arraycount(bmx280_osrs); i++) {
+		if (t == bmx280_osrs[i].text) {
+			break;
+		}
+	}
+
+	if (i == __arraycount(bmx280_osrs))
+		return EINVAL;
+
+	*(int *)rnode->sysctl_data = t;
+
+	return error;
+}
+
+int
+bmx280_verify_sysctl_irr(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error = 0, t;
+	size_t i;
+
+	node = *rnode;
+	t = *(int *)rnode->sysctl_data;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	for (i = 0; i < __arraycount(bmx280_irr); i++) {
+		if (t == bmx280_irr[i].text) {
+			break;
+		}
+	}
+
+	if (i == __arraycount(bmx280_irr))
+		return EINVAL;
+
+	*(int *)rnode->sysctl_data = t;
+
+	return error;
+}
+
+/* The datasheet was pretty vague as to the byte order...
+ * in fact, down right deceptive...
+ */
+
+static void
+bmx280_store_raw_blob_tp(struct bmx280_sc *sc, uint8_t *b) {
+	sc->sc_cal_blob.dig_T1 = (uint16_t)b[1] << 8;
+	sc->sc_cal_blob.dig_T1 = sc->sc_cal_blob.dig_T1 | (uint16_t)b[0];
+	sc->sc_cal_blob.dig_T2 = (int16_t)b[3] << 8;
+	sc->sc_cal_blob.dig_T2 = sc->sc_cal_blob.dig_T2 | (int16_t)b[2];
+	sc->sc_cal_blob.dig_T3 = (int16_t)b[5] << 8;
+	sc->sc_cal_blob.dig_T3 = sc->sc_cal_blob.dig_T3 | (int16_t)b[4];
+
+	sc->sc_cal_blob.dig_P1 = (uint16_t)b[7] << 8;
+	sc->sc_cal_blob.dig_P1 = sc->sc_cal_blob.dig_P1 | (uint16_t)b[6];
+	sc->sc_cal_blob.dig_P2 = (int16_t)b[9] << 8;
+	sc->sc_cal_blob.dig_P2 = sc->sc_cal_blob.dig_P2 | (int16_t)b[8];
+	sc->sc_cal_blob.dig_P3 = (int16_t)b[11] << 8;
+	sc->sc_cal_blob.dig_P3 = sc->sc_cal_blob.dig_P3 | (int16_t)b[10];
+	sc->sc_cal_blob.dig_P4 = (int16_t)b[13] << 8;
+	sc->sc_cal_blob.dig_P4 = sc->sc_cal_blob.dig_P4 | (int16_t)b[12];
+	sc->sc_cal_blob.dig_P5 = (int16_t)b[15] << 8;
+	sc->sc_cal_blob.dig_P5 = sc->sc_cal_blob.dig_P5 | (int16_t)b[14];
+	sc->sc_cal_blob.dig_P6 = (int16_t)b[17] << 8;
+	sc->sc_cal_blob.dig_P6 = sc->sc_cal_blob.dig_P6 | (int16_t)b[16];
+	sc->sc_cal_blob.dig_P7 = (int16_t)b[19] << 8;
+	sc->sc_cal_blob.dig_P7 = sc->sc_cal_blob.dig_P7 | (int16_t)b[18];
+	sc->sc_cal_blob.dig_P8 = (int16_t)b[21] << 8;
+	sc->sc_cal_blob.dig_P8 = sc->sc_cal_blob.dig_P8 | (int16_t)b[20];
+	sc->sc_cal_blob.dig_P9 = (int16_t)b[23] << 8;
+	sc->sc_cal_blob.dig_P9 = sc->sc_cal_blob.dig_P9 | (int16_t)b[22];
+}
+
+static void
+bmx280_store_raw_blob_h(struct bmx280_sc *sc, uint8_t *b) {
+	sc->sc_cal_blob.dig_H1 = (uint8_t)b[0];
+	sc->sc_cal_blob.dig_H2 = (int16_t)b[2] << 8;
+	sc->sc_cal_blob.dig_H2 = sc->sc_cal_blob.dig_H2 | (int16_t)b[1];
+	sc->sc_cal_blob.dig_H3 = (uint8_t)b[3];
+	sc->sc_cal_blob.dig_H4 = ((int16_t)b[5] & 0x000f) << 8;
+	sc->sc_cal_blob.dig_H4 = sc->sc_cal_blob.dig_H4 | (int16_t)b[4];
+	sc->sc_cal_blob.dig_H5 = (int16_t)b[6] << 4;
+	sc->sc_cal_blob.dig_H5 = sc->sc_cal_blob.dig_H5 | (((int16_t)b[5] & 0x00f0) >> 4);
+	sc->sc_cal_blob.dig_H6 = (int8_t)b[7];
+}
+
+/* For the BMX280, a write consists of sending a I2C START, I2C SLAVE
+ * address and then pairs of registers and data until a I2C STOP is
+ * sent.
+ */
+
+static int
+bmx280_write_register(i2c_tag_t tag, i2c_addr_t addr,
+    uint8_t *buf, size_t blen)
+{
+	int error;
+
+	KASSERT(blen > 0);
+	/* XXX - there should be a KASSERT for blen at least
+	   being an even number */
+
+	error = iic_exec(tag,I2C_OP_WRITE_WITH_STOP,addr,NULL,0,
+	    buf,blen,0);
+
+	return error;
+}
+
+/* For the BMX280, a read consists of writing on the I2C bus
+ * a I2C START, I2C SLAVE address, then the starting register.
+ * If that works, then following will be another I2C START,
+ * I2C SLAVE address, followed by as many I2C reads that is
+ * desired and then a I2C STOP
+ */
+
+static int
+bmx280_read_register(i2c_tag_t tag, i2c_addr_t addr, uint8_t *reg,
+    uint8_t *buf, size_t blen)
+{
+	int error;
+
+	KASSERT(blen > 0);
+
+	error = iic_exec(tag,I2C_OP_WRITE,addr,reg,1,NULL,0,0);
+
+	if (error == 0) {
+		error = iic_exec(tag,I2C_OP_READ_WITH_STOP,addr,NULL,0,
+		    buf,blen,0);
+	}
+
+	return error;
+}
+
+
+static int
+bmx280_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug)
+{
+	uint8_t reg = BMX280_REGISTER_ID;
+	uint8_t buf[1];
+	int error;
+
+	error = bmx280_read_register(tag, addr, &reg, buf, 1);
+	if (matchdebug) {
+		printf("poke X 1: %d\n", error);
+	}
+	return error;
+}
+
+static int
+bmx280_sysctl_init(struct bmx280_sc *sc)
+{
+	int error;
+	const struct sysctlnode *cnode;
+	int sysctlroot_num;
+
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    0, CTLTYPE_NODE, device_xname(sc->sc_dev),
+	    SYSCTL_DESCR("bmx280 controls"), NULL, 0, NULL, 0, CTL_HW,
+	    CTL_CREATE, CTL_EOL)) != 0)
+		return error;
+
+	sysctlroot_num = cnode->sysctl_num;
+
+#ifdef BMX280_DEBUG
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
+	    SYSCTL_DESCR("Debug level"), bmx280_verify_sysctl, 0,
+	    &sc->sc_bmx280debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
+	    CTL_EOL)) != 0)
+		return error;
+
+	/* It would be nice to have a CTLTYPE_SHORT */
+
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "dump_calibration",
+	    SYSCTL_DESCR("Dumps the calibration values to the console"),
+	    bmx280_verify_sysctl, 0,
+	    &sc->sc_bmx280dump, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
+	    CTL_EOL)) != 0)
+		return error;
+#endif
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts",
+	    SYSCTL_DESCR("Read attempts"), bmx280_verify_sysctl, 0,
+	    &sc->sc_readattempts, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
+	    CTL_EOL)) != 0)
+		return error;
+
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_t",
+	    SYSCTL_DESCR("Temperature oversample"),
+	    bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_t,
+	    0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+		return error;
+
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_p",
+	    SYSCTL_DESCR("Pressure oversample"),
+	    bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_p,
+	    0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+		return error;
+
+	if (sc->sc_has_humidity) {
+		if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+		    CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_h",
+		    SYSCTL_DESCR("Humidity oversample"),
+		    bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_h,
+		    0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+			return error;
+	}
+
+	if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "irr_samples",
+	    SYSCTL_DESCR("IRR samples"),
+	    bmx280_verify_sysctl_irr, 0, &sc->sc_irr_samples,
+	    0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+		return error;
+
+	return 0;
+}
+
+static int
+bmx280_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct i2c_attach_args *ia = aux;
+	int error, match_result;
+	const bool matchdebug = false;
+
+	if (iic_use_direct_match(ia, match, NULL, &match_result))
+		return match_result;
+
+	/* indirect config - check for configured address */
+	if (ia->ia_addr != BMX280_TYPICAL_ADDR_1 &&
+	    ia->ia_addr != BMX280_TYPICAL_ADDR_2)
+		return 0;
+
+	/*
+	 * Check to see if something is really at this i2c address. This will
+	 * keep phantom devices from appearing
+	 */
+	if (iic_acquire_bus(ia->ia_tag, 0) != 0) {
+		if (matchdebug)
+			printf("in match acquire bus failed\n");
+		return 0;
+	}
+
+	error = bmx280_poke(ia->ia_tag, ia->ia_addr, matchdebug);
+	iic_release_bus(ia->ia_tag, 0);
+
+	return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0;
+}
+
+static void
+bmx280_attach(device_t parent, device_t self, void *aux)
+{
+	struct bmx280_sc *sc;
+	struct i2c_attach_args *ia;
+	int error, i;
+	uint8_t reg, chip_id;
+	uint8_t buf[2];
+
+	ia = aux;
+	sc = device_private(self);
+
+	sc->sc_dev = self;
+	sc->sc_tag = ia->ia_tag;
+	sc->sc_addr = ia->ia_addr;
+	sc->sc_bmx280debug = 0;
+	sc->sc_bmx280dump = false;
+	sc->sc_has_humidity = false;
+	sc->sc_readattempts = 25;
+	sc->sc_osrs_t = 1;
+	sc->sc_osrs_p = 4;
+	sc->sc_osrs_h = 1;
+	sc->sc_irr_samples = 1;
+	sc->sc_previous_irr = 0xff;
+	sc->sc_sme = NULL;
+
+	aprint_normal("\n");
+
+	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
+	sc->sc_numsensors = __arraycount(bmx280_sensors);
+
+	if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
+		aprint_error_dev(self,
+		    "Unable to create sysmon structure\n");
+		sc->sc_sme = NULL;
+		return;
+	}
+
+	error = iic_acquire_bus(sc->sc_tag, 0);
+	if (error) {
+		aprint_error_dev(self, "Could not acquire iic bus: %d\n",
+		    error);
+		goto out;
+	}
+
+	buf[0] = BMX280_REGISTER_RESET;
+	buf[1] = BMX280_TRIGGER_RESET;
+	error = bmx280_write_register(sc->sc_tag, sc->sc_addr, buf, 2);
+	if (error) {
+		aprint_error_dev(self, "Failed to reset chip: %d\n",
+		    error);
+	}
+
+	delay(100);
+
+	reg = BMX280_REGISTER_ID;
+	error = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, &chip_id, 1);
+	if (error) {
+		aprint_error_dev(self, "Failed to read ID: %d\n",
+		    error);
+	}
+
+	delay(100);
+
+	DPRINTF(sc, 2, ("%s: read ID value: %02x\n",
+	    device_xname(sc->sc_dev), chip_id));
+
+	if (chip_id == BMX280_ID_BME280) {
+		sc->sc_has_humidity = true;
+	}
+
+	if ((error = bmx280_sysctl_init(sc)) != 0) {
+		aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error);
+		goto out;
+	}
+
+	uint8_t raw_blob_tp[24];
+	reg = BMX280_REGISTER_DIG_T1;
+	error = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, raw_blob_tp, 24);
+	if (error) {
+		aprint_error_dev(self, "Failed to read the calibration registers for tp: %d\n",
+		    error);
+	}
+
+	bmx280_store_raw_blob_tp(sc,raw_blob_tp);
+
+	if (sc->sc_has_humidity) {
+		uint8_t raw_blob_h[8];
+
+		reg = BMX280_REGISTER_DIG_H1;
+		error = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, raw_blob_h, 1);
+		if (error) {
+			aprint_error_dev(self, "Failed to read the calibration registers for h1: %d\n",
+			    error);
+		}
+
+		reg = BMX280_REGISTER_DIG_H2;
+		error = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, &raw_blob_h[1], 7);
+		if (error) {
+			aprint_error_dev(self, "Failed to read the calibration registers for h2 - h6: %d\n",
+			    error);
+		}
+
+		bmx280_store_raw_blob_h(sc,raw_blob_h);
+	}
+
+	iic_release_bus(sc->sc_tag, 0);
+
+	if (error != 0) {
+		aprint_error_dev(self, "Unable to setup device\n");
+		goto out;
+	}
+
+	for (i = 0; i < sc->sc_numsensors; i++) {
+		if (sc->sc_has_humidity == false &&
+		    bmx280_sensors[i].type == ENVSYS_SRELHUMIDITY) {
+			break;
+		}
+
+		strlcpy(sc->sc_sensors[i].desc, bmx280_sensors[i].desc,
+		    sizeof(sc->sc_sensors[i].desc));
+
+		sc->sc_sensors[i].units = bmx280_sensors[i].type;
+		sc->sc_sensors[i].state = ENVSYS_SINVALID;
+
+		DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i,
+		    sc->sc_sensors[i].desc));
+
+		error = sysmon_envsys_sensor_attach(sc->sc_sme,
+		    &sc->sc_sensors[i]);
+		if (error) {
+			aprint_error_dev(self,
+			    "Unable to attach sensor %d: %d\n", i, error);
+			goto out;
+		}
+	}
+
+	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
+	sc->sc_sme->sme_cookie = sc;
+	sc->sc_sme->sme_refresh = bmx280_refresh;
+
+	DPRINTF(sc, 2, ("bmx280_attach: registering with envsys\n"));
+
+	if (sysmon_envsys_register(sc->sc_sme)) {
+		aprint_error_dev(self,
+			"unable to register with sysmon\n");
+		sysmon_envsys_destroy(sc->sc_sme);
+		sc->sc_sme = NULL;
+		return;
+	}
+
+	aprint_normal_dev(self, "Bosch Sensortec %s, Chip ID: 0x%02x\n",
+	    (chip_id == BMX280_ID_BMP280) ? "BMP280" : (chip_id == BMX280_ID_BME280) ? "BME280" : "Unknown chip",
+	    chip_id);
+
+	return;
+out:
+	sysmon_envsys_destroy(sc->sc_sme);
+	sc->sc_sme = NULL;
+}
+
+/* The conversion algorithms are taken from the Bosch datasheet for
+ * the BMX280 and adapted to the envsys infrastructure.
+ */
+
+static int32_t
+bmx280_compensate_T_int32(struct bmx280_calibration_blob *b,
+    int32_t adc_T,
+    int32_t *t_fine)
+{
+	int32_t var1, var2, T;
+	var1 = ((((adc_T>>3) - ((int32_t)b->dig_T1<<1))) * ((int32_t)b->dig_T2)) >> 11;
+	var2 = (((((adc_T>>4) - ((int32_t)b->dig_T1)) * ((adc_T>>4) - ((int32_t)b->dig_T1))) >> 12) *
+	    ((int32_t)b->dig_T3)) >> 14;
+	*t_fine = var1 + var2;
+	T = (*t_fine * 5 + 128) >> 8;
+	return T;
+}
+
+/* Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
+ * Output value of 24674867 represents 24674867/256 = 96386.2 Pa = 963.862 hPa
+ */
+static uint32_t
+bmx280_compensate_P_int64(struct bmx280_calibration_blob *b,
+    int32_t adc_P,
+    int32_t t_fine)
+{
+	int64_t var1, var2, p;
+	var1 = ((int64_t)t_fine) - 128000;
+	var2 = var1 * var1 * (int64_t)b->dig_P6;
+	var2 = var2 + ((var1*(int64_t)b->dig_P5)<<17);
+	var2 = var2 + (((int64_t)b->dig_P4)<<35);
+	var1 = ((var1 * var1 * (int64_t)b->dig_P3)>>8) + ((var1 * (int64_t)b->dig_P2)<<12);
+	var1 = (((((int64_t)1)<<47)+var1))*((int64_t)b->dig_P1)>>33;
+	if (var1 == 0) {
+		return 0; /* avoid exception caused by division by zero */
+	}
+	p = 1048576-adc_P;
+	p = (((p<<31)-var2)*3125)/var1;
+	var1 = (((int64_t)b->dig_P9) * (p>>13) * (p>>13)) >> 25;
+	var2 = (((int64_t)b->dig_P8) * p) >> 19;
+	p = ((p + var1 + var2) >> 8) + (((int64_t)b->dig_P7)<<4);
+	return (uint32_t)p;
+}
+
+/* Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
+ *
+ * Output value of 47445 represents 47445/1024 = 46.333 %RH
+ */
+static uint32_t
+bmx280_compensate_H_int32(struct bmx280_calibration_blob *b,
+    int32_t adc_H,
+    int32_t t_fine)
+{
+	int32_t v_x1_u32r;
+	v_x1_u32r = (t_fine - ((int32_t)76800));
+	v_x1_u32r = (((((adc_H << 14) - (((int32_t)b->dig_H4) << 20) - (((int32_t)b->dig_H5) *
+	    v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((((((v_x1_u32r *
+	    ((int32_t)b->dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)b->dig_H3)) >> 11) +
+	    ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)b->dig_H2) +
+	    8192) >> 14));
+	v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
+	    ((int32_t)b->dig_H1)) >> 4));
+	v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
+	v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
+	return (uint32_t)(v_x1_u32r>>12);
+}
+
+
+static int
+bmx280_set_control_and_trigger(struct bmx280_sc *sc,
+    uint8_t osrs_t_mask,
+    uint8_t osrs_p_mask,
+    uint8_t osrs_h_mask,
+    uint8_t filter_mask)
+{
+	uint8_t cr[6];
+	int error;
+	int s = 0;
+
+	cr[0] = cr[1] = cr[2] = cr[3] = cr[4] = cr[5] = 0;
+
+	if (filter_mask != sc->sc_previous_irr) {
+		cr[s] = BMX280_REGISTER_CONFIG;
+		s++;
+		cr[s] = filter_mask << BMX280_CONFIG_FILTER_SHIFT;
+		s++;
+		sc->sc_previous_irr = filter_mask;
+	}
+	if (sc->sc_has_humidity) {
+		cr[s] = BMX280_REGISTER_CTRL_HUM;
+		s++;
+		cr[s] = osrs_h_mask;
+		s++;
+	}
+	cr[s] = BMX280_REGISTER_CTRL_MEAS;
+	s++;
+	cr[s] = osrs_t_mask << BMX280_CTRL_OSRS_T_SHIFT;
+	cr[s] = cr[s] | osrs_p_mask << BMX280_CTRL_OSRS_P_SHIFT;
+	cr[s] = cr[s] | BMX280_MODE_FORCED;
+	s++;
+	DPRINTF(sc, 2, ("%s: control register set up: num: %d ; %02x %02x ; %02x %02x ; %02x %02x\n",
+	    device_xname(sc->sc_dev), s, cr[0], cr[1], cr[2], cr[3], cr[4], cr[5]));
+	error = bmx280_write_register(sc->sc_tag, sc->sc_addr, cr, s);
+	if (error) {
+		DPRINTF(sc, 2, ("%s: write control registers: %d\n",
+		    device_xname(sc->sc_dev), error));
+		error = EINVAL;
+	}
+
+	return error;
+}
+
+static int
+bmx280_wait_for_data(struct bmx280_sc *sc)
+{
+	uint8_t reg;
+	uint8_t running = 99;
+	int c = sc->sc_readattempts;
+	int error = 0, ierror;
+
+	reg = BMX280_REGISTER_STATUS;
+	do {
+		delay(10);
+		ierror = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, &running, 1);
+		if (ierror) {
+			DPRINTF(sc, 2, ("%s: Refresh failed to read back status: %d\n",
+			    device_xname(sc->sc_dev), ierror));
+			error = EINVAL;
+			break;
+		}
+
+		DPRINTF(sc, 2, ("%s: Refresh status read back: %02x\n",
+		    device_xname(sc->sc_dev), running));
+
+		c--;
+	} while (c > 0 && (running & BMX280_STATUS_MEASURING_MASK));
+
+	return error;
+}
+
+static int
+bmx280_read_data(struct bmx280_sc *sc,
+    int32_t *temp,
+    int32_t *press,
+    int32_t *hum,
+    bool justtemp)
+{
+	int error = 0, ierror;
+	int rlen, rtstart, rpstart, rhstart;
+	int x_temp, x_press, x_hum;
+	uint8_t raw_press_temp_hum[8], reg;
+
+	raw_press_temp_hum[0] = raw_press_temp_hum[1] =
+	    raw_press_temp_hum[2] = raw_press_temp_hum[3] =
+	    raw_press_temp_hum[4] = raw_press_temp_hum[5] =
+	    raw_press_temp_hum[6] = raw_press_temp_hum[7] = 0;
+
+	if (justtemp) {
+		reg = BMX280_REGISTER_TEMP_MSB;
+		rlen = 3;
+		rtstart = 0;
+		rpstart = 0;
+		rhstart = 0;
+	} else {
+		reg = BMX280_REGISTER_PRESS_MSB;
+		if (sc->sc_has_humidity == false) {
+			rlen = 6;
+		} else {
+			rlen = 8;
+		}
+		rtstart = 3;
+		rpstart = 0;
+		rhstart = 6;
+	}
+
+	DPRINTF(sc, 2, ("%s: read data: reg: %02x ; len: %d ; tstart: %d ; pstart: %d\n",
+	    device_xname(sc->sc_dev), reg, rlen, rtstart, rpstart));
+
+	ierror = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, raw_press_temp_hum, rlen);
+	if (ierror) {
+		DPRINTF(sc, 2, ("%s: failed to read pressure and temp registers: %d\n",
+		    device_xname(sc->sc_dev), ierror));
+		error = EINVAL;
+		goto out;
+	}
+
+	DPRINTF(sc, 2, ("%s: raw pressure, temp and hum: %02x %02x %02x - %02x %02x %02x - %02x %02x\n",
+	    device_xname(sc->sc_dev),
+	    raw_press_temp_hum[0], raw_press_temp_hum[1], raw_press_temp_hum[2],
+	    raw_press_temp_hum[3], raw_press_temp_hum[4], raw_press_temp_hum[5],
+	    raw_press_temp_hum[6],raw_press_temp_hum[7]));
+
+	x_temp = raw_press_temp_hum[rtstart] << 12;
+	x_temp = x_temp | (raw_press_temp_hum[rtstart + 1] << 4);
+	x_temp = x_temp | (raw_press_temp_hum[rtstart + 2] >> 4);
+
+	DPRINTF(sc, 1, ("%s: intermediate temp: %d (%04x)\n",
+	    device_xname(sc->sc_dev), x_temp, x_temp));
+
+	*temp = x_temp;
+
+	*hum = 0;
+	*press = 0;
+
+	if (justtemp == false) {
+		x_press = raw_press_temp_hum[rpstart] << 12;
+		x_press = x_press | (raw_press_temp_hum[rpstart + 1] << 4);
+		x_press = x_press | (raw_press_temp_hum[rpstart + 2] >> 4);
+
+		DPRINTF(sc, 1, ("%s: intermediate pressure: %d (%04x)\n",
+		    device_xname(sc->sc_dev), x_press, x_press));
+		*press = x_press;
+	}
+	if (sc->sc_has_humidity) {
+		x_hum = raw_press_temp_hum[rhstart] << 8;
+		x_hum = x_hum | raw_press_temp_hum[rhstart + 1];
+
+		DPRINTF(sc, 1, ("%s: intermediate humidity: %d (%02x)\n",
+		    device_xname(sc->sc_dev), x_hum, x_hum));
+		*hum = x_hum;
+	}
+
+ out:
+	return error;
+}
+
+static void
+bmx280_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
+{
+	struct bmx280_sc *sc;
+	sc = sme->sme_cookie;
+	int error = 0;
+	int32_t t_fine;
+	int32_t m_temp, m_press, m_hum;
+	int32_t comp_temp;
+	uint32_t comp_press;
+	uint32_t comp_hum;
+	edata->state = ENVSYS_SINVALID;
+
+	/* Ya... just do this on a refresh... */
+
+	if (sc->sc_bmx280dump) {
+		DPRINTF(sc, 1, ("%s: dig_T1: %d %04x\n",__func__,sc->sc_cal_blob.dig_T1,sc->sc_cal_blob.dig_T1));
+		DPRINTF(sc, 1, ("%s: dig_T2: %d %04x\n",__func__,sc->sc_cal_blob.dig_T2,sc->sc_cal_blob.dig_T2));
+		DPRINTF(sc, 1, ("%s: dig_T3: %d %04x\n",__func__,sc->sc_cal_blob.dig_T3,sc->sc_cal_blob.dig_T3));
+		DPRINTF(sc, 1, ("%s: dig_P1: %d %04x\n",__func__,sc->sc_cal_blob.dig_P1,sc->sc_cal_blob.dig_P1));
+		DPRINTF(sc, 1, ("%s: dig_P2: %d %04x\n",__func__,sc->sc_cal_blob.dig_P2,sc->sc_cal_blob.dig_P2));
+		DPRINTF(sc, 1, ("%s: dig_P3: %d %04x\n",__func__,sc->sc_cal_blob.dig_P3,sc->sc_cal_blob.dig_P3));
+		DPRINTF(sc, 1, ("%s: dig_P4: %d %04x\n",__func__,sc->sc_cal_blob.dig_P4,sc->sc_cal_blob.dig_P4));
+		DPRINTF(sc, 1, ("%s: dig_P5: %d %04x\n",__func__,sc->sc_cal_blob.dig_P5,sc->sc_cal_blob.dig_P5));
+		DPRINTF(sc, 1, ("%s: dig_P6: %d %04x\n",__func__,sc->sc_cal_blob.dig_P6,sc->sc_cal_blob.dig_P6));
+		DPRINTF(sc, 1, ("%s: dig_P7: %d %04x\n",__func__,sc->sc_cal_blob.dig_P7,sc->sc_cal_blob.dig_P7));
+		DPRINTF(sc, 1, ("%s: dig_P8: %d %04x\n",__func__,sc->sc_cal_blob.dig_P8,sc->sc_cal_blob.dig_P8));
+		DPRINTF(sc, 1, ("%s: dig_P9: %d %04x\n",__func__,sc->sc_cal_blob.dig_P9,sc->sc_cal_blob.dig_P9));
+
+		if (sc->sc_has_humidity) {
+			DPRINTF(sc, 1, ("%s: dig_H1: %d %02x\n",__func__,sc->sc_cal_blob.dig_H1,sc->sc_cal_blob.dig_H1));
+			DPRINTF(sc, 1, ("%s: dig_H2: %d %04x\n",__func__,sc->sc_cal_blob.dig_H2,sc->sc_cal_blob.dig_H2));
+			DPRINTF(sc, 1, ("%s: dig_H3: %d %02x\n",__func__,sc->sc_cal_blob.dig_H3,sc->sc_cal_blob.dig_H3));
+			DPRINTF(sc, 1, ("%s: dig_H4: %d %04x\n",__func__,sc->sc_cal_blob.dig_H4,sc->sc_cal_blob.dig_H4));
+			DPRINTF(sc, 1, ("%s: dig_H5: %d %04x\n",__func__,sc->sc_cal_blob.dig_H5,sc->sc_cal_blob.dig_H5));
+			DPRINTF(sc, 1, ("%s: dig_H6: %d %02x\n",__func__,sc->sc_cal_blob.dig_H6,sc->sc_cal_blob.dig_H6));
+		}
+
+		sc->sc_bmx280dump = false;
+	}
+
+	mutex_enter(&sc->sc_mutex);
+	error = iic_acquire_bus(sc->sc_tag, 0);
+	if (error) {
+		DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
+		    device_xname(sc->sc_dev), error));
+		goto out;
+	}
+
+	if (error == 0) {
+		switch (edata->sensor) {
+		case BMX280_TEMP_SENSOR:
+			/* A temperature reading does not need pressure */
+
+			error = bmx280_set_control_and_trigger(sc,
+			    bmx280_osrs_text_to_mask(sc->sc_osrs_t),
+			    0,
+			    0,
+			    bmx280_irr_text_to_mask(sc->sc_irr_samples));
+
+			if (error == 0) {
+				error = bmx280_wait_for_data(sc);
+
+				if (error == 0) {
+					error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, true);
+
+					if (error == 0) {
+						comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine);
+
+						DPRINTF(sc, 1, ("%s: Refresh compensated temp: %d - t_fine: %d\n",
+						    device_xname(sc->sc_dev), comp_temp, t_fine));
+
+						/* comp_temp is in Celcius * 100.  This converts it to microkelvin */
+
+						uint32_t q;
+
+						q = (uint32_t)comp_temp;
+						q = q + 27315;
+						q = q * 10000;
+
+						DPRINTF(sc, 1, ("%s: Refresh Q: %d\n", __func__, q));
+
+						edata->value_cur = q;
+						edata->state = ENVSYS_SVALID;
+					}
+				}
+			}
+			break;
+		case BMX280_PRESSURE_SENSOR:
+
+			/* Pressure needs the temp too */
+			error = bmx280_set_control_and_trigger(sc,
+			    bmx280_osrs_text_to_mask(sc->sc_osrs_t),
+			    bmx280_osrs_text_to_mask(sc->sc_osrs_p),
+			    0,
+			    bmx280_irr_text_to_mask(sc->sc_irr_samples));
+
+			if (error == 0) {
+				error = bmx280_wait_for_data(sc);
+
+				if (error == 0) {
+					error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, false);
+
+					if (error == 0) {
+						comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine);
+
+						DPRINTF(sc, 1, ("%s: Refresh compensated temp for pressure: %d - t_fine: %d\n",
+						    device_xname(sc->sc_dev), comp_temp, t_fine));
+
+						comp_press = bmx280_compensate_P_int64(&sc->sc_cal_blob, m_press, t_fine);
+
+						DPRINTF(sc, 1, ("%s: Refresh compensated pressure: %d\n",
+						    device_xname(sc->sc_dev), comp_press));
+
+						uint32_t q;
+
+						q = comp_press;
+						q = q / 256;
+						q = q * 100;
+
+						DPRINTF(sc, 1, ("%s: Refresh pressure Q: %d\n", __func__, q));
+
+						edata->value_cur = q;
+						edata->state = ENVSYS_SVALID;
+					}
+				}
+			}
+			break;
+
+		case BMX280_HUMIDITY_SENSOR:
+
+			/* Humidity wants temperature */
+
+			error = bmx280_set_control_and_trigger(sc,
+			    bmx280_osrs_text_to_mask(sc->sc_osrs_t),
+			    0,
+			    bmx280_osrs_text_to_mask(sc->sc_osrs_h),
+			    bmx280_irr_text_to_mask(sc->sc_irr_samples));
+
+			if (error == 0) {
+				error = bmx280_wait_for_data(sc);
+
+				if (error == 0) {
+					error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, false);
+
+					if (error == 0) {
+						comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine);
+
+						DPRINTF(sc, 1, ("%s: Refresh compensated temp for humidity: %d - t_fine: %d\n",
+						    device_xname(sc->sc_dev), comp_temp, t_fine));
+
+						comp_hum = bmx280_compensate_H_int32(&sc->sc_cal_blob, m_hum, t_fine);
+
+						DPRINTF(sc, 2, ("%s: Refresh compensated humidity: %d\n",
+						    device_xname(sc->sc_dev), comp_hum));
+
+						uint32_t q;
+
+						q = comp_hum;
+						q = q / 1024;
+						q = q * 100; /* XXX - this probably is not correct */
+
+						DPRINTF(sc, 1, ("%s: Refresh humidity Q: %d\n", __func__, q));
+
+						edata->value_cur = q;
+						edata->state = ENVSYS_SVALID;
+					}
+				}
+			}
+			break;
+		}
+	}
+
+	if (error) {
+		DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d\n",
+		    device_xname(sc->sc_dev), error));
+	}
+
+	iic_release_bus(sc->sc_tag, 0);
+out:
+	mutex_exit(&sc->sc_mutex);
+}
+
+static int
+bmx280_detach(device_t self, int flags)
+{
+	struct bmx280_sc *sc;
+
+	sc = device_private(self);
+
+	mutex_enter(&sc->sc_mutex);
+
+	/* Remove the sensors */
+	if (sc->sc_sme != NULL) {
+		sysmon_envsys_unregister(sc->sc_sme);
+		sc->sc_sme = NULL;
+	}
+	mutex_exit(&sc->sc_mutex);
+
+	/* Remove the sysctl tree */
+	sysctl_teardown(&sc->sc_bmx280log);
+
+	/* Remove the mutex */
+	mutex_destroy(&sc->sc_mutex);
+
+	return 0;
+}
+
+MODULE(MODULE_CLASS_DRIVER, bmx280thp, "iic,sysmon_envsys");
+
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
+
+static int
+bmx280thp_modcmd(modcmd_t cmd, void *opaque)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+#ifdef _MODULE
+		return config_init_component(cfdriver_ioconf_bmx280thp,
+		    cfattach_ioconf_bmx280thp, cfdata_ioconf_bmx280thp);
+#else
+		return 0;
+#endif
+	case MODULE_CMD_FINI:
+#ifdef _MODULE
+		return config_fini_component(cfdriver_ioconf_bmx280thp,
+		      cfattach_ioconf_bmx280thp, cfdata_ioconf_bmx280thp);
+#else
+		return 0;
+#endif
+	default:
+		return ENOTTY;
+	}
+}
Index: src/sys/dev/i2c/bmx280reg.h
diff -u /dev/null src/sys/dev/i2c/bmx280reg.h:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/sys/dev/i2c/bmx280reg.h	Mon Nov 21 21:24:01 2022
@@ -0,0 +1,96 @@
+/*	$NetBSD: bmx280reg.h,v 1.1 2022/11/21 21:24:01 brad Exp $	*/
+
+/*
+ * Copyright (c) 2022 Brad Spencer <b...@anduin.eldar.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_I2C_BMX280REG_H_
+#define _DEV_I2C_BMX280REG_H_
+
+#define BMX280_TYPICAL_ADDR_1	0x76
+#define BMX280_TYPICAL_ADDR_2	0x77
+
+#define BMX280_REGISTER_DIG_T1		0x88
+#define BMX280_REGISTER_DIG_T2		0x8A
+#define BMX280_REGISTER_DIG_T3		0x8C
+#define BMX280_REGISTER_DIG_P1		0x8E
+#define BMX280_REGISTER_DIG_P2		0x90
+#define BMX280_REGISTER_DIG_P3		0x92
+#define BMX280_REGISTER_DIG_P4		0x94
+#define BMX280_REGISTER_DIG_P5		0x96
+#define BMX280_REGISTER_DIG_P6		0x98
+#define BMX280_REGISTER_DIG_P7		0x9A
+#define BMX280_REGISTER_DIG_P8		0x9C
+#define BMX280_REGISTER_DIG_P9		0x9E
+#define BMX280_REGISTER_DIG_H1		0xA1
+#define BMX280_REGISTER_DIG_H2		0xE1
+#define BMX280_REGISTER_DIG_H3		0xE3
+#define BMX280_REGISTER_DIG_H4		0xE4
+#define BMX280_REGISTER_DIG_H5		0xE5
+
+#define BMX280_REGISTER_ID		0xD0
+#define BMX280_ID_BMP280		0x58
+#define BMX280_ID_BME280		0x60
+
+#define BMX280_REGISTER_RESET		0xE0
+#define BMX280_TRIGGER_RESET		0xB6
+
+#define BMX280_REGISTER_CTRL_HUM	0xF2
+
+#define BMX280_REGISTER_STATUS		0xF3
+#define BMX280_STATUS_MEASURING_MASK	0x08
+#define BMX280_STATUS_IM_UPDATE_MASK	0x01
+
+#define BMX280_REGISTER_CTRL_MEAS	0xF4
+#define BMX280_CTRL_OSRS_T_MASK		0xE0
+#define BMX280_CTRL_OSRS_P_MASK		0x1C
+#define BMX280_CTRL_OSRS_T_SHIFT	5
+#define BMX280_CTRL_OSRS_P_SHIFT	2
+#define BMX280_OSRS_TP_VALUE_SKIPPED	0x00
+#define BMX280_OSRS_TP_VALUE_X1		0x01
+#define BMX280_OSRS_TP_VALUE_X2		0x02
+#define BMX280_OSRS_TP_VALUE_X4		0x03
+#define BMX280_OSRS_TP_VALUE_X8		0x04
+#define BMX280_OSRS_TP_VALUE_X16	0x05
+#define BMX280_CTRL_MODE_MASK		0x03
+#define BMX280_MODE_SLEEP		0x00
+#define BMX280_MODE_FORCED		0x01
+#define BMX280_MODE_NORMAL		0x03
+
+#define BMX280_REGISTER_CONFIG		0xF5
+#define BMX280_CONFIG_T_SB_MASK		0xE0
+#define BMX280_CONFIG_FILTER_MASK	0x1C
+#define BMX280_CONFIG_FILTER_SHIFT	2
+#define BMX280_FILTER_VALUE_OFF		0x00
+#define BMX280_FILTER_VALUE_2		0x01
+#define BMX280_FILTER_VALUE_5		0x02
+#define BMX280_FILTER_VALUE_11		0x04
+#define BMX280_FILTER_VALUE_22		0x05
+#define BMX280_CONFIG_SPI3W_EN_MASK	0x01
+
+#define BMX280_REGISTER_PRESS_MSB	0xF7
+#define BMX280_REGISTER_PRESS_LSB	0xF8
+#define BMX280_REGISTER_PRESS_XLSB	0xF9
+
+#define BMX280_REGISTER_TEMP_MSB	0xFA
+#define BMX280_REGISTER_TEMP_LSB	0xFB
+#define BMX280_REGISTER_TEMP_XLSB	0xFC
+
+#define BMX280_TEMPPRES_XLSB_MASK	0xF0
+
+#define BMX280_REGISTER_HUM_MSB		0xFD
+#define BMX280_REGISTER_HUM_LSB		0xFE
+
+#endif
Index: src/sys/dev/i2c/bmx280var.h
diff -u /dev/null src/sys/dev/i2c/bmx280var.h:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/sys/dev/i2c/bmx280var.h	Mon Nov 21 21:24:01 2022
@@ -0,0 +1,85 @@
+/*	$NetBSD: bmx280var.h,v 1.1 2022/11/21 21:24:01 brad Exp $	*/
+
+/*
+ * Copyright (c) 2022 Brad Spencer <b...@anduin.eldar.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_I2C_BMX280VAR_H_
+#define _DEV_I2C_BMX280VAR_H_
+
+#define BMX280_NUM_SENSORS	3
+#define BMX280_TEMP_SENSOR 0
+#define BMX280_PRESSURE_SENSOR 1
+#define BMX280_HUMIDITY_SENSOR 2
+
+struct bmx280_calibration_blob {
+	uint16_t dig_T1;
+	int16_t dig_T2;
+	int16_t dig_T3;
+
+	uint16_t dig_P1;
+	int16_t dig_P2;
+	int16_t dig_P3;
+	int16_t dig_P4;
+	int16_t dig_P5;
+	int16_t dig_P6;
+	int16_t dig_P7;
+	int16_t dig_P8;
+	int16_t dig_P9;
+	uint8_t dig_H1;
+	int16_t dig_H2;
+	uint8_t dig_H3;
+	int16_t dig_H4;
+	int16_t dig_H5;
+	int8_t dig_H6;
+};
+
+struct bmx280_sc {
+	int 		sc_bmx280debug;
+	device_t 	sc_dev;
+	i2c_tag_t 	sc_tag;
+	i2c_addr_t 	sc_addr;
+	kmutex_t 	sc_mutex;
+	int 		sc_numsensors;
+	struct sysmon_envsys *sc_sme;
+	struct sysctllog *sc_bmx280log;
+	envsys_data_t 	sc_sensors[BMX280_NUM_SENSORS];
+	struct bmx280_calibration_blob	sc_cal_blob;
+	bool		sc_has_humidity;
+	int		sc_readattempts;
+	int		sc_osrs_t;
+	int		sc_osrs_p;
+	int		sc_osrs_h;
+	int		sc_irr_samples;
+	uint8_t		sc_previous_irr;
+	bool		sc_bmx280dump;
+};
+
+struct bmx280_sensor {
+	const char     *desc;
+	enum envsys_units type;
+};
+
+struct bmx280_osrs_list {
+	const int	text;
+	uint8_t		mask;
+};
+
+struct bmx280_irr_list {
+	const int	text;
+	uint8_t		mask;
+};
+
+#endif

Index: src/sys/modules/bmx280thp/Makefile
diff -u /dev/null src/sys/modules/bmx280thp/Makefile:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/sys/modules/bmx280thp/Makefile	Mon Nov 21 21:24:01 2022
@@ -0,0 +1,11 @@
+.include "../Makefile.inc"
+
+.PATH:	${S}/dev/i2c
+
+KMOD=	bmx280thp
+IOCONF=	bmx280thp.ioconf
+SRCS=	bmx280.c
+
+WARNS=	3
+
+.include <bsd.kmodule.mk>
Index: src/sys/modules/bmx280thp/bmx280thp.ioconf
diff -u /dev/null src/sys/modules/bmx280thp/bmx280thp.ioconf:1.1
--- /dev/null	Mon Nov 21 21:24:02 2022
+++ src/sys/modules/bmx280thp/bmx280thp.ioconf	Mon Nov 21 21:24:01 2022
@@ -0,0 +1,8 @@
+ioconf bmx280thp
+
+include "conf/files"
+
+pseudo-root iic*
+
+bmx280thp* at iic? addr 0x76
+bmx280thp* at iic? addr 0x77

Reply via email to