#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bmx280thpspi.c,v 1.7 2025/09/13 16:16:40 thorpej Exp $");
#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>
struct bmx280_spi_softc {
struct bmx280_sc sc_bmx280;
spi_handle_t sc_sh;
};
#define BMX280_TO_SPI(sc) \
container_of((sc), struct bmx280_spi_softc, sc_bmx280)
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);
CFATTACH_DECL_NEW(bmx280thpspi, sizeof(struct bmx280_spi_softc),
bmx280thpspi_match, bmx280thpspi_attach, bmx280thpspi_detach, NULL);
static int
bmx280thpspi_read_reg_direct(spi_handle_t 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)
{
struct bmx280_spi_softc *ssc = BMX280_TO_SPI(sc);
return bmx280thpspi_read_reg_direct(ssc->sc_sh, reg, buf, rlen);
}
static int
bmx280thpspi_write_reg_direct(spi_handle_t sh, uint8_t *buf, size_t slen)
{
int err = 0;
int i;
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)
{
struct bmx280_spi_softc *ssc = BMX280_TO_SPI(sc);
return bmx280thpspi_write_reg_direct(ssc->sc_sh, buf, slen);
}
static int
bmx280thpspi_acquire_bus(struct bmx280_sc *sc __unused)
{
return 0;
}
static void
bmx280thpspi_release_bus(struct bmx280_sc *sc __unused)
{
return;
}
static const struct bmx280_accessfuncs bmx280_spi_accessfuncs = {
.acquire_bus = bmx280thpspi_acquire_bus,
.release_bus = bmx280thpspi_release_bus,
.read_reg = bmx280thpspi_read_reg,
.write_reg = bmx280thpspi_write_reg,
};
static int
bmx280thpspi_match(device_t parent, cfdata_t match, void *aux)
{
struct spi_attach_args *sa = aux;
int match_result;
if (spi_use_direct_match(sa, bmx280_compat_data, &match_result)) {
return match_result;
}
return SPI_MATCH_DEFAULT;
}
static void
bmx280thpspi_attach(device_t parent, device_t self, void *aux)
{
struct bmx280_spi_softc *ssc = device_private(self);
struct bmx280_sc *sc = &ssc->sc_bmx280;
struct spi_attach_args *sa = aux;
int error;
sc->sc_dev = self;
sc->sc_funcs = &bmx280_spi_accessfuncs;
ssc->sc_sh = sa->sa_handle;
error = spi_configure(self, sa->sa_handle, SPI_MODE_0, SPI_FREQ_MHz(1));
if (error) {
return;
}
bmx280_attach(sc);
}
static int
bmx280thpspi_detach(device_t self, int flags)
{
struct bmx280_spi_softc *ssc = device_private(self);
return bmx280_detach(&ssc->sc_bmx280, flags);
}