summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorDan Robertson <dan@dlrobertson.com>2019-09-05 01:45:53 +0000
committerGuenter Roeck <linux@roeck-us.net>2019-09-10 11:42:56 -0700
commitffd96868ac5d4c22bba1ba2175d124cb2775f3f7 (patch)
tree4b2b792cbca4348f17f33700d0410028cc9b71cd /drivers/hwmon
parentfdc7d8e829ec755c5cfb2f5a8d8c0cdfb664f895 (diff)
hwmon: (shtc1) add support for the SHTC3 sensor
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>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/shtc1.c57
2 files changed, 45 insertions, 16 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c823b662adc9..2ca5668bdb62 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -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.
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
index b267cf2a9817..a0078ccede03 100644
--- a/drivers/hwmon/shtc1.c
+++ b/drivers/hwmon/shtc1.c
@@ -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);