Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Fix the serial number handling of the HTU21D chip and probab...



details:   https://anonhg.NetBSD.org/src/rev/9a8debde41ba
branches:  trunk
changeset: 1025554:9a8debde41ba
user:      brad <brad%NetBSD.org@localhost>
date:      Fri Nov 12 15:12:11 2021 +0000

description:
Fix the serial number handling of the HTU21D chip and probably others.
Increase the number of read attempts as the HTU21D and probably others
do not respond as fast the actual SI70xx chip can.

diffstat:

 share/man/man4/si70xxtemp.4 |   4 +-
 sys/dev/i2c/si70xx.c        |  53 ++++++++++++++++++++++++++++++++------------
 2 files changed, 40 insertions(+), 17 deletions(-)

diffs (144 lines):

diff -r 12d1de592dba -r 9a8debde41ba share/man/man4/si70xxtemp.4
--- a/share/man/man4/si70xxtemp.4       Fri Nov 12 07:41:55 2021 +0000
+++ b/share/man/man4/si70xxtemp.4       Fri Nov 12 15:12:11 2021 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: si70xxtemp.4,v 1.6 2021/11/11 14:24:24 wiz Exp $
+.\" $NetBSD: si70xxtemp.4,v 1.7 2021/11/12 15:12:11 brad Exp $
 .\"
 .\" Copyright (c) 2017 Brad Spencer <brad%anduin.eldar.org@localhost>
 .\"
@@ -72,7 +72,7 @@
 Depending on the resolution, and other factors, the wait time varies.
 The driver will attempt to read back the values readattempts number of
 times.
-The default is 25 which should be more than enough for most purposes.
+The default is 40 which should be enough for most purposes.
 There is an initial wait of 10,500 microseconds followed by
 a additional 1,000 microseconds per read attempt.
 .El
diff -r 12d1de592dba -r 9a8debde41ba sys/dev/i2c/si70xx.c
--- a/sys/dev/i2c/si70xx.c      Fri Nov 12 07:41:55 2021 +0000
+++ b/sys/dev/i2c/si70xx.c      Fri Nov 12 15:12:11 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: si70xx.c,v 1.9 2021/11/11 14:16:04 brad Exp $  */
+/*     $NetBSD: si70xx.c,v 1.10 2021/11/12 15:12:11 brad Exp $ */
 
 /*
  * Copyright (c) 2017 Brad Spencer <brad%anduin.eldar.org@localhost>
@@ -17,7 +17,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: si70xx.c,v 1.9 2021/11/11 14:16:04 brad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: si70xx.c,v 1.10 2021/11/12 15:12:11 brad Exp $");
 
 /*
   Driver for the Silicon Labs SI7013/SI7020/SI7021, HTU21D and SHT21
@@ -609,6 +609,7 @@
        uint8_t testcrcpt1[4];
        uint8_t testcrcpt2[4];
        uint8_t crc1 = 0, crc2 = 0;
+       bool validcrcpt1, validcrcpt2;
        uint8_t readcrc1 = 0, readcrc2 = 0;
        uint8_t fwversion = 0, model, heaterregister;
 
@@ -622,7 +623,7 @@
 #ifdef HAVE_I2C_EXECV
        sc->sc_clockstretch = 2048;
 #endif
-       sc->sc_readattempts = 25;
+       sc->sc_readattempts = 40;
        sc->sc_ignorecrc = false;
        sc->sc_sme = NULL;
        sc->sc_noheater = false;
@@ -665,11 +666,24 @@
        testcrcpt1[3] = buf[6];
        readcrc1 = buf[7];
        crc1 = si70xx_crc(testcrcpt1, 4);
+       /* A "real" SI70xx has the CRC cover the entire first part of the
+        * serial number.  An HTU21D has the CRC broken out into each
+        * part of the serial number.
+        */
+       validcrcpt1 = (readcrc1 == crc1);
+       if (! validcrcpt1) {
+               validcrcpt1 = (si70xx_crc(&testcrcpt1[0],1) == buf[1] &&
+                   si70xx_crc(&testcrcpt1[1],1) == buf[3] &&
+                   si70xx_crc(&testcrcpt1[2],1) == buf[5] &&
+                   si70xx_crc(&testcrcpt1[3],1) == buf[7]);
+               DPRINTF(sc, 2, ("%s: Part 1 SN CRC was not valid for real type, "
+                   "check clone: %d\n", device_xname(sc->sc_dev), validcrcpt1));
+       }
 
        DPRINTF(sc, 2, ("%s: read 1 values: %02x%02x%02x%02x%02x%02x%02x%02x "
-           "- %02x\n", device_xname(sc->sc_dev), buf[0], buf[1],
+           "- %02x -- %d\n", device_xname(sc->sc_dev), buf[0], buf[1],
            buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
-           crc1));
+           crc1, validcrcpt1));
 
        error = si70xx_cmd2(sc, SI70XX_READ_ID_PT2A, SI70XX_READ_ID_PT2B,
            buf, 8);
@@ -684,16 +698,30 @@
        testcrcpt2[3] = buf[4];
        readcrc2 = buf[5];
        crc2 = si70xx_crc(testcrcpt2, 4);
+       /* It is even stranger for this part of the serial number.  A "real"
+        * SI70XX will have a single CRC for the entire second part, but
+        * an HTU21D has a CRC for each word in this case.
+        *
+        * The datasheet actually agrees with the HTU21D case, and not the "real"
+        * chip.
+        */
+       validcrcpt2 = (readcrc2 == crc2);
+       if (! validcrcpt2) {
+               validcrcpt2 = (si70xx_crc(&testcrcpt2[0],2) == buf[2] &&
+                   si70xx_crc(&testcrcpt2[2],2) == buf[5]);
+               DPRINTF(sc, 2, ("%s: Part 2 SN CRC was not valid for real type, "
+                   "check clone: %d\n", device_xname(sc->sc_dev), validcrcpt2));
+       }
 
-       DPRINTF(sc, 2, ("%s: read 2 values: %02x%02x%02x%02x%02x%02x - %02x\n",
+       DPRINTF(sc, 2, ("%s: read 2 values: %02x%02x%02x%02x%02x%02x - %02x -- %d\n",
            device_xname(sc->sc_dev), buf[0], buf[1], buf[2],
-           buf[3], buf[4], buf[5], crc2));
+           buf[3], buf[4], buf[5], crc2, validcrcpt2));
 
        error = si70xx_cmd2(sc, SI70XX_READ_FW_VERA, SI70XX_READ_FW_VERB,
            buf, 8);
 
        if (error) {
-               aprint_error_dev(self, "Failed to read firmware version: %d\n",
+               aprint_error_dev(self, "Failed to read firmware version: Error %d\n",
                    error);
                sc->sc_nofw = true;
        }
@@ -706,7 +734,7 @@
        error = si70xx_cmd1(sc, SI70XX_READ_HEATER_REG, &heaterregister, 1);
 
        if (error) {
-               aprint_error_dev(self, "Failed to read heater register: %d\n",
+               aprint_error_dev(self, "Failed to read heater register: Error %d\n",
                    error);
                sc->sc_noheater = true;
        }
@@ -759,11 +787,6 @@
                sc->sc_sme = NULL;
                return;
        }
-       if (ecount != 0) {
-               aprint_normal_dev(self, "Could not read model, "
-                   "probably an HTU21D\n");
-               return;
-       }
 
        char modelstr[64];
        switch (model) {
@@ -800,7 +823,7 @@
            modelstr, fwversionstr, testcrcpt1[0], testcrcpt1[1],
            testcrcpt1[2], testcrcpt1[3], testcrcpt2[0], testcrcpt2[1],
            testcrcpt2[2], testcrcpt2[3],
-           (crc1 == readcrc1 && crc2 == readcrc2) ? "\n" : " (bad crc)\n");
+           (validcrcpt1 && validcrcpt2) ? "\n" : " (bad crc)\n");
        return;
 out:
        sysmon_envsys_destroy(sc->sc_sme);



Home | Main Index | Thread Index | Old Index