PR/52848: Brad Spencer: Two environment sensor drivers: AM2315 and SI70xx
XXX: Please check that my refactoring did not break them!
This commit is contained in:
parent
d31c829649
commit
ee4352f2da
|
@ -0,0 +1,531 @@
|
|||
/* $NetBSD: am2315.c,v 1.1 2017/12/28 23:23:47 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 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: am2315.c,v 1.1 2017/12/28 23:23:47 christos Exp $");
|
||||
|
||||
/*
|
||||
* Driver for the Aosong AM2315
|
||||
*/
|
||||
|
||||
#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/condvar.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dev/sysmon/sysmonvar.h>
|
||||
#include <dev/i2c/i2cvar.h>
|
||||
#include <dev/i2c/am2315reg.h>
|
||||
#include <dev/i2c/am2315var.h>
|
||||
|
||||
static uint16_t am2315_crc(uint8_t *, size_t);
|
||||
static int am2315_poke(struct am2315_sc *);
|
||||
static int am2315_poke_m(i2c_tag_t, i2c_addr_t, const char *, bool);
|
||||
static int am2315_match(device_t, cfdata_t, void *);
|
||||
static void am2315_attach(device_t, device_t, void *);
|
||||
static int am2315_detach(device_t, int);
|
||||
static void am2315_refresh(struct sysmon_envsys *, envsys_data_t *);
|
||||
static int am2315_verify_sysctl(SYSCTLFN_ARGS);
|
||||
|
||||
#define AM2315_DEBUG
|
||||
#ifdef AM2315_DEBUG
|
||||
#define DPRINTF(s, l, x) \
|
||||
do { \
|
||||
if (l <= s->sc_am2315debug) \
|
||||
printf x; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#else
|
||||
#define DPRINTF(s, l, x)
|
||||
#endif
|
||||
|
||||
CFATTACH_DECL_NEW(am2315temp, sizeof(struct am2315_sc),
|
||||
am2315_match, am2315_attach, am2315_detach, NULL);
|
||||
|
||||
static struct am2315_sensor am2315_sensors[] = {
|
||||
{
|
||||
.desc = "humidity",
|
||||
.type = ENVSYS_SRELHUMIDITY,
|
||||
},
|
||||
{
|
||||
.desc = "temperature",
|
||||
.type = ENVSYS_STEMP,
|
||||
}
|
||||
};
|
||||
|
||||
static uint16_t
|
||||
am2315_crc(uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t crc = 0xffff;
|
||||
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
crc ^= data[j];
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
if (crc & 0x01) {
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
int
|
||||
am2315_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;
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t dir, uint8_t cmd,
|
||||
uint8_t clen, uint8_t *buf, size_t blen)
|
||||
{
|
||||
uint8_t command[] = { dir, cmd, clen };
|
||||
if (buf)
|
||||
memset(buf, 0xff, blen);
|
||||
uint8_t reg = dir == AM2315_READ_REGISTERS ?
|
||||
I2C_OP_READ_WITH_STOP : I2C_OP_WRITE_WITH_STOP;
|
||||
|
||||
return iic_exec(tag, reg, addr, command,
|
||||
__arraycount(command), buf, blen, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_read_regs(struct am2315_sc *sc, uint8_t cmd, uint8_t clen, uint8_t *buf,
|
||||
size_t blen)
|
||||
{
|
||||
return am2315_cmd(sc->sc_tag, sc->sc_addr, AM2315_READ_REGISTERS,
|
||||
cmd, clen, buf, blen);
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_poke(struct am2315_sc *sc)
|
||||
{
|
||||
return am2315_poke_m(sc->sc_tag, sc->sc_addr, device_xname(sc->sc_dev),
|
||||
sc->sc_am2315debug >= 2);
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_poke_m(i2c_tag_t tag, i2c_addr_t addr, const char *name, bool debug)
|
||||
{
|
||||
uint8_t buf[5];
|
||||
int error;
|
||||
|
||||
error = am2315_cmd(tag, addr, AM2315_WRITE_REGISTERS,
|
||||
AM2315_REGISTER_HIGH_USER1, 1, NULL, 0);
|
||||
if (debug)
|
||||
printf("%s: poke 1: %d\n", name, error);
|
||||
|
||||
if (error != 0)
|
||||
delay(2800);
|
||||
|
||||
error = am2315_cmd(tag, addr, AM2315_READ_REGISTERS,
|
||||
AM2315_REGISTER_STATUS, 1, buf, __arraycount(buf));
|
||||
if (debug)
|
||||
printf("%s: poke 2: %d %02x %02x %02x %02x%02x\n", name, error,
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4]);
|
||||
|
||||
if (error != 0)
|
||||
delay(2800);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
struct i2c_attach_args *ia;
|
||||
int rv;
|
||||
const bool matchdebug = false;
|
||||
|
||||
ia = aux;
|
||||
|
||||
if (ia->ia_name) {
|
||||
/* direct config - check name */
|
||||
if (strcmp(ia->ia_name, "am2315temp") != 0)
|
||||
return 0;
|
||||
} else {
|
||||
/* indirect config - check for configured address */
|
||||
if (ia->ia_addr != AM2315_TYPICAL_ADDR)
|
||||
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;
|
||||
}
|
||||
|
||||
if ((rv = am2315_poke_m(ia->ia_tag, ia->ia_addr, __func__, matchdebug))
|
||||
!= 0) {
|
||||
if (matchdebug)
|
||||
printf("match rv poke %d\n", rv);
|
||||
iic_release_bus(ia->ia_tag, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
am2315_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct am2315_sc *sc = device_private(self);
|
||||
struct i2c_attach_args *ia = aux;
|
||||
uint8_t buf[11];
|
||||
int error;
|
||||
uint16_t crc, readcrc, model;
|
||||
uint8_t chipver;
|
||||
uint32_t id;
|
||||
bool modelgood, chipvergood, idgood;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_tag = ia->ia_tag;
|
||||
sc->sc_addr = ia->ia_addr;
|
||||
sc->sc_am2315debug = 0;
|
||||
sc->sc_readcount = 2;
|
||||
sc->sc_readticks = 100;
|
||||
sc->sc_sme = NULL;
|
||||
|
||||
aprint_normal("\n");
|
||||
|
||||
mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&sc->sc_waitmutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
cv_init(&sc->sc_condwait, "am2315wait");
|
||||
|
||||
sc->sc_numsensors = __arraycount(am2315_sensors);
|
||||
|
||||
if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
|
||||
aprint_error_dev(self, "unable to create sysmon structure\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX: sysctl's not destroyed on failure */
|
||||
const struct sysctlnode *cnode;
|
||||
int sysctlroot_num;
|
||||
if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode, 0,
|
||||
CTLTYPE_NODE, device_xname(self),
|
||||
SYSCTL_DESCR("am2315 controls"), NULL, 0, NULL, 0, CTL_HW,
|
||||
CTL_CREATE, CTL_EOL)) != 0)
|
||||
goto badsysctl;
|
||||
sysctlroot_num = cnode->sysctl_num;
|
||||
|
||||
#ifdef AM2315_DEBUG
|
||||
if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
|
||||
SYSCTL_DESCR("Debug level"), am2315_verify_sysctl, 0,
|
||||
&sc->sc_am2315debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
|
||||
CTL_EOL)) != 0)
|
||||
goto badsysctl;
|
||||
|
||||
#endif
|
||||
|
||||
if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT, "readcount",
|
||||
SYSCTL_DESCR("Number of times to read the sensor"),
|
||||
am2315_verify_sysctl, 0, &sc->sc_readcount, 0, CTL_HW,
|
||||
sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
|
||||
goto badsysctl;
|
||||
|
||||
if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT, "readticks",
|
||||
SYSCTL_DESCR("Number of ticks between reads"),
|
||||
am2315_verify_sysctl, 0, &sc->sc_readticks, 0, CTL_HW,
|
||||
sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
|
||||
goto badsysctl;
|
||||
|
||||
if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) {
|
||||
aprint_error_dev(self,
|
||||
"Could not acquire iic bus: %d\n", error);
|
||||
return;
|
||||
}
|
||||
am2315_poke(sc);
|
||||
|
||||
#define DUMP(a) \
|
||||
DPRINTF(sc, 2, ("%s: read cmd+len+%s+crcl+crch values: %02x %02x " \
|
||||
"%02x%02x %02x%02x -- %02x%02x%02x%02x%02x -- %04x %04x\n", a, \
|
||||
device_xname(self), buf[0], buf[1], buf[2], buf[3], \
|
||||
buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], \
|
||||
buf[10], crc, readcrc))
|
||||
|
||||
error = am2315_read_regs(sc, AM2315_REGISTER_HIGH_MODEL, 2, buf, 6);
|
||||
if (error)
|
||||
aprint_error_dev(sc->sc_dev, "read model: %d\n", error);
|
||||
readcrc = buf[5] << 8 | buf[4];
|
||||
crc = am2315_crc(buf, 4);
|
||||
DUMP("modh+modl");
|
||||
model = buf[2] << 8 | buf[3];
|
||||
modelgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
|
||||
&& crc == readcrc;
|
||||
|
||||
error = am2315_read_regs(sc, AM2315_REGISTER_VERSION, 1, buf, 5);
|
||||
if (error != 0)
|
||||
aprint_error_dev(self, "read chipver: %d\n", error);
|
||||
readcrc = buf[4] << 8 | buf[3];
|
||||
crc = am2315_crc(buf, 3);
|
||||
DUMP("ver");
|
||||
chipver = buf[2];
|
||||
chipvergood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 1
|
||||
&& crc == readcrc;
|
||||
|
||||
error = am2315_read_regs(sc, AM2315_REGISTER_ID_PT_24_31, 2, buf, 6);
|
||||
if (error != 0)
|
||||
aprint_error_dev(self, "read id 1: %d\n", error);
|
||||
readcrc = buf[5] << 8 | buf[4];
|
||||
crc = am2315_crc(buf, 4);
|
||||
DUMP("id1+id2");
|
||||
id = buf[2] << 8 | buf[3];
|
||||
idgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
|
||||
&& crc == readcrc;
|
||||
|
||||
error = am2315_read_regs(sc, AM2315_REGISTER_ID_PT_8_15, 2, buf, 6);
|
||||
if (error != 0)
|
||||
aprint_error_dev(self, "read id 2: %d\n", error);
|
||||
readcrc = buf[5] << 8 | buf[4];
|
||||
crc = am2315_crc(buf, 4);
|
||||
DUMP("id3+id4");
|
||||
id = id << 8 | buf[2];
|
||||
id = id << 8 | buf[3];
|
||||
idgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
|
||||
&& crc == readcrc && idgood;
|
||||
|
||||
iic_release_bus(sc->sc_tag, 0);
|
||||
|
||||
for (int i = 0; i < sc->sc_numsensors; i++) {
|
||||
strlcpy(sc->sc_sensors[i].desc, am2315_sensors[i].desc,
|
||||
sizeof(sc->sc_sensors[i].desc));
|
||||
|
||||
sc->sc_sensors[i].units = am2315_sensors[i].type;
|
||||
sc->sc_sensors[i].state = ENVSYS_SINVALID;
|
||||
|
||||
DPRINTF(sc, 2, ("am2315_attach: registering sensor %d (%s)\n",
|
||||
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\n",
|
||||
error);
|
||||
goto badregister;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_sme->sme_name = device_xname(sc->sc_dev);
|
||||
sc->sc_sme->sme_cookie = sc;
|
||||
sc->sc_sme->sme_refresh = am2315_refresh;
|
||||
|
||||
DPRINTF(sc, 2, ("am2315_attach: registering with envsys\n"));
|
||||
|
||||
error = sysmon_envsys_register(sc->sc_sme);
|
||||
if (error) {
|
||||
aprint_error_dev(self, "unable to register with sysmon %d\n",
|
||||
error);
|
||||
goto badregister;
|
||||
}
|
||||
aprint_normal_dev(self, "Aosong AM2315, Model: %04x%s Version: %02x%s"
|
||||
" ID: %08x%s",
|
||||
model, (modelgood ? "," : "(inaccurate),"),
|
||||
chipver, (chipvergood ? "," : "(inaccurate),"),
|
||||
id, (idgood ? "\n" : "(inaccurate)\n"));
|
||||
return;
|
||||
|
||||
badsysctl:
|
||||
aprint_error_dev(self, ": can't setup sysctl tree (%d)\n", error);
|
||||
return;
|
||||
badregister:
|
||||
sysmon_envsys_destroy(sc->sc_sme);
|
||||
sc->sc_sme = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
am2315_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
|
||||
{
|
||||
struct am2315_sc *sc;
|
||||
uint8_t buf[11], thecommand;
|
||||
uint16_t crc, readcrc;
|
||||
int error, rv;
|
||||
uint32_t val32;
|
||||
bool istempneg = false;
|
||||
|
||||
sc = sme->sme_cookie;
|
||||
edata->state = ENVSYS_SINVALID;
|
||||
|
||||
mutex_enter(&sc->sc_mutex);
|
||||
error = iic_acquire_bus(sc->sc_tag, 0);
|
||||
if (error == 0) {
|
||||
DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %d\n",
|
||||
device_xname(sc->sc_dev), error));
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (edata->sensor) {
|
||||
case AM2315_HUMIDITY_SENSOR:
|
||||
thecommand = AM2315_REGISTER_HIGH_RH;
|
||||
break;
|
||||
case AM2315_TEMP_SENSOR:
|
||||
thecommand = AM2315_REGISTER_HIGH_TEMP;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(sc, 2, ("%s: bad sensor %d\n",
|
||||
device_xname(sc->sc_dev), edata->sensor));
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (int count = 0; ;) {
|
||||
am2315_poke(sc);
|
||||
|
||||
if ((error = am2315_read_regs(sc, thecommand, 2, buf, 6)) != 0)
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"Read sensor %d error: %d\n", edata->sensor, error);
|
||||
|
||||
readcrc = buf[5] << 8 | buf[4];
|
||||
crc = am2315_crc(buf, 4);
|
||||
|
||||
DPRINTF(sc, 2, ("%s: read cmd+len+dh+dl+crch+crcl values: %02x"
|
||||
" %02x %02x%02x %02x%02x -- %04x %04x -- %d\n",
|
||||
device_xname(sc->sc_dev), buf[0], buf[1], buf[2],
|
||||
buf[3], buf[4], buf[5], crc, readcrc, count));
|
||||
if (++count == sc->sc_readcount)
|
||||
break;
|
||||
mutex_enter(&sc->sc_waitmutex);
|
||||
rv = cv_timedwait(&sc->sc_condwait, &sc->sc_waitmutex,
|
||||
sc->sc_readticks);
|
||||
DPRINTF(sc, 2, ("%s: wait rv: %d\n", device_xname(sc->sc_dev),
|
||||
rv));
|
||||
mutex_exit(&sc->sc_waitmutex);
|
||||
}
|
||||
|
||||
iic_release_bus(sc->sc_tag, 0);
|
||||
|
||||
if (buf[0] != AM2315_READ_REGISTERS || buf[1] != 2 ||
|
||||
crc != readcrc) {
|
||||
DPRINTF(sc, 2, ("%s: Invalid sensor data for %d\n",
|
||||
device_xname(sc->sc_dev), edata->sensor));
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (edata->sensor) {
|
||||
case AM2315_HUMIDITY_SENSOR:
|
||||
val32 = buf[2] << 8 | buf[3];
|
||||
val32 = val32 * 100000;
|
||||
DPRINTF(sc, 2, ("%s: read translated values RH: %x\n",
|
||||
device_xname(sc->sc_dev), val32));
|
||||
edata->value_cur = val32;
|
||||
edata->state = ENVSYS_SVALID;
|
||||
break;
|
||||
case AM2315_TEMP_SENSOR:
|
||||
istempneg = (buf[2] & AM2315_TEMP_NEGATIVE);
|
||||
buf[2] = buf[2] & (~AM2315_TEMP_NEGATIVE);
|
||||
val32 = buf[2] << 8 | buf[3];
|
||||
if (istempneg) {
|
||||
val32 = 273150000 - (val32 * 100000);
|
||||
} else {
|
||||
val32 = (val32 * 100000) + 273150000;
|
||||
}
|
||||
DPRINTF(sc, 2, ("%s: read translated values TEMP: %x\n",
|
||||
device_xname(sc->sc_dev), val32));
|
||||
edata->value_cur = val32;
|
||||
edata->state = ENVSYS_SVALID;
|
||||
break;
|
||||
default:
|
||||
panic("bad sensor %d\n", edata->sensor);
|
||||
}
|
||||
out:
|
||||
mutex_exit(&sc->sc_mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
am2315_detach(device_t self, int flags)
|
||||
{
|
||||
struct am2315_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);
|
||||
|
||||
/* Destroy the wait cond */
|
||||
cv_destroy(&sc->sc_condwait);
|
||||
|
||||
/* Remove the sysctl tree */
|
||||
sysctl_teardown(&sc->sc_am2315log);
|
||||
|
||||
/* Remove the mutex */
|
||||
mutex_destroy(&sc->sc_waitmutex);
|
||||
mutex_destroy(&sc->sc_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE(MODULE_CLASS_DRIVER, am2315temp, "i2cexec,sysmon_envsys");
|
||||
|
||||
#ifdef _MODULE
|
||||
#include "ioconf.c"
|
||||
#endif
|
||||
|
||||
static int
|
||||
am2315temp_modcmd(modcmd_t cmd, void *opaque)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
#ifdef _MODULE
|
||||
return config_init_component(cfdriver_ioconf_am2315temp,
|
||||
cfattach_ioconf_am2315temp, cfdata_ioconf_am2315temp);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case MODULE_CMD_FINI:
|
||||
#ifdef _MODULE
|
||||
return config_fini_component(cfdriver_ioconf_am2315temp,
|
||||
cfattach_ioconf_am2315temp, cfdata_ioconf_am2315temp);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_I2C_AM2315REG_H_
|
||||
#define _DEV_I2C_AM2315REG_H_
|
||||
|
||||
#define AM2315_TYPICAL_ADDR 0x5c
|
||||
|
||||
#define AM2315_READ_REGISTERS 0x03
|
||||
#define AM2315_WRITE_REGISTERS 0x10
|
||||
|
||||
#define AM2315_REGISTER_HIGH_RH 0x00
|
||||
#define AM2315_REGISTER_LOW_RH 0x01
|
||||
#define AM2315_REGISTER_HIGH_TEMP 0x02
|
||||
#define AM2315_REGISTER_LOW_TEMP 0x03
|
||||
#define AM2315_REGISTER_RETENTION_04 0x04
|
||||
#define AM2315_REGISTER_RETENTION_05 0x05
|
||||
#define AM2315_REGISTER_RETENTION_06 0x06
|
||||
#define AM2315_REGISTER_RETENTION_07 0x07
|
||||
#define AM2315_REGISTER_HIGH_MODEL 0x08
|
||||
#define AM2315_REGISTER_LOW_MODEL 0x09
|
||||
#define AM2315_REGISTER_VERSION 0x0a
|
||||
#define AM2315_REGISTER_ID_PT_24_31 0x0b
|
||||
#define AM2315_REGISTER_ID_PT_16_23 0x0c
|
||||
#define AM2315_REGISTER_ID_PT_8_15 0x0d
|
||||
#define AM2315_REGISTER_ID_PT_0_7 0x0e
|
||||
#define AM2315_REGISTER_STATUS 0x0f
|
||||
#define AM2315_REGISTER_HIGH_USER1 0x10
|
||||
#define AM2315_REGISTER_LOW_USER1 0x11
|
||||
#define AM2315_REGISTER_HIGH_USER2 0x12
|
||||
#define AM2315_REGISTER_LOW_USER2 0x13
|
||||
#define AM2315_REGISTER_RETENTION_14 0x14
|
||||
#define AM2315_REGISTER_RETENTION_15 0x15
|
||||
#define AM2315_REGISTER_RETENTION_16 0x16
|
||||
#define AM2315_REGISTER_RETENTION_17 0x17
|
||||
#define AM2315_REGISTER_RETENTION_18 0x18
|
||||
#define AM2315_REGISTER_RETENTION_19 0x19
|
||||
#define AM2315_REGISTER_RETENTION_1a 0x1a
|
||||
#define AM2315_REGISTER_RETENTION_1b 0x1b
|
||||
#define AM2315_REGISTER_RETENTION_1c 0x1c
|
||||
#define AM2315_REGISTER_RETENTION_1d 0x1d
|
||||
#define AM2315_REGISTER_RETENTION_1e 0x1e
|
||||
#define AM2315_REGISTER_RETENTION_1f 0x1f
|
||||
|
||||
#define AM2315_TEMP_NEGATIVE 0x80
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_I2C_AM2315VAR_H_
|
||||
#define _DEV_I2C_AM2315VAR_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#define AM2315_NUM_SENSORS 2
|
||||
#define AM2315_HUMIDITY_SENSOR 0
|
||||
#define AM2315_TEMP_SENSOR 1
|
||||
|
||||
struct am2315_sc {
|
||||
int sc_am2315debug;
|
||||
device_t sc_dev;
|
||||
i2c_tag_t sc_tag;
|
||||
i2c_addr_t sc_addr;
|
||||
kmutex_t sc_mutex;
|
||||
kmutex_t sc_waitmutex;
|
||||
kcondvar_t sc_condwait;
|
||||
int sc_numsensors;
|
||||
struct sysmon_envsys *sc_sme;
|
||||
envsys_data_t sc_sensors[AM2315_NUM_SENSORS];
|
||||
struct sysctllog *sc_am2315log;
|
||||
int sc_readcount;
|
||||
int sc_readticks;
|
||||
};
|
||||
|
||||
struct am2315_sensor {
|
||||
const char *desc;
|
||||
enum envsys_units type;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.i2c,v 1.79 2017/12/10 17:05:54 bouyer Exp $
|
||||
# $NetBSD: files.i2c,v 1.80 2017/12/28 23:23:47 christos Exp $
|
||||
|
||||
obsolete defflag opt_i2cbus.h I2C_SCAN
|
||||
define i2cbus { }
|
||||
|
@ -280,6 +280,16 @@ device tcagpio
|
|||
attach tcagpio at iic
|
||||
file dev/i2c/tcagpio.c tcagpio
|
||||
|
||||
# Silicon Lab SI7013/SI7020/SI7021 Temperature and Humidity sensor
|
||||
device si70xxtemp
|
||||
attach si70xxtemp at iic
|
||||
file dev/i2c/si70xx.c si70xxtemp
|
||||
|
||||
# Aosong AM2315 Temperature and Humidity sensor
|
||||
device am2315temp
|
||||
attach am2315temp at iic
|
||||
file dev/i2c/am2315.c am2315temp
|
||||
|
||||
# Silergy SY8106A regulator
|
||||
device sy8106a
|
||||
attach sy8106a at iic
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_I2C_SI70XXREG_H_
|
||||
#define _DEV_I2C_SI70XXREG_H_
|
||||
|
||||
#define SI70XX_TYPICAL_ADDR 0x40
|
||||
|
||||
#define SI70XX_MEASURE_RH_HOLD 0xE5
|
||||
#define SI70XX_MEASURE_RH_NOHOLD 0xF5
|
||||
#define SI70XX_MEASURE_TEMP_HOLD 0xE3
|
||||
#define SI70XX_MEASURE_TEMP_NOHOLD 0xF3
|
||||
#define SI70XX_READ_PREVIOUS_TEMP 0xE0
|
||||
#define SI70XX_RESET 0xFE
|
||||
#define SI70XX_WRITE_USER_REG_1 0xE6
|
||||
#define SI70XX_READ_USER_REG_1 0xE7
|
||||
#define SI70XX_WRITE_HEATER_REG 0x51
|
||||
#define SI70XX_READ_HEATER_REG 0x11
|
||||
#define SI70XX_READ_ID_PT1A 0xFA
|
||||
#define SI70XX_READ_ID_PT1B 0x0F
|
||||
#define SI70XX_READ_ID_PT2A 0xFC
|
||||
#define SI70XX_READ_ID_PT2B 0xC9
|
||||
#define SI70XX_READ_FW_VERA 0x84
|
||||
#define SI70XX_READ_FW_VERB 0xB8
|
||||
|
||||
#define SI70XX_VDDS_MASK 0x40
|
||||
#define SI70XX_HTRE_MASK 0x04
|
||||
#define SI70XX_RESOLUTION_MASK 0x81
|
||||
#define SI70XX_HEATER_MASK 0x0F
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_I2C_SI70XXVAR_H_
|
||||
#define _DEV_I2C_SI70XXVAR_H_
|
||||
|
||||
#define SI70XX_NUM_SENSORS 2
|
||||
#define SI70XX_HUMIDITY_SENSOR 0
|
||||
#define SI70XX_TEMP_SENSOR 1
|
||||
|
||||
#define SI70XX_RES_NAME 12
|
||||
|
||||
struct si70xx_sc {
|
||||
int sc_si70xxdebug;
|
||||
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;
|
||||
envsys_data_t sc_sensors[SI70XX_NUM_SENSORS];
|
||||
struct sysctllog *sc_si70xxlog;
|
||||
char sc_resolution[SI70XX_RES_NAME];
|
||||
int sc_resnumber;
|
||||
bool sc_ignorecrc;
|
||||
bool sc_vddok;
|
||||
bool sc_heateron;
|
||||
int sc_heaterval;
|
||||
#ifdef HAVE_I2C_EXECV
|
||||
uint32_t sc_clockstretch;
|
||||
#endif
|
||||
int sc_readattempts;
|
||||
};
|
||||
|
||||
struct si70xx_sensor {
|
||||
const char *desc;
|
||||
enum envsys_units type;
|
||||
};
|
||||
|
||||
struct si70xx_resolution {
|
||||
const char *text;
|
||||
int num;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue