summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorbrad <brad@NetBSD.org>2022-12-03 01:04:42 +0000
committerbrad <brad@NetBSD.org>2022-12-03 01:04:42 +0000
commit02b8954fe89d72e580aac9928e8f0dd91cabaedc (patch)
tree3d66e5b9ef8e2812eb0fd4eb5c10499ac92a1975 /sys
parenta76f61463de79fb55af1db5ff83b1f68aeca0073 (diff)
Split the BMP280 / BME280 driver into common code and create I2C and
SPI attachments.
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files6
-rw-r--r--sys/dev/i2c/bmx280thpi2c.c264
-rw-r--r--sys/dev/i2c/files.i2c7
-rw-r--r--sys/dev/ic/bmx280.c (renamed from sys/dev/i2c/bmx280.c)210
-rw-r--r--sys/dev/ic/bmx280reg.h (renamed from sys/dev/i2c/bmx280reg.h)6
-rw-r--r--sys/dev/ic/bmx280var.h (renamed from sys/dev/i2c/bmx280var.h)12
-rw-r--r--sys/dev/spi/bmx280thpspi.c205
-rw-r--r--sys/dev/spi/files.spi6
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/bmx280thp/Makefile2
-rw-r--r--sys/modules/bmx280thp/bmx280thp.ioconf5
-rw-r--r--sys/modules/bmx280thpi2c/Makefile11
-rw-r--r--sys/modules/bmx280thpi2c/bmx280thpi2c.ioconf8
13 files changed, 555 insertions, 190 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 136de51c53c..7e035fcdc14 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.1303 2022/11/05 17:31:38 jmcneill Exp $
+# $NetBSD: files,v 1.1304 2022/12/03 01:04:42 brad Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20171118
@@ -437,6 +437,10 @@ file dev/ic/ssdfb.c ssdfb
device scmd
file dev/ic/scmd.c scmd
+# Bosch BMP280 / BME280 sensor (attaches via I2C or SPI)
+device bmx280thp
+file dev/ic/bmx280.c bmx280thp
+
# Generic HID support (used by USB, bluetooth and i2c)
include "dev/hid/files.hid"
diff --git a/sys/dev/i2c/bmx280thpi2c.c b/sys/dev/i2c/bmx280thpi2c.c
new file mode 100644
index 00000000000..f381b2a6f1e
--- /dev/null
+++ b/sys/dev/i2c/bmx280thpi2c.c
@@ -0,0 +1,264 @@
+/* $NetBSD: bmx280thpi2c.c,v 1.1 2022/12/03 01:04:43 brad Exp $ */
+
+/*
+ * Copyright (c) 2022 Brad Spencer <brad@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: bmx280thpi2c.c,v 1.1 2022/12/03 01:04:43 brad Exp $");
+
+/*
+ * I2C driver for the Bosch BMP280 / BME280 sensor.
+ * Uses the common bmx280thp driver to do the real work.
+*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/pool.h>
+#include <sys/kmem.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/i2c/i2cvar.h>
+#include <dev/spi/spivar.h>
+#include <dev/ic/bmx280reg.h>
+#include <dev/ic/bmx280var.h>
+
+extern void bmx280_attach(struct bmx280_sc *);
+
+static int bmx280thpi2c_poke(i2c_tag_t, i2c_addr_t, bool);
+static int bmx280thpi2c_match(device_t, cfdata_t, void *);
+static void bmx280thpi2c_attach(device_t, device_t, void *);
+static int bmx280thpi2c_detach(device_t, int);
+
+#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(bmx280thpi2c, sizeof(struct bmx280_sc),
+ bmx280thpi2c_match, bmx280thpi2c_attach, bmx280thpi2c_detach, NULL);
+
+/* 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
+bmx280thpi2c_read_register_direct(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg,
+ uint8_t *buf, size_t blen)
+{
+ int error;
+
+ 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
+bmx280thpi2c_read_register(struct bmx280_sc *sc, uint8_t reg,
+ uint8_t *buf, size_t blen)
+{
+ int error;
+
+ KASSERT(blen > 0);
+
+ error = bmx280thpi2c_read_register_direct(sc->sc_tag, sc->sc_addr, reg,
+ buf, blen);
+
+ return error;
+}
+
+/* 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
+bmx280thpi2c_write_register(struct bmx280_sc *sc,
+ 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(sc->sc_tag,I2C_OP_WRITE_WITH_STOP,sc->sc_addr,NULL,0,
+ buf,blen,0);
+
+ return error;
+}
+
+static int
+bmx280thpi2c_acquire_bus(struct bmx280_sc *sc)
+{
+ return(iic_acquire_bus(sc->sc_tag, 0));
+}
+
+static void
+bmx280thpi2c_release_bus(struct bmx280_sc *sc)
+{
+ iic_release_bus(sc->sc_tag, 0);
+}
+
+static int
+bmx280thpi2c_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug)
+{
+ uint8_t reg = BMX280_REGISTER_ID;
+ uint8_t buf[1];
+ int error;
+
+ error = bmx280thpi2c_read_register_direct(tag, addr, reg, buf, 1);
+ if (matchdebug) {
+ printf("poke X 1: %d\n", error);
+ }
+ return error;
+}
+
+static int
+bmx280thpi2c_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 = bmx280thpi2c_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
+bmx280thpi2c_attach(device_t parent, device_t self, void *aux)
+{
+ struct bmx280_sc *sc;
+ struct i2c_attach_args *ia;
+
+ 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_func_acquire_bus = &bmx280thpi2c_acquire_bus;
+ sc->sc_func_release_bus = &bmx280thpi2c_release_bus;
+ sc->sc_func_read_register = &bmx280thpi2c_read_register;
+ sc->sc_func_write_register = &bmx280thpi2c_write_register;
+
+ mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
+
+ bmx280_attach(sc);
+
+ return;
+}
+
+static int
+bmx280thpi2c_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, bmx280thpi2c, "iic,bmx280thp");
+
+#ifdef _MODULE
+/* Like other drivers, we do this because the bmx280 common
+ * driver has the definitions already.
+ */
+#undef CFDRIVER_DECL
+#define CFDRIVER_DECL(name, class, attr)
+#include "ioconf.c"
+#endif
+
+static int
+bmx280thpi2c_modcmd(modcmd_t cmd, void *opaque)
+{
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+#ifdef _MODULE
+ return config_init_component(cfdriver_ioconf_bmx280thpi2c,
+ cfattach_ioconf_bmx280thpi2c, cfdata_ioconf_bmx280thpi2c);
+#else
+ return 0;
+#endif
+ case MODULE_CMD_FINI:
+#ifdef _MODULE
+ return config_fini_component(cfdriver_ioconf_bmx280thpi2c,
+ cfattach_ioconf_bmx280thpi2c, cfdata_ioconf_bmx280thpi2c);
+#else
+ return 0;
+#endif
+ default:
+ return ENOTTY;
+ }
+}
diff --git a/sys/dev/i2c/files.i2c b/sys/dev/i2c/files.i2c
index 6e10edb7429..c1c61c5f4c9 100644
--- a/sys/dev/i2c/files.i2c
+++ b/sys/dev/i2c/files.i2c
@@ -1,4 +1,4 @@
-# $NetBSD: files.i2c,v 1.125 2022/11/21 21:24:01 brad Exp $
+# $NetBSD: files.i2c,v 1.126 2022/12/03 01:04:43 brad Exp $
obsolete defflag opt_i2cbus.h I2C_SCAN
define i2cbus { }
@@ -437,6 +437,5 @@ 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
+attach bmx280thp at iic with bmx280thpi2c
+file dev/i2c/bmx280thpi2c.c bmx280thpi2c
diff --git a/sys/dev/i2c/bmx280.c b/sys/dev/ic/bmx280.c
index 5a8e402ce68..8cd4dcf0b09 100644
--- a/sys/dev/i2c/bmx280.c
+++ b/sys/dev/ic/bmx280.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bmx280.c,v 1.6 2022/12/01 02:29:37 brad Exp $ */
+/* $NetBSD: bmx280.c,v 1.1 2022/12/03 01:04:43 brad Exp $ */
/*
* Copyright (c) 2022 Brad Spencer <brad@anduin.eldar.org>
@@ -17,11 +17,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bmx280.c,v 1.6 2022/12/01 02:29:37 brad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bmx280.c,v 1.1 2022/12/03 01:04:43 brad Exp $");
/*
- Driver for the Bosch BMP280/BME280 temperature, humidity (sometimes) and
- (usually barometric) pressure sensor
+ * Common driver for the Bosch BMP280/BME280 temperature, humidity (sometimes) and
+ * (usually barometric) pressure sensor. Calls out to specific frontends to
+ * the move bits around.
*/
#include <sys/param.h>
@@ -34,21 +35,15 @@ __KERNEL_RCSID(0, "$NetBSD: bmx280.c,v 1.6 2022/12/01 02:29:37 brad Exp $");
#include <sys/proc.h>
#include <dev/sysmon/sysmonvar.h>
+#include <dev/spi/spivar.h>
#include <dev/i2c/i2cvar.h>
-#include <dev/i2c/bmx280reg.h>
-#include <dev/i2c/bmx280var.h>
+#include <dev/ic/bmx280reg.h>
+#include <dev/ic/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);
+void bmx280_attach(struct bmx280_sc *);
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);
@@ -65,9 +60,6 @@ static int bmx280_verify_sysctl_irr(SYSCTLFN_ARGS);
#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",
@@ -283,67 +275,6 @@ bmx280_store_raw_blob_h(struct bmx280_sc *sc, uint8_t *b) {
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)
{
@@ -351,6 +282,8 @@ bmx280_sysctl_init(struct bmx280_sc *sc)
const struct sysctlnode *cnode;
int sysctlroot_num, sysctlwait_num;
+ sc->sc_func_attach = &bmx280_attach;
+
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,
@@ -446,54 +379,13 @@ bmx280_sysctl_init(struct bmx280_sc *sc)
return 0;
}
-
-static int
-bmx280_match(device_t parent, cfdata_t match, void *aux)
+void
+bmx280_attach(struct bmx280_sc *sc)
{
- 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;
@@ -513,33 +405,33 @@ bmx280_attach(device_t parent, device_t self, void *aux)
sc->sc_numsensors = __arraycount(bmx280_sensors);
if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
- aprint_error_dev(self,
+ aprint_error_dev(sc->sc_dev,
"Unable to create sysmon structure\n");
sc->sc_sme = NULL;
return;
}
- error = iic_acquire_bus(sc->sc_tag, 0);
+ error = (*(sc->sc_func_acquire_bus))(sc);
if (error) {
- aprint_error_dev(self, "Could not acquire iic bus: %d\n",
+ aprint_error_dev(sc->sc_dev, "Could not acquire the 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);
+ error = (*(sc->sc_func_write_register))(sc, buf, 2);
if (error) {
- aprint_error_dev(self, "Failed to reset chip: %d\n",
+ aprint_error_dev(sc->sc_dev, "Failed to reset chip: %d\n",
error);
}
delay(30000);
reg = BMX280_REGISTER_ID;
- error = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, &chip_id, 1);
+ error = (*(sc->sc_func_read_register))(sc, reg, &chip_id, 1);
if (error) {
- aprint_error_dev(self, "Failed to read ID: %d\n",
+ aprint_error_dev(sc->sc_dev, "Failed to read ID: %d\n",
error);
}
@@ -553,15 +445,15 @@ bmx280_attach(device_t parent, device_t self, void *aux)
}
if ((error = bmx280_sysctl_init(sc)) != 0) {
- aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error);
+ aprint_error_dev(sc->sc_dev, "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);
+ error = (*(sc->sc_func_read_register))(sc, reg, raw_blob_tp, 24);
if (error) {
- aprint_error_dev(self, "Failed to read the calibration registers for tp: %d\n",
+ aprint_error_dev(sc->sc_dev, "Failed to read the calibration registers for tp: %d\n",
error);
}
@@ -578,16 +470,16 @@ bmx280_attach(device_t parent, device_t self, void *aux)
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);
+ error = (*(sc->sc_func_read_register))(sc, reg, raw_blob_h, 1);
if (error) {
- aprint_error_dev(self, "Failed to read the calibration registers for h1: %d\n",
+ aprint_error_dev(sc->sc_dev, "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);
+ error = (*(sc->sc_func_read_register))(sc, reg, &raw_blob_h[1], 7);
if (error) {
- aprint_error_dev(self, "Failed to read the calibration registers for h2 - h6: %d\n",
+ aprint_error_dev(sc->sc_dev, "Failed to read the calibration registers for h2 - h6: %d\n",
error);
}
@@ -601,10 +493,10 @@ bmx280_attach(device_t parent, device_t self, void *aux)
bmx280_store_raw_blob_h(sc,raw_blob_h);
}
- iic_release_bus(sc->sc_tag, 0);
+ (*(sc->sc_func_release_bus))(sc);
if (error != 0) {
- aprint_error_dev(self, "Unable to setup device\n");
+ aprint_error_dev(sc->sc_dev, "Unable to setup device\n");
goto out;
}
@@ -626,7 +518,7 @@ bmx280_attach(device_t parent, device_t self, void *aux)
error = sysmon_envsys_sensor_attach(sc->sc_sme,
&sc->sc_sensors[i]);
if (error) {
- aprint_error_dev(self,
+ aprint_error_dev(sc->sc_dev,
"Unable to attach sensor %d: %d\n", i, error);
goto out;
}
@@ -639,14 +531,14 @@ bmx280_attach(device_t parent, device_t self, void *aux)
DPRINTF(sc, 2, ("bmx280_attach: registering with envsys\n"));
if (sysmon_envsys_register(sc->sc_sme)) {
- aprint_error_dev(self,
+ aprint_error_dev(sc->sc_dev,
"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",
+ aprint_normal_dev(sc->sc_dev, "Bosch Sensortec %s, Chip ID: 0x%02x\n",
(chip_id == BMX280_ID_BMP280) ? "BMP280" : (chip_id == BMX280_ID_BME280) ? "BME280" : "Unknown chip",
chip_id);
@@ -763,7 +655,7 @@ bmx280_set_control_and_trigger(struct bmx280_sc *sc,
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);
+ error = (*(sc->sc_func_write_register))(sc, cr, s);
if (error) {
DPRINTF(sc, 2, ("%s: write control registers: %d\n",
device_xname(sc->sc_dev), error));
@@ -803,7 +695,7 @@ bmx280_wait_for_data(struct bmx280_sc *sc)
reg = BMX280_REGISTER_STATUS;
do {
delay(1000);
- ierror = bmx280_read_register(sc->sc_tag, sc->sc_addr, &reg, &running, 1);
+ ierror = (*(sc->sc_func_read_register))(sc, reg, &running, 1);
if (ierror) {
DPRINTF(sc, 2, ("%s: Refresh failed to read back status: %d\n",
device_xname(sc->sc_dev), ierror));
@@ -858,7 +750,7 @@ bmx280_read_data(struct bmx280_sc *sc,
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);
+ ierror = (*(sc->sc_func_read_register))(sc, 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));
@@ -948,7 +840,7 @@ bmx280_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
}
mutex_enter(&sc->sc_mutex);
- error = iic_acquire_bus(sc->sc_tag, 0);
+ error = (*(sc->sc_func_acquire_bus))(sc);
if (error) {
DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
device_xname(sc->sc_dev), error));
@@ -1084,39 +976,15 @@ bmx280_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
device_xname(sc->sc_dev), error));
}
- iic_release_bus(sc->sc_tag, 0);
+ (*(sc->sc_func_release_bus))(sc);
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");
+MODULE(MODULE_CLASS_DRIVER, bmx280thp, NULL);
#ifdef _MODULE
+CFDRIVER_DECL(bmx280thp, DV_DULL, NULL);
#include "ioconf.c"
#endif
diff --git a/sys/dev/i2c/bmx280reg.h b/sys/dev/ic/bmx280reg.h
index 20a4031ffba..df07bd07ca7 100644
--- a/sys/dev/i2c/bmx280reg.h
+++ b/sys/dev/ic/bmx280reg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: bmx280reg.h,v 1.1 2022/11/21 21:24:01 brad Exp $ */
+/* $NetBSD: bmx280reg.h,v 1.1 2022/12/03 01:04:43 brad Exp $ */
/*
* Copyright (c) 2022 Brad Spencer <brad@anduin.eldar.org>
@@ -16,8 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _DEV_I2C_BMX280REG_H_
-#define _DEV_I2C_BMX280REG_H_
+#ifndef _DEV_IC_BMX280REG_H_
+#define _DEV_IC_BMX280REG_H_
#define BMX280_TYPICAL_ADDR_1 0x76
#define BMX280_TYPICAL_ADDR_2 0x77
diff --git a/sys/dev/i2c/bmx280var.h b/sys/dev/ic/bmx280var.h
index 19cc99ceb9f..b303465fc42 100644
--- a/sys/dev/i2c/bmx280var.h
+++ b/sys/dev/ic/bmx280var.h
@@ -1,4 +1,4 @@
-/* $NetBSD: bmx280var.h,v 1.2 2022/11/23 23:45:29 brad Exp $ */
+/* $NetBSD: bmx280var.h,v 1.1 2022/12/03 01:04:43 brad Exp $ */
/*
* Copyright (c) 2022 Brad Spencer <brad@anduin.eldar.org>
@@ -16,8 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _DEV_I2C_BMX280VAR_H_
-#define _DEV_I2C_BMX280VAR_H_
+#ifndef _DEV_IC_BMX280VAR_H_
+#define _DEV_IC_BMX280VAR_H_
#define BMX280_NUM_SENSORS 3
#define BMX280_TEMP_SENSOR 0
@@ -51,6 +51,7 @@ struct bmx280_sc {
device_t sc_dev;
i2c_tag_t sc_tag;
i2c_addr_t sc_addr;
+ struct spi_handle *sc_sh;
kmutex_t sc_mutex;
int sc_numsensors;
struct sysmon_envsys *sc_sme;
@@ -68,6 +69,11 @@ struct bmx280_sc {
int sc_waitfactor_t;
int sc_waitfactor_p;
int sc_waitfactor_h;
+ void (*sc_func_attach)(struct bmx280_sc *);
+ int (*sc_func_acquire_bus)(struct bmx280_sc *);
+ void (*sc_func_release_bus)(struct bmx280_sc *);
+ int (*sc_func_read_register)(struct bmx280_sc *, uint8_t, uint8_t *, size_t);
+ int (*sc_func_write_register)(struct bmx280_sc *, uint8_t *, size_t);
};
struct bmx280_sensor {
diff --git a/sys/dev/spi/bmx280thpspi.c b/sys/dev/spi/bmx280thpspi.c
new file mode 100644
index 00000000000..f3262ad5250
--- /dev/null
+++ b/sys/dev/spi/bmx280thpspi.c
@@ -0,0 +1,205 @@
+/* $NetBSD: bmx280thpspi.c,v 1.1 2022/12/03 01:04:43 brad Exp $ */
+
+/*
+ * Copyright (c) 2022 Brad Spencer <brad@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: bmx280thpspi.c,v 1.1 2022/12/03 01:04:43 brad Exp $");
+
+/*
+ * SPI driver for the Bosch BMP280 / BME280 sensor.
+ * Uses the common bmx280thp driver to do the real work.
+*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/pool.h>
+#include <sys/kmem.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/i2c/i2cvar.h>
+#include <dev/spi/spivar.h>
+#include <dev/ic/bmx280reg.h>
+#include <dev/ic/bmx280var.h>
+
+extern void bmx280_attach(struct bmx280_sc *);
+
+static int bmx280thpspi_match(device_t, cfdata_t, void *);
+static void bmx280thpspi_attach(device_t, device_t, void *);
+static int bmx280thpspi_detach(device_t, int);
+
+#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(bmx280thpspi, sizeof(struct bmx280_sc),
+ bmx280thpspi_match, bmx280thpspi_attach, bmx280thpspi_detach, NULL);
+
+/* The SPI interface of the chip, assuming that it has managed to get into that
+ * mode to start with, is pretty simple. Simply send the register MINUS the 7th
+ * bit which will be 1 and then do as many reads as you want. The chip will
+ * auto increment for you.
+ *
+ * The delays are only hinted at in the data sheet.
+ */
+
+static int
+bmx280thpspi_read_reg_direct(struct spi_handle *sh, uint8_t reg,
+ uint8_t *buf, size_t rlen)
+{
+ int err = 0;
+ uint8_t rreg = reg | 0x80;
+
+ if (buf != NULL) {
+ err = spi_send_recv(sh, 1, &rreg,
+ rlen, buf);
+ } else {
+ err = spi_send(sh, 1, &rreg);
+ }
+
+ return err;
+}
+
+static int
+bmx280thpspi_read_reg(struct bmx280_sc *sc, uint8_t reg, uint8_t *buf, size_t rlen)
+{
+ return bmx280thpspi_read_reg_direct(sc->sc_sh, reg, buf, rlen);
+}
+
+/* SPI writes to this device are normal enough. You send the register
+ * you want making sure that the high bit, 0x80, is clear and then the
+ * data. These pairs can be repeated as many times as you like.
+ */
+static int
+bmx280thpspi_write_reg_direct(struct spi_handle *sh, uint8_t *buf, size_t slen)
+{
+ int err = 0;
+ int i;
+
+ /* XXX -
+ this is probably BAD thing to do... but we must insure that the
+ registers have a cleared bit.. otherwise it is a read ....
+ */
+
+ for(i = 0; i < slen;i+=2) {
+ buf[i] = buf[i] & 0x7F;
+ }
+
+ err = spi_send(sh, slen, buf);
+
+ return err;
+}
+
+static int
+bmx280thpspi_write_reg(struct bmx280_sc *sc, uint8_t *buf, size_t slen)
+{
+ return bmx280thpspi_write_reg_direct(sc->sc_sh, buf, slen);
+}
+
+/* These are to satisfy the common code */
+static int
+bmx280thpspi_acquire_bus(struct bmx280_sc *sc)
+{
+ return 0;
+}
+
+static void
+bmx280thpspi_release_bus(struct bmx280_sc *sc)
+{
+ return;
+}
+
+/* Nothing more is done here. Assumptions on whether or not
+ * the SPI interface is set up may not be proper.... for better
+ * or worse... and there is setting that are needed such as the
+ * SPI mode and bus speed that really should not be done here, so
+ * any active match might not work anyway.
+ */
+static int
+bmx280thpspi_match(device_t parent, cfdata_t match, void *aux)
+{
+ const bool matchdebug = false;
+
+ if (matchdebug) {
+ printf("Trying to match\n");
+ }
+
+ return 1;
+}
+
+static void
+bmx280thpspi_attach(device_t parent, device_t self, void *aux)
+{
+ struct bmx280_sc *sc;
+ struct spi_attach_args *sa;
+ int error;
+
+ sa = aux;
+ sc = device_private(self);
+
+ sc->sc_dev = self;
+ sc->sc_sh = sa->sa_handle;
+ sc->sc_bmx280debug = 0;
+ sc->sc_func_acquire_bus = &bmx280thpspi_acquire_bus;
+ sc->sc_func_release_bus = &bmx280thpspi_release_bus;
+ sc->sc_func_read_register = &bmx280thpspi_read_reg;
+ sc->sc_func_write_register = &bmx280thpspi_write_reg;
+
+ /* Configure for 1MHz and SPI mode 0 according to the data sheet.
+ * The chip will actually handle a number of different modes and
+ * can go a lot faster, just use this for now...
+ */
+ error = spi_configure(self, sa->sa_handle, SPI_MODE_0, 1000000);
+ if (error) {
+ return;
+ }
+
+ /* Please note that if the pins are not set up for SPI, the attachment
+ * will probably not work out.
+ */
+ bmx280_attach(sc);
+
+ return;
+}
+
+/* These really do not do a whole lot, as SPI devices do not seem to work
+ * as modules.
+ */
+static int
+bmx280thpspi_detach(device_t self, int flags)
+{
+ struct bmx280_sc *sc;
+
+ sc = device_private(self);
+
+ mutex_destroy(&sc->sc_mutex);
+
+ return 0;
+}
diff --git a/sys/dev/spi/files.spi b/sys/dev/spi/files.spi
index e73dde62112..f7807089bfe 100644
--- a/sys/dev/spi/files.spi
+++ b/sys/dev/spi/files.spi
@@ -1,4 +1,4 @@
-# $NetBSD: files.spi,v 1.9 2022/01/17 16:31:23 thorpej Exp $
+# $NetBSD: files.spi,v 1.10 2022/12/03 01:04:43 brad Exp $
define spibus { }
@@ -47,3 +47,7 @@ file dev/spi/mcp3k.c mcp3kadc
# Sparkfun Serial motor controller
attach scmd at spi with scmdspi
file dev/spi/scmdspi.c scmdspi
+
+# Bosch BMP280 / BME280 sensor
+attach bmx280thp at spi with bmx280thpspi
+file dev/spi/bmx280thpspi.c bmx280thpspi
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 1106a74e31f..7ce632c96d2 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.273 2022/11/21 21:24:01 brad Exp $
+# $NetBSD: Makefile,v 1.274 2022/12/03 01:04:42 brad Exp $
.include <bsd.own.mk>
@@ -34,6 +34,7 @@ SUBDIR+= blowfish
SUBDIR+= bpf
SUBDIR+= bpf_filter
SUBDIR+= bmx280thp
+SUBDIR+= bmx280thpi2c
SUBDIR+= bufq_disksort
SUBDIR+= bufq_fcfs
SUBDIR+= bufq_priocscan
diff --git a/sys/modules/bmx280thp/Makefile b/sys/modules/bmx280thp/Makefile
index 24f88cc6e48..19460f49e06 100644
--- a/sys/modules/bmx280thp/Makefile
+++ b/sys/modules/bmx280thp/Makefile
@@ -1,6 +1,6 @@
.include "../Makefile.inc"
-.PATH: ${S}/dev/i2c
+.PATH: ${S}/dev/ic
KMOD= bmx280thp
IOCONF= bmx280thp.ioconf
diff --git a/sys/modules/bmx280thp/bmx280thp.ioconf b/sys/modules/bmx280thp/bmx280thp.ioconf
index 4285144f8a3..3c7e6ffaf18 100644
--- a/sys/modules/bmx280thp/bmx280thp.ioconf
+++ b/sys/modules/bmx280thp/bmx280thp.ioconf
@@ -1,8 +1,3 @@
ioconf bmx280thp
include "conf/files"
-
-pseudo-root iic*
-
-bmx280thp* at iic? addr 0x76
-bmx280thp* at iic? addr 0x77
diff --git a/sys/modules/bmx280thpi2c/Makefile b/sys/modules/bmx280thpi2c/Makefile
new file mode 100644
index 00000000000..bd04c22a2ad
--- /dev/null
+++ b/sys/modules/bmx280thpi2c/Makefile
@@ -0,0 +1,11 @@
+.include "../Makefile.inc"
+
+.PATH: ${S}/dev/i2c
+
+KMOD= bmx280thpi2c
+IOCONF= bmx280thpi2c.ioconf
+SRCS= bmx280thpi2c.c
+
+WARNS= 3
+
+.include <bsd.kmodule.mk>
diff --git a/sys/modules/bmx280thpi2c/bmx280thpi2c.ioconf b/sys/modules/bmx280thpi2c/bmx280thpi2c.ioconf
new file mode 100644
index 00000000000..e7dff0b5530
--- /dev/null
+++ b/sys/modules/bmx280thpi2c/bmx280thpi2c.ioconf
@@ -0,0 +1,8 @@
+ioconf bmx280thpi2c
+
+include "conf/files"
+
+pseudo-root iic*
+
+bmx280thp* at iic? addr 0x76
+bmx280thp* at iic? addr 0x77