diff options
| author | brad <brad@NetBSD.org> | 2022-12-03 01:04:42 +0000 |
|---|---|---|
| committer | brad <brad@NetBSD.org> | 2022-12-03 01:04:42 +0000 |
| commit | 02b8954fe89d72e580aac9928e8f0dd91cabaedc (patch) | |
| tree | 3d66e5b9ef8e2812eb0fd4eb5c10499ac92a1975 /sys | |
| parent | a76f61463de79fb55af1db5ff83b1f68aeca0073 (diff) | |
Split the BMP280 / BME280 driver into common code and create I2C and
SPI attachments.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/conf/files | 6 | ||||
| -rw-r--r-- | sys/dev/i2c/bmx280thpi2c.c | 264 | ||||
| -rw-r--r-- | sys/dev/i2c/files.i2c | 7 | ||||
| -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.c | 205 | ||||
| -rw-r--r-- | sys/dev/spi/files.spi | 6 | ||||
| -rw-r--r-- | sys/modules/Makefile | 3 | ||||
| -rw-r--r-- | sys/modules/bmx280thp/Makefile | 2 | ||||
| -rw-r--r-- | sys/modules/bmx280thp/bmx280thp.ioconf | 5 | ||||
| -rw-r--r-- | sys/modules/bmx280thpi2c/Makefile | 11 | ||||
| -rw-r--r-- | sys/modules/bmx280thpi2c/bmx280thpi2c.ioconf | 8 |
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,®,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, ®, 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, ®, &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, ®, 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, ®, 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, ®, &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, ®, &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, ®, 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 |
