On Thu, May 03, 2018 at 09:55:21PM -0700, s_g...@telus.net wrote:
> Thank you for the updates.  I will build and test as soon as I get finished 
> with the php build.  My system is still flailing away at gtk with each ld 
> session taking about 20 minutes.  Could be days yet.
> 

fixed the diff with moving dev/fdt/bme.c to dev/i2c/bme280.c,
thanks to clue by kettenis@.

-Artturi


diff --git share/man/man4/Makefile share/man/man4/Makefile
index 8004d8b575d..3ac02b89788 100644
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -15,7 +15,7 @@ MAN=  aac.4 ac97.4 acphy.4 acrtc.4 \
        auacer.4 audio.4 aue.4 auglx.4 auich.4 auixp.4 autri.4 auvia.4 \
        axe.4 axen.4 axppmic.4 azalia.4 \
        bce.4 bcmaux.4 bcmdog.4  bcmrng.4 bcmtemp.4 berkwdt.4 bge.4 \
-       bgw.4 bio.4 bktr.4 bmtphy.4 bnx.4 \
+       bgw.4 bio.4 bktr.4 bme.4 bmtphy.4 bnx.4 \
        boca.4 bpf.4 brgphy.4 bridge.4 brswphy.4 bwfm.4 bwi.4 bytgpio.4 \
        cac.4 cas.4 cardbus.4 carp.4 ccp.4 cd.4 cdce.4 cfxga.4 \
        ch.4 chvgpio.4 ciphy.4 ciss.4 clcs.4 clct.4 cmpci.4 \
diff --git share/man/man4/bme.4 share/man/man4/bme.4
new file mode 100644
index 00000000000..bb48513d9dc
--- /dev/null
+++ share/man/man4/bme.4
@@ -0,0 +1,44 @@
+.\"    $OpenBSD: tsl.4,v 1.10 2015/10/02 09:29:02 sobrado Exp $
+.\"
+.\" Copyright (c) 2005 Mark Kettenis <kette...@openbsd.org>
+.\" Copyright (c) 2018 Artturi Alm
+.\"
+.\" 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 $Mdocdate$
+.Dt BME 4
+.Os
+.Sh NAME
+.Nm bme
+.Nd Bosch BME280 Environmental sensor
+.Sh SYNOPSIS
+.Cd "bme* at iic?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Bosch BME280 Environmental sensor.
+These sensors contain combined digital humidity, pressure and temperature
+sensing capabilities.
+These values are made available through the
+.Xr sysctl 8
+interface.
+.Sh SEE ALSO
+.Xr iic 4 ,
+.Xr intro 4 ,
+.Xr sensorsd 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 6.4 .
diff --git sys/dev/i2c/bme280.c sys/dev/i2c/bme280.c
new file mode 100644
index 00000000000..8d35f5ae44d
--- /dev/null
+++ sys/dev/i2c/bme280.c
@@ -0,0 +1,543 @@
+/*     $OpenBSD: tsl2560.c,v 1.7 2008/04/18 01:17:51 deraadt Exp $     */
+
+/*
+ * Copyright (c) 2005 Mark Kettenis
+ * Copyright (c) 2017 Artturi Alm
+ *
+ * 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/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kthread.h>
+#include <sys/sensors.h>
+
+#include <dev/i2c/i2cvar.h>
+
+/*
+ * Register Name       Address b7 b6 b5 b4 b3 b2 b1 b0         Reset state
+ * hum_lsb             0xFE    hum_lsb<7:0>                    0x00
+ * hum_msb             0xFD    hum_msb<7:0>                    0x80
+ * temp_xlsb           0xFC    temp_xlsb<7:4>  0000            0x00
+ * temp_lsb            0xFB    temp_lsb<7:0>                   0x00
+ * temp_msb            0xFA    temp_msb<7:0>                   0x80
+ * press_xlsb          0xF9    press_xlsb<7:4> 0000            0x00
+ * press_lsb           0xF8    press_lsb<7:0>                  0x00
+ * press_msb           0xF7    press_msb<7:0>                  0x80
+ * config              0xF5    t_sb[2:0]filter[2:0]spi3w_en[0] 0x00
+ * ctrl_meas           0xF4    osrs_p[2:0]osrs_t[2:0]mode[1:0] 0x00
+ * status              0xF3    measuring[0]im_update[0]        0x00
+ * ctrl_hum            0xF2    osrs_h[2:0]                     0x00
+ * calib26..calib41    0xE1-0xF0       calibration data        individual
+ * reset               0xE0    reset[7:0]                      0x00
+ * id                  0xD0    chip_id[7:0]                    0x60
+ * calib00..calib25    0x88-0xA1       calibration data        individual
+*/
+
+#define        BME280_CALIB00_23       0x88
+#define        BME280_CALIB24          0xa1
+#define        BME280_ID               0xd0
+#define        BME280_RESET            0xe0
+       /* soft reset magic value */
+#define        BME280_RESET_MAGIC      0xb6
+#define        BME280_CALIB25_31       0xe1
+       /* changes become effective only after a write op to ctrl_meas */
+#define        BME280_CTRL_HUM         0xf2
+
+#define        BME280_STATUS           0xf3
+#define        BME280_STATUS_MASK      0x09
+#define        BME280_STATUS_CONV      0x08    /* conversion running */
+#define        BME280_STATUS_UPD       0x01    /* update in progress */
+
+#define        BME280_CTRL_MEAS                0xf4
+#define        BME280_CTRL_MEAS_MODE_MASK      0x03
+#define        BME280_CTRL_MEAS_MODE_SLEEP     0x00
+#define        BME280_CTRL_MEAS_MODE_FORCED    0x01
+#define        BME280_CTRL_MEAS_MODE_FORCE     0x02
+#define        BME280_CTRL_MEAS_MODE_NORMAL    0x03
+       /* writes in normal mode may be ignored, not so in sleep mode */
+#define        BME280_CONFIG           0xf5
+#define        BME280_CONFIG_SPI_EN    0x01
+
+#define        BME280_PRESS_MSB        0xf7
+#define        BME280_PRESS_LSB        0xf8
+#define        BME280_PRESS_XLSB       0xf9
+#define        BME280_TEMP_MSB         0xfa
+#define        BME280_TEMP_LSB         0xfb
+#define        BME280_TEMP_XLSB        0xfc
+#define        BME280_HUM_MSB          0xfd
+#define        BME280_HUM_LSB          0xfe
+
+#define        BME_OVERSAMPLING_SKIP   0x00
+#define        BME_OVERSAMPLING_X1     0x01
+#define        BME_OVERSAMPLING_X2     0x02
+#define        BME_OVERSAMPLING_X4     0x03
+#define        BME_OVERSAMPLING_X8     0x04
+#define        BME_OVERSAMPLING_X16    0x05
+
+#define        BME_HUMI        0
+#define        BME_TEMP        1
+#define        BME_PRES        2
+
+struct bme_softc {
+       struct device           sc_dev;
+       i2c_tag_t               sc_i2c;
+       i2c_addr_t              sc_addr;
+
+       struct ksensor          sc_sensor[3];
+       struct ksensordev       sc_sensordev;
+
+       int                     sc_calibrated;
+       int                     sc_configured;
+
+       /*
+        * fine resolution temperature value for pressure and
+        * humidity compensation formulas.
+        */
+       int32_t                 sc_t_fine;
+       /* calibration data */
+       int32_t                 sc_t_trim[3];
+       int64_t                 sc_p_trim[9];
+       int32_t                 sc_h_trim[6];
+};
+
+int    bme_match(struct device *, void *, void *);
+void   bme_attach(struct device *, struct device *, void *);
+void   bme_deferred(void *);
+void   bme_refresh(void *);
+void   bme_softreset(struct bme_softc *, int);
+void   bme_configure(struct bme_softc *, int);
+void   bme_get_calib(struct bme_softc *, int);
+
+int32_t                bme_comp_temp(struct bme_softc *, int32_t);
+uint32_t       bme_comp_pres(struct bme_softc *, int32_t);
+uint32_t       bme_comp_humi(struct bme_softc *, int32_t);
+
+static inline uint8_t  bme_config_filter(int);
+static inline uint8_t  bme_config_standby(int);
+static inline uint8_t  bme_oversample(uint8_t, uint8_t);
+
+struct cfattach bme_ca = {
+       sizeof(struct bme_softc), bme_match, bme_attach
+};
+
+struct cfdriver bme_cd = {
+       NULL, "bme", DV_DULL
+};
+
+int
+bme_match(struct device *parent, void *match, void *aux)
+{
+       struct i2c_attach_args *ia = aux;
+
+       if (strcmp(ia->ia_name, "bosch,bme280") == 0)
+               return 1;
+
+       return 0;
+}
+
+void
+bme_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct bme_softc *sc = (struct bme_softc *)self;
+       struct i2c_attach_args *ia = aux;
+       int ieflags = I2C_F_POLL;
+       uint8_t reg_addr, data;
+
+       sc->sc_i2c = ia->ia_tag;
+       sc->sc_addr = ia->ia_addr;
+
+       iic_acquire_bus(sc->sc_i2c, ieflags);
+
+       sc->sc_calibrated = 0;
+       bme_softreset(sc, ieflags);
+
+       reg_addr = BME280_ID;
+       if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+           sc->sc_addr, &reg_addr, 1, &data, 1, ieflags)) {
+               iic_release_bus(sc->sc_i2c, ieflags);
+               printf(": failed to read ID register\n");
+               return;
+       }
+
+       iic_release_bus(sc->sc_i2c, ieflags);
+
+        switch (data) {
+       default:
+               printf(": unknown value in ID register 0x%x\n", data);
+               return;
+       case 0x58:
+       case 0x57:
+       case 0x56:
+               /* XXX atleast somehow register compatible with BMP280 */
+               printf(": sorry, no BMP280 support yet\n");
+               return;
+       case 0x60:
+               printf(": BME280 %x\n", data);
+               break;
+       }
+
+       kthread_create_deferred(bme_deferred, sc);
+}
+
+void
+bme_deferred(void *arg)
+{
+       struct bme_softc *sc = arg;
+       int ieflags = I2C_F_POLL; /* XXX cold ? I2C_F_POLL : 0 */
+       int i;
+
+       iic_acquire_bus(sc->sc_i2c, ieflags);
+
+       bme_configure(sc, ieflags);
+#ifdef DIAGNOSTIC
+       if (sc->sc_configured != 1)     /* non-fatal */
+               printf("%s: failed to configure\n", sc->sc_dev.dv_xname);
+#endif
+
+       bme_get_calib(sc, ieflags);
+
+       iic_release_bus(sc->sc_i2c, ieflags);
+
+       if (sc->sc_calibrated != 1) {
+               printf("%s: failed to read calibration data\n",
+                   sc->sc_dev.dv_xname);
+               /* fatal; and retrying feels bloat, fix your i2c "wiring" */
+               return; /* XXX can't defer failure to config_detach.. :( */
+       }
+
+       if (sensor_task_register(sc, bme_refresh, 1) == NULL) {
+               printf("%s: unable to register update task\n",
+                   sc->sc_dev.dv_xname);
+               return;
+       }
+
+       /* Initialize sensor data. */
+       strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
+           sizeof(sc->sc_sensordev.xname));
+       sc->sc_sensor[BME_HUMI].type = SENSOR_HUMIDITY;
+       sc->sc_sensor[BME_TEMP].type = SENSOR_TEMP;
+       sc->sc_sensor[BME_PRES].type = SENSOR_PRESSURE;
+
+       for (i = 0; i < 3; i++) {
+               sc->sc_sensor[i].flags = SENSOR_FINVALID;
+               sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
+       }
+       sensordev_install(&sc->sc_sensordev);
+}
+
+void
+bme_refresh(void *arg)
+{
+       struct bme_softc *sc = arg;
+       int32_t raw[3] = { 0, 0, 0 };
+       int ieflags = I2C_F_POLL; /* XXX cold ? I2C_F_POLL : 0 */
+       uint8_t addr;
+       uint8_t data[8];
+
+       iic_acquire_bus(sc->sc_i2c, ieflags);
+
+       if (sc->sc_configured == 0) {
+               bme_configure(sc, ieflags);
+               if (sc->sc_configured != 1) {
+#ifdef DIAGNOSTIC
+                       printf("%s: failed to configure - resetting\n",
+                           sc->sc_dev.dv_xname);
+#endif
+                       bme_softreset(sc, ieflags);
+                       goto fail_out;
+               }
+       }
+
+       /*
+        * read raw uncompensated values in a single read "burst",
+        * to keep data register shadowing functional in the normal-mode
+        * we're configured to, as we don't really synchronize with the
+        * sensor, so we have no need to read the status register at all.
+        */
+       addr = BME280_PRESS_MSB;
+       if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+           sc->sc_addr, &addr, 1, &data, sizeof data, ieflags)) {
+               printf("%s: failed to read data - resetting\n",
+                   sc->sc_dev.dv_xname);
+               bme_softreset(sc, ieflags);
+               bme_configure(sc, ieflags);
+               goto fail_out;
+        }
+
+       iic_release_bus(sc->sc_i2c, ieflags);
+
+       /* got raw */
+       raw[BME_HUMI] = (data[6] << 8) | data[7];
+       raw[BME_TEMP] = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
+       raw[BME_PRES] = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
+
+       /* do compensate raw values */
+       sc->sc_sensor[BME_TEMP].value = bme_comp_temp(sc, raw[BME_TEMP]);
+       sc->sc_sensor[BME_PRES].value = bme_comp_pres(sc, raw[BME_PRES]);
+       sc->sc_sensor[BME_HUMI].value = bme_comp_humi(sc, raw[BME_HUMI]);
+
+       sc->sc_sensor[BME_TEMP].flags &= ~SENSOR_FINVALID;
+       sc->sc_sensor[BME_PRES].flags &= ~SENSOR_FINVALID;
+       sc->sc_sensor[BME_HUMI].flags &= ~SENSOR_FINVALID;
+       return;
+fail_out:
+       iic_release_bus(sc->sc_i2c, ieflags);
+       sc->sc_sensor[BME_TEMP].flags |= SENSOR_FINVALID;
+       sc->sc_sensor[BME_PRES].flags |= SENSOR_FINVALID;
+       sc->sc_sensor[BME_HUMI].flags |= SENSOR_FINVALID;
+}
+
+void
+bme_get_calib(struct bme_softc *sc, int ieflags)
+{
+       int i, j;
+       uint8_t addr;
+       uint8_t calib[32];
+
+       /* read calibration data */
+       addr = BME280_CALIB00_23;
+       if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+           sc->sc_addr, &addr, 1, &calib[0], 24, ieflags))
+               return;
+
+       addr = BME280_CALIB24;
+       if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+           sc->sc_addr, &addr, 1, &calib[24], 1, ieflags))
+               return;
+
+       addr = BME280_CALIB25_31;
+       if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+           sc->sc_addr, &addr, 1, &calib[25], 7, ieflags))
+               return;
+
+       /* adjust calibration data for later compensations */
+       for (i = 0, j = 0; i < 3; j += 2)
+               sc->sc_t_trim[i++] = (calib[j + 1] << 8) | calib[j];
+       for (i = 0, j = 6; i < 9; j += 2)
+               sc->sc_p_trim[i++] = (calib[j + 1] << 8) | calib[j];
+       sc->sc_h_trim[(i = 0)] = calib[24];
+       sc->sc_h_trim[++i] = (calib[26] << 8) | calib[25];
+       sc->sc_h_trim[++i] = calib[27];
+       sc->sc_h_trim[++i] = (calib[28] << 4) | (calib[29] & 0xf);
+       sc->sc_h_trim[++i] = (calib[30] << 4) | ((calib[29] & 0xf0) >> 4);
+       sc->sc_h_trim[++i] = calib[31];
+
+       for (i = 1; i < 3; i++)
+               if (sc->sc_t_trim[i] & 0x8000)
+                       sc->sc_t_trim[i] = (-sc->sc_t_trim[i] ^ 0xffff) + 1;
+       for (j = 1; j < 9; j++)
+               if (sc->sc_p_trim[j] & 0x8000)
+                       sc->sc_p_trim[j] = (-sc->sc_p_trim[j] ^ 0xffff) + 1;
+       for (i = 1; i < 6; i++)         /* XXX last one is signed char? */
+               if (sc->sc_h_trim[i] & 0x8000) /* so will never match this */
+                       sc->sc_h_trim[i] = (-sc->sc_h_trim[i] ^ 0xffff) + 1;
+
+       sc->sc_calibrated = 1;
+}
+
+/*
+ * this is not really required, as the chip should be in this
+ * condition already after Power-On-Reset (POR), and we configure
+ * everything without reading current values in correct order,
+ * so i decided to let this fail as void, trusting sc_configured=0 will
+ * fix configuration registers later anyway.
+ */
+void
+bme_softreset(struct bme_softc *sc, int ieflags)
+{
+       uint8_t addr = BME280_RESET;
+       uint8_t data = BME280_RESET_MAGIC;
+
+       sc->sc_configured = 0;
+
+        if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
+            sc->sc_addr, &addr, 1, &data, 1, ieflags)) {
+#ifdef DIAGNOSTIC
+               printf("%s: failed to write softreset\n", sc->sc_dev.dv_xname);
+#endif
+               return;
+       }
+       /*
+        * XXX should this have some delay here? SoC-performance do vary..
+        */
+}
+
+void
+bme_configure(struct bme_softc *sc, int ieflags)
+{
+       uint8_t addr, data;
+
+       /* XXX do seek for devicetree bindings, for config parameters */
+
+       addr = BME280_CTRL_HUM;
+       data = bme_oversample(1, BME_HUMI);
+       if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
+           sc->sc_addr, &addr, 1, &data, 1, ieflags))
+               return;
+
+       addr = BME280_CONFIG;
+       data = bme_config_filter(0) | bme_config_standby(1000000);
+       if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
+           sc->sc_addr, &addr, 1, &data, 1, ieflags))
+               return;
+
+       addr = BME280_CTRL_MEAS;
+       data = BME280_CTRL_MEAS_MODE_NORMAL | bme_oversample(1, BME_TEMP) |
+           bme_oversample(1, BME_PRES);
+       if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
+           sc->sc_addr, &addr, 1, &data, 1, ieflags))
+               return;
+
+       sc->sc_configured = 1;
+}
+
+int32_t
+bme_comp_temp(struct bme_softc *sc, int32_t raw)
+{
+       int32_t t1 = sc->sc_t_trim[0];
+       int32_t t2 = sc->sc_t_trim[1];
+       int32_t t3 = sc->sc_t_trim[2];
+       int32_t var1  = ((((raw >> 3) - (t1 << 1))) * t2) >> 11;
+       int32_t var2  = (((((raw >> 4) - t1) * ((raw >> 4) - t1)) >> 12) * t3)
+           >> 14;
+       int32_t rv_t;
+
+       sc->sc_t_fine = var1 + var2;
+       rv_t = (sc->sc_t_fine * 5 + 128) >> 8;
+       rv_t = (rv_t + 27315) * 10000;  /* for micro Kelvin */
+       return rv_t;
+}
+
+uint32_t
+bme_comp_pres(struct bme_softc *sc, int32_t raw)
+{
+       int64_t var1 = (int64_t)sc->sc_t_fine;
+       int64_t var2;
+       int64_t pa;
+
+       var1 -= 128000;
+       var2 = var1 * var1 * sc->sc_p_trim[5];
+       var2 = var2 + ((var1 * sc->sc_p_trim[4]) << 17);
+       var2 = var2 + (sc->sc_p_trim[3] << 35);
+
+       var1 = ((var1 * var1 * sc->sc_p_trim[2]) >> 8) +
+           ((var1 * sc->sc_p_trim[1]) << 12);
+
+       var1 = ((((int64_t)1) << 47) + var1) * sc->sc_p_trim[0] >> 33;
+       if (var1 == 0)
+               return 0;
+
+       pa = 1048576 - raw;
+       pa = (((pa << 31) - var2) * 3125) / var1;
+       var1 = (sc->sc_p_trim[8] * (pa >> 13) * (pa >> 13)) >> 25;
+       var2 = (sc->sc_p_trim[7] * pa) >> 19;
+       pa = ((pa + var1 + var2) >> 8) + (sc->sc_p_trim[6] << 4);
+       pa /= 256;
+       return (uint32_t)pa;
+}
+
+uint32_t
+bme_comp_humi(struct bme_softc *sc, int32_t raw)
+{
+       int32_t rh = (int32_t)sc->sc_t_fine;
+
+       rh -= 76800;
+       rh = (((((raw << 14) - (sc->sc_h_trim[3] << 20) -
+           (sc->sc_h_trim[4] * rh)) + 16384) >> 15) *
+           (((((((rh * sc->sc_h_trim[5]) >> 10) *
+           (((rh * sc->sc_h_trim[2]) >> 11) + 32768)) >> 10) +
+           2097152) * sc->sc_h_trim[1] + 8192) >> 14));
+       rh -= (((((rh >> 15) * (rh >> 15)) >> 7) * sc->sc_h_trim[0]) >> 4);
+       if (rh < 0)
+               rh = 0;
+       if (rh > 419430400)
+               rh = 419430400;
+       rh >>= 12;
+       rh = (rh * 1000) / 1024;
+       return (uint32_t)rh;
+}
+
+uint8_t
+bme_config_filter(int filter_coeff)
+{
+       switch (filter_coeff) {
+       default:
+       case 0: /* filter off */
+               return 0x00;
+       case 2:
+               return 0x01;
+       case 4:
+               return 0x02;
+       case 8:
+               return 0x03;
+       case 16:
+               return 0x04;
+       }
+}
+
+uint8_t
+bme_config_standby(int us)
+{
+       switch (us) {
+       case 500:
+               return 0x00U << 5;
+       case 10000:
+               return 0x06U << 5;
+       case 20000:
+               return 0x07U << 5;
+       case 62500:
+               return 0x01U << 5;
+       case 125000:
+               return 0x02U << 5;
+       case 250000:
+               return 0x03U << 5;
+       case 500000:
+               return 0x04U << 5;
+       default:
+       case 1000000:
+               return 0x05U << 5;
+       }
+}
+
+uint8_t
+bme_oversample(uint8_t over_sample, uint8_t sensor)
+{
+       uint8_t off = 0;
+
+       switch (sensor) {
+       case BME_PRES:
+               off += 3;
+       case BME_TEMP:
+               off += 2;
+       case BME_HUMI:
+               break;
+       default:
+               return 0;
+       }
+
+       switch (over_sample) {
+       default:
+       case 0:
+               return BME_OVERSAMPLING_SKIP;
+       case 1:
+               return BME_OVERSAMPLING_X1 << off;
+       case 2:
+               return BME_OVERSAMPLING_X2 << off;
+       case 4:
+               return BME_OVERSAMPLING_X4 << off;
+       case 16:
+               return BME_OVERSAMPLING_X16 << off;
+       }
+}
diff --git sys/dev/i2c/files.i2c sys/dev/i2c/files.i2c
index 10f5bc63fa8..edb070bd11a 100644
--- sys/dev/i2c/files.i2c
+++ sys/dev/i2c/files.i2c
@@ -220,6 +220,11 @@ device     bgw
 attach bgw at i2c
 file dev/i2c/bmc150.c                          bgw
 
+# Bosch BME280 environmental sensor
+device bme
+attach bme at i2c
+file   dev/i2c/bme280.c                        bme
+
 # Intersil ISL1208 Real Time Clock
 device islrtc
 attach islrtc at i2c
diff --git sys/arch/armv7/conf/GENERIC sys/arch/armv7/conf/GENERIC
index 052f73bf71f..59d314e5909 100644
--- sys/arch/armv7/conf/GENERIC
+++ sys/arch/armv7/conf/GENERIC
@@ -179,6 +179,7 @@ rktemp*             at fdt?
 dwdog*         at fdt?
 
 axppmic*       at iic?                 # axp209 pmic
+bme*           at iic?                 # BME280 environmental sensor
 crosec*                at iic?
 wskbd*         at crosec? mux 1
 pcfrtc*                at iic?

Reply via email to