hwmon: (shtc1) add support for the SHTC3 sensor
authorDan Robertson <dan@dlrobertson.com>
Thu, 5 Sep 2019 01:45:53 +0000 (01:45 +0000)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 10 Sep 2019 18:42:56 +0000 (11:42 -0700)
Add support for the Sensirion SHTC3 humidity and temperature sensor to
the shtc1 module.

Signed-off-by: Dan Robertson <dan@dlrobertson.com>
Link: https://lore.kernel.org/r/20190905014554.21658-2-dan@dlrobertson.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Documentation/hwmon/shtc1.rst
drivers/hwmon/Kconfig
drivers/hwmon/shtc1.c

index aa11633..9b0f1ee 100644 (file)
@@ -19,7 +19,17 @@ Supported chips:
 
     Addresses scanned: none
 
-    Datasheet: Not publicly available
+    Datasheet: http://www.sensirion.com/file/datasheet_shtw1
+
+
+
+  * Sensirion SHTC3
+
+    Prefix: 'shtc3'
+
+    Addresses scanned: none
+
+    Datasheet: http://www.sensirion.com/file/datasheet_shtc3
 
 
 
@@ -30,10 +40,9 @@ Author:
 Description
 -----------
 
-This driver implements support for the Sensirion SHTC1 chip, a humidity and
-temperature sensor. Temperature is measured in degrees celsius, relative
-humidity is expressed as a percentage. Driver can be used as well for SHTW1
-chip, which has the same electrical interface.
+This driver implements support for the Sensirion SHTC1, SHTW1, and SHTC3
+chips, a humidity and temperature sensor. Temperature is measured in degrees
+celsius, relative humidity is expressed as a percentage.
 
 The device communicates with the I2C protocol. All sensors are set to I2C
 address 0x70. See Documentation/i2c/instantiating-devices for methods to
index c823b66..2ca5668 100644 (file)
@@ -1392,8 +1392,8 @@ config SENSORS_SHTC1
        tristate "Sensiron humidity and temperature sensors. SHTC1 and compat."
        depends on I2C
        help
-         If you say yes here you get support for the Sensiron SHTC1 and SHTW1
-         humidity and temperature sensors.
+         If you say yes here you get support for the Sensiron SHTC1, SHTW1,
+         and SHTC3 humidity and temperature sensors.
 
          This driver can also be built as a module. If so, the module
          will be called shtc1.
index b267cf2..a0078cc 100644 (file)
@@ -24,19 +24,33 @@ static const unsigned char shtc1_cmd_measure_blocking_lpm[]    = { 0x64, 0x58 };
 static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c };
 
 /* command for reading the ID register */
-static const unsigned char shtc1_cmd_read_id_reg[]            = { 0xef, 0xc8 };
+static const unsigned char shtc1_cmd_read_id_reg[]             = { 0xef, 0xc8 };
 
-/* constants for reading the ID register */
-#define SHTC1_ID         0x07
-#define SHTC1_ID_REG_MASK 0x3f
+/*
+ * constants for reading the ID register
+ * SHTC1: 0x0007 with mask 0x003f
+ * SHTW1: 0x0007 with mask 0x003f
+ * SHTC3: 0x0807 with mask 0x083f
+ */
+#define SHTC3_ID      0x0807
+#define SHTC3_ID_MASK 0x083f
+#define SHTC1_ID      0x0007
+#define SHTC1_ID_MASK 0x003f
 
 /* delays for non-blocking i2c commands, both in us */
 #define SHTC1_NONBLOCKING_WAIT_TIME_HPM  14400
 #define SHTC1_NONBLOCKING_WAIT_TIME_LPM   1000
+#define SHTC3_NONBLOCKING_WAIT_TIME_HPM  12100
+#define SHTC3_NONBLOCKING_WAIT_TIME_LPM    800
 
 #define SHTC1_CMD_LENGTH      2
 #define SHTC1_RESPONSE_LENGTH 6
 
+enum shtcx_chips {
+       shtc1,
+       shtc3,
+};
+
 struct shtc1_data {
        struct i2c_client *client;
        struct mutex update_lock;
@@ -47,6 +61,7 @@ struct shtc1_data {
        unsigned int nonblocking_wait_time; /* in us */
 
        struct shtc1_platform_data setup;
+       enum shtcx_chips chip;
 
        int temperature; /* 1000 * temperature in dgr C */
        int humidity; /* 1000 * relative humidity in %RH */
@@ -157,13 +172,16 @@ static void shtc1_select_command(struct shtc1_data *data)
                data->command = data->setup.blocking_io ?
                                shtc1_cmd_measure_blocking_hpm :
                                shtc1_cmd_measure_nonblocking_hpm;
-               data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM;
-
+               data->nonblocking_wait_time = (data->chip == shtc1) ?
+                               SHTC1_NONBLOCKING_WAIT_TIME_HPM :
+                               SHTC3_NONBLOCKING_WAIT_TIME_HPM;
        } else {
                data->command = data->setup.blocking_io ?
                                shtc1_cmd_measure_blocking_lpm :
                                shtc1_cmd_measure_nonblocking_lpm;
-               data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM;
+               data->nonblocking_wait_time = (data->chip == shtc1) ?
+                               SHTC1_NONBLOCKING_WAIT_TIME_LPM :
+                               SHTC3_NONBLOCKING_WAIT_TIME_LPM;
        }
 }
 
@@ -171,9 +189,11 @@ static int shtc1_probe(struct i2c_client *client,
                       const struct i2c_device_id *id)
 {
        int ret;
-       char id_reg[2];
+       u16 id_reg;
+       char id_reg_buf[2];
        struct shtc1_data *data;
        struct device *hwmon_dev;
+       enum shtcx_chips chip = id->driver_data;
        struct i2c_adapter *adap = client->adapter;
        struct device *dev = &client->dev;
 
@@ -187,13 +207,20 @@ static int shtc1_probe(struct i2c_client *client,
                dev_err(dev, "could not send read_id_reg command: %d\n", ret);
                return ret < 0 ? ret : -ENODEV;
        }
-       ret = i2c_master_recv(client, id_reg, sizeof(id_reg));
-       if (ret != sizeof(id_reg)) {
+       ret = i2c_master_recv(client, id_reg_buf, sizeof(id_reg_buf));
+       if (ret != sizeof(id_reg_buf)) {
                dev_err(dev, "could not read ID register: %d\n", ret);
                return -ENODEV;
        }
-       if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) {
-               dev_err(dev, "ID register doesn't match\n");
+
+       id_reg = be16_to_cpup((__be16 *)id_reg_buf);
+       if (chip == shtc3) {
+               if ((id_reg & SHTC3_ID_MASK) != SHTC3_ID) {
+                       dev_err(dev, "SHTC3 ID register does not match\n");
+                       return -ENODEV;
+               }
+       } else if ((id_reg & SHTC1_ID_MASK) != SHTC1_ID) {
+               dev_err(dev, "SHTC1 ID register does not match\n");
                return -ENODEV;
        }
 
@@ -204,6 +231,7 @@ static int shtc1_probe(struct i2c_client *client,
        data->setup.blocking_io = false;
        data->setup.high_precision = true;
        data->client = client;
+       data->chip = chip;
 
        if (client->dev.platform_data)
                data->setup = *(struct shtc1_platform_data *)dev->platform_data;
@@ -222,8 +250,9 @@ static int shtc1_probe(struct i2c_client *client,
 
 /* device ID table */
 static const struct i2c_device_id shtc1_id[] = {
-       { "shtc1", 0 },
-       { "shtw1", 0 },
+       { "shtc1", shtc1 },
+       { "shtw1", shtc1 },
+       { "shtc3", shtc3 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, shtc1_id);