Module Name: src Committed By: christos Date: Sat Nov 13 13:36:43 UTC 2021
Modified Files: src/sys/dev/i2c: sht3x.c Log Message: Brad wants the __did_not_work code back :-) To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/dev/i2c/sht3x.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/sht3x.c diff -u src/sys/dev/i2c/sht3x.c:1.2 src/sys/dev/i2c/sht3x.c:1.3 --- src/sys/dev/i2c/sht3x.c:1.2 Fri Nov 12 17:16:27 2021 +++ src/sys/dev/i2c/sht3x.c Sat Nov 13 08:36:42 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: sht3x.c,v 1.2 2021/11/12 22:16:27 christos Exp $ */ +/* $NetBSD: sht3x.c,v 1.3 2021/11/13 13:36:42 christos Exp $ */ /* * Copyright (c) 2021 Brad Spencer <b...@anduin.eldar.org> @@ -17,7 +17,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.2 2021/11/12 22:16:27 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.3 2021/11/13 13:36:42 christos Exp $"); /* Driver for the Sensirion SHT30/SHT31/SHT35 @@ -41,7 +41,6 @@ __KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1. #include <dev/i2c/sht3xreg.h> #include <dev/i2c/sht3xvar.h> - static int sht3x_take_break(void *, bool); static int sht3x_get_status_register(void *, uint16_t *, bool); static int sht3x_clear_status_register(void *, bool); @@ -52,6 +51,18 @@ static int sht3x_match(device_t, cfdata static void sht3x_attach(device_t, device_t, void *); static int sht3x_detach(device_t, int); static void sht3x_refresh(struct sysmon_envsys *, envsys_data_t *); +#ifdef __did_not_work +/* + * The chip that I had would not allow the limits to actually be set + * for reasons which are not obvious. The chip took the command just + * fine, but a read back of the limit registers showed that no change + * was made, so disable limits for now. + */ +static void sht3x_get_limits(struct sysmon_envsys *, envsys_data_t *, + sysmon_envsys_lim_t *, uint32_t *); +static void sht3x_set_limits(struct sysmon_envsys *, envsys_data_t *, + sysmon_envsys_lim_t *, uint32_t *); +#endif static int sht3x_verify_sysctl(SYSCTLFN_ARGS); static int sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS); static int sht3x_verify_sysctl_modes(SYSCTLFN_ARGS); @@ -1166,6 +1177,9 @@ sht3x_attach(device_t parent, device_t s sc->sc_sensors[i].units = sht3x_sensors[i].type; sc->sc_sensors[i].state = ENVSYS_SINVALID; +#ifdef __did_not_work + sc->sc_sensors[i].flags |= ENVSYS_FMONLIMITS; +#endif DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i, sc->sc_sensors[i].desc)); @@ -1182,6 +1196,10 @@ sht3x_attach(device_t parent, device_t s sc->sc_sme->sme_name = device_xname(sc->sc_dev); sc->sc_sme->sme_cookie = sc; sc->sc_sme->sme_refresh = sht3x_refresh; +#ifdef __did_not_work + sc->sc_sme->sme_get_limits = sht3x_get_limits; + sc->sc_sme->sme_set_limits = sht3x_set_limits; +#endif DPRINTF(sc, 2, ("sht3x_attach: registering with envsys\n")); @@ -1348,6 +1366,38 @@ sht3x_parse_data(struct sht3x_sc *sc, en return 0; } +#ifdef __did_not_work +/* + * These are the the same as above except solved for the raw tick rather than + * temperature or humidity. These are needed for setting the alert limits, but + * since that did not work, disable these too for now. + */ +static uint16_t +sht3x_compute_raw_from_temp(uint32_t temp) +{ + uint64_t i1; + uint32_t tempc; + + tempc = temp - 272150000; + tempc = tempc / 1000000; + + i1 = (13107 * tempc) + 589815; + return (uint16_t)(i1 / 35); +} + +static uint16_t +sht3x_compute_raw_from_rh(uint32_t mrh) +{ + uint64_t i1; + uint32_t rh; + + rh = mrh / 1000000; + + i1 = 13107 * rh; + return (uint16_t)(i1 / 20); +} +#endif + static int sht3x_refresh_periodic(struct sysmon_envsys *sme, envsys_data_t *edata) { @@ -1426,6 +1476,419 @@ sht3x_refresh(struct sysmon_envsys *sme, mutex_exit(&sc->sc_mutex); } +#ifdef __did_not_work +static void +sht3x_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, + sysmon_envsys_lim_t *limits, uint32_t *props) +{ + struct sht3x_sc *sc = sme->sme_cookie; + uint16_t rawlimitshigh, rawlimitslow; + uint16_t templimithigh, rhlimithigh, + templimitlow, rhlimitlow; + uint8_t templimithighmsb, templimithighlsb, + templimitlowmsb, templimitlowlsb; + uint8_t rhlimithighmsb, rhlimithighlsb, + rhlimitlowmsb, rhlimitlowlsb; + int error; + uint8_t lbuf[3]; + uint8_t limitscrchigh, limitskcrchigh, + limitscrclow, limitskcrclow; + + *props = 0; + + mutex_enter(&sc->sc_mutex); + error = iic_acquire_bus(sc->sc_tag, 0); + if (error) { + DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", + device_xname(sc->sc_dev), error)); + mutex_exit(&sc->sc_mutex); + return; + } + + error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitshigh = (lbuf[0] << 8) | lbuf[1]; + limitskcrchigh = lbuf[2]; + limitscrchigh = sht3x_crc(&lbuf[0],2); + + templimithigh = ((rawlimitshigh & 0x1FF) << 7); + templimithighmsb = (uint8_t)(templimithigh >> 8); + templimithighlsb = (uint8_t)(templimithigh & 0x00FF); + DPRINTF(sc, 2, ("%s: Limits high intermediate temp: " + "%04x %04x %02x %02x\n", device_xname(sc->sc_dev), rawlimitshigh, + templimithigh, templimithighmsb, templimithighlsb)); + + rhlimithigh = (rawlimitshigh & 0xFE00); + rhlimithighmsb = (uint8_t)(rhlimithigh >> 8); + rhlimithighlsb = (uint8_t)(rhlimithigh & 0x00FF); + DPRINTF(sc, 2, ("%s: Limits high intermediate rh: " + "%04x %04x %02x %02x\n", device_xname(sc->sc_dev), rawlimitshigh, + rhlimithigh, rhlimithighmsb, rhlimithighlsb)); + + DPRINTF(sc, 2, ("%s: Limit high raw: %02x%02x %02x %02x %02x\n", + device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2], + limitscrchigh, limitskcrchigh)); + + error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitslow = (lbuf[0] << 8) | lbuf[1]; + limitskcrclow = lbuf[2]; + limitscrclow = sht3x_crc(&lbuf[0],2); + + templimitlow = ((rawlimitslow & 0x1FF) << 7); + templimitlowmsb = (uint8_t)(templimitlow >> 8); + templimitlowlsb = (uint8_t)(templimitlow & 0x00FF); + DPRINTF(sc, 2, ("%s: Limits low intermediate temp: " + "%04x %04x %02x %02x\n", device_xname(sc->sc_dev), rawlimitslow, + templimitlow, templimitlowmsb, templimitlowlsb)); + + rhlimitlow = (rawlimitslow & 0xFE00); + rhlimitlowmsb = (uint8_t)(rhlimitlow >> 8); + rhlimitlowlsb = (uint8_t)(rhlimitlow & 0x00FF); + DPRINTF(sc, 2, ("%s: Limits low intermediate rh: %04x %04x %02x %02x\n", + device_xname(sc->sc_dev), rawlimitslow, rhlimitlow, rhlimitlowmsb, + rhlimitlowlsb)); + + DPRINTF(sc, 2, ("%s: Limit low raw: %02x%02x %02x %02x %02x\n", + device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2], + limitscrclow, limitskcrclow)); + + + switch (edata->sensor) { + case SHT3X_TEMP_SENSOR: + if (limitscrchigh == limitskcrchigh) { + limits->sel_critmax = sht3x_compute_temp_from_raw( + templimithighmsb, templimithighlsb); + *props |= PROP_CRITMAX; + } + if (limitscrclow == limitskcrclow) { + limits->sel_critmin = sht3x_compute_temp_from_raw( + templimitlowmsb, templimitlowlsb); + *props |= PROP_CRITMIN; + } + break; + case SHT3X_HUMIDITY_SENSOR: + if (limitscrchigh == limitskcrchigh) { + limits->sel_critmax = sht3x_compute_rh_from_raw( + rhlimithighmsb, rhlimithighlsb); + *props |= PROP_CRITMAX; + } + if (limitscrclow == limitskcrclow) { + limits->sel_critmin = sht3x_compute_rh_from_raw( + rhlimitlowmsb, rhlimitlowlsb); + *props |= PROP_CRITMIN; + } + break; + default: + break; + } + + if (*props != 0) + *props |= PROP_DRIVER_LIMITS; + + iic_release_bus(sc->sc_tag, 0); +out: + mutex_exit(&sc->sc_mutex); +} + +static void +sht3x_set_alert_limits(void *aux, uint16_t high, uint16_t low, bool have_bus) +{ + struct sht3x_sc *sc = aux; + int error; + uint8_t hbuf[3]; + uint8_t lbuf[3]; + + if (! have_bus) { + error = iic_acquire_bus(sc->sc_tag, 0); + if (error) { + DPRINTF(sc, 2, ("%s: Could not acquire iic bus for " + "setting alerts %d\n", device_xname(sc->sc_dev), + error)); + return; + } + } + + hbuf[0] = high >> 8; + hbuf[1] = high & 0x00FF; + hbuf[2] = sht3x_crc(&hbuf[0],2); + + lbuf[0] = low >> 8; + lbuf[1] = low & 0x00FF; + lbuf[2] = sht3x_crc(&lbuf[0],2); + + error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n", + device_xname(sc->sc_dev), error)); + } + + out: + if (! have_bus) { + iic_release_bus(sc->sc_tag, 0); + } +} + +static void +sht3x_set_alert_limits2(void *aux, uint16_t high, uint16_t low, + uint16_t highminusone, uint16_t lowplusone, bool have_bus) +{ + struct sht3x_sc *sc; + sc = aux; + + int error; + uint8_t hbuf[3]; + uint8_t lbuf[3]; + uint8_t hbufminusone[3]; + uint8_t lbufplusone[3]; + + if (! have_bus) { + error = iic_acquire_bus(sc->sc_tag, 0); + if (error) { + DPRINTF(sc, 2, ("%s: Could not acquire iic bus for " + "setting alerts %d\n", device_xname(sc->sc_dev), + error)); + return; + } + } + + hbuf[0] = high >> 8; + hbuf[1] = high & 0x00FF; + hbuf[2] = sht3x_crc(&hbuf[0],2); + + lbuf[0] = low >> 8; + lbuf[1] = low & 0x00FF; + lbuf[2] = sht3x_crc(&lbuf[0],2); + + hbufminusone[0] = highminusone >> 8; + hbufminusone[1] = highminusone & 0x00FF; + hbufminusone[2] = sht3x_crc(&hbufminusone[0],2); + + lbufplusone[0] = lowplusone >> 8; + lbufplusone[1] = lowplusone & 0x00FF; + lbufplusone[2] = sht3x_crc(&lbufplusone[0],2); + + DPRINTF(sc, 2, ("%s: Physical SET HIGH %02x %02x %02x\n", + device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2])); + error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + uint16_t sbuf; + int status_error; + status_error = sht3x_get_status_register(sc, &sbuf, true); + DPRINTF(sc, 2, ("%s: In SETTING, status register %04x -- %d\n", + device_xname(sc->sc_dev), sbuf, status_error)); + + hbuf[0] = 0; + hbuf[1] = 0; + hbuf[2] = 0; + error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, hbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not read high alert for SET %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + DPRINTF(sc, 2, ("%s: Physical READBACK SET HIGH %02x %02x %02x\n", + device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2])); + + DPRINTF(sc, 2, ("%s: Physical CLEAR HIGH %02x %02x %02x\n", + device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], + hbufminusone[2])); + error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbufminusone, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + hbufminusone[0] = 0; + hbufminusone[1] = 0; + hbufminusone[2] = 0; + error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, hbufminusone, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not read high alert for CLEAR %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + DPRINTF(sc, 2, ("%s: Physical READBACK CLEAR HIGH %02x %02x %02x\n", + device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], + hbufminusone[2])); + + DPRINTF(sc, 2, ("%s: Physical SET LOW %02x %02x %02x\n", + device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2])); + error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n", + device_xname(sc->sc_dev), error)); + goto out; + } + DPRINTF(sc, 2, ("%s: Physical CLEAR LOW %02x %02x %02x\n", + device_xname(sc->sc_dev), lbufplusone[0], lbufplusone[1], + lbufplusone[2])); + error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbufplusone, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n", + device_xname(sc->sc_dev), error)); + } + +out: + if (! have_bus) { + iic_release_bus(sc->sc_tag, 0); + } +} + +static void +sht3x_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata, + sysmon_envsys_lim_t *limits, uint32_t *props) +{ + struct sht3x_sc *sc = sme->sme_cookie; + uint16_t rawlimitshigh, rawlimitslow; + uint16_t rawlimitshighclear, rawlimitslowclear; + uint16_t rawlimitshighminusone, rawlimitslowplusone; + int error; + uint8_t lbuf[3]; + uint8_t limitscrchigh, limitskcrchigh, limitscrclow, limitskcrclow; + uint16_t limithigh, limitlow; + uint16_t limithighminusone, limitlowplusone; + + if (limits == NULL) { + printf("XXX - Need to set back to default... limits is NULL\n"); + return; + } + + DPRINTF(sc, 2, ("%s: In set_limits - %d -- %d %d\n", + device_xname(sc->sc_dev), edata->sensor, + limits->sel_critmin, limits->sel_critmax)); + + mutex_enter(&sc->sc_mutex); + error = iic_acquire_bus(sc->sc_tag, 0); + if (error) { + DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitshigh = (lbuf[0] << 8) | lbuf[1]; + limitskcrchigh = lbuf[2]; + limitscrchigh = sht3x_crc(&lbuf[0],2); + + + error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitslow = (lbuf[0] << 8) | lbuf[1]; + limitskcrclow = lbuf[2]; + limitscrclow = sht3x_crc(&lbuf[0],2); + + error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitshighclear = (lbuf[0] << 8) | lbuf[1]; + + error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_CLEAR, lbuf, 3); + if (error) { + DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + rawlimitslowclear = (lbuf[0] << 8) | lbuf[1]; + + DPRINTF(sc, 2, ("%s: Set limits current raw limits %04x - %02x %02x ; " + "%04x - %02x %02x ;; %04x %04x\n", + device_xname(sc->sc_dev), rawlimitshigh, limitskcrchigh, + limitscrchigh, rawlimitslow, limitskcrclow, limitscrclow, + rawlimitshighclear, rawlimitslowclear)); + + switch (edata->sensor) { + case SHT3X_TEMP_SENSOR: + limithigh = sht3x_compute_raw_from_temp(limits->sel_critmax); + limitlow = sht3x_compute_raw_from_temp(limits->sel_critmin); + limithigh = limithigh >> 7; + limithighminusone = limithigh - 1; + limitlow = limitlow >> 7; + limitlowplusone = limitlow + 1; + rawlimitshigh = (rawlimitshigh & 0xFE00) | limithigh; + rawlimitshighminusone = (rawlimitshigh & 0xFE00) | + limithighminusone; + rawlimitslow = (rawlimitslow & 0xFE00) | limitlow; + rawlimitslowplusone = (rawlimitslow & 0xFE00) | limitlowplusone; + DPRINTF(sc, 2, ("%s: Temp new raw limits high/low " + "%04x %04x %04x %04x\n", + device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow, + rawlimitshighminusone, rawlimitslowplusone)); + sht3x_set_alert_limits2(sc, rawlimitshigh, rawlimitslow, + rawlimitshighminusone, rawlimitslowplusone, true); + break; + case SHT3X_HUMIDITY_SENSOR: + limithigh = sht3x_compute_raw_from_rh(limits->sel_critmax); + limitlow = sht3x_compute_raw_from_rh(limits->sel_critmin); + limithigh = limithigh & 0xFE00; + limitlow = limitlow & 0xFE00; + rawlimitshigh = (rawlimitshigh & 0x1FF) | limithigh; + rawlimitslow = (rawlimitslow & 0x1FF) | limitlow; + DPRINTF(sc, 2, ("%s: RH new raw limits high/low " + "%04x %04x from %x %x\n", + device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow, + limithigh, limitlow)); + sht3x_set_alert_limits(sc, rawlimitshigh, rawlimitslow, true); + break; + default: + break; + } + + iic_release_bus(sc->sc_tag, 0); + out: + mutex_exit(&sc->sc_mutex); +} +#endif + static int sht3xopen(dev_t dev, int flags, int fmt, struct lwp *l) {