diff options
author | Dan Robertson <dan@dlrobertson.com> | 2019-09-04 21:45:53 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2019-09-10 14:42:56 -0400 |
commit | ffd96868ac5d4c22bba1ba2175d124cb2775f3f7 (patch) | |
tree | 4b2b792cbca4348f17f33700d0410028cc9b71cd /drivers/hwmon/shtc1.c | |
parent | fdc7d8e829ec755c5cfb2f5a8d8c0cdfb664f895 (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/shtc1.c')
-rw-r--r-- | drivers/hwmon/shtc1.c | 57 |
1 files changed, 43 insertions, 14 deletions
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 }; | |||
24 | static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c }; | 24 | static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c }; |
25 | 25 | ||
26 | /* command for reading the ID register */ | 26 | /* command for reading the ID register */ |
27 | static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 }; | 27 | static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 }; |
28 | 28 | ||
29 | /* constants for reading the ID register */ | 29 | /* |
30 | #define SHTC1_ID 0x07 | 30 | * constants for reading the ID register |
31 | #define SHTC1_ID_REG_MASK 0x3f | 31 | * SHTC1: 0x0007 with mask 0x003f |
32 | * SHTW1: 0x0007 with mask 0x003f | ||
33 | * SHTC3: 0x0807 with mask 0x083f | ||
34 | */ | ||
35 | #define SHTC3_ID 0x0807 | ||
36 | #define SHTC3_ID_MASK 0x083f | ||
37 | #define SHTC1_ID 0x0007 | ||
38 | #define SHTC1_ID_MASK 0x003f | ||
32 | 39 | ||
33 | /* delays for non-blocking i2c commands, both in us */ | 40 | /* delays for non-blocking i2c commands, both in us */ |
34 | #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 | 41 | #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 |
35 | #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000 | 42 | #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000 |
43 | #define SHTC3_NONBLOCKING_WAIT_TIME_HPM 12100 | ||
44 | #define SHTC3_NONBLOCKING_WAIT_TIME_LPM 800 | ||
36 | 45 | ||
37 | #define SHTC1_CMD_LENGTH 2 | 46 | #define SHTC1_CMD_LENGTH 2 |
38 | #define SHTC1_RESPONSE_LENGTH 6 | 47 | #define SHTC1_RESPONSE_LENGTH 6 |
39 | 48 | ||
49 | enum shtcx_chips { | ||
50 | shtc1, | ||
51 | shtc3, | ||
52 | }; | ||
53 | |||
40 | struct shtc1_data { | 54 | struct shtc1_data { |
41 | struct i2c_client *client; | 55 | struct i2c_client *client; |
42 | struct mutex update_lock; | 56 | struct mutex update_lock; |
@@ -47,6 +61,7 @@ struct shtc1_data { | |||
47 | unsigned int nonblocking_wait_time; /* in us */ | 61 | unsigned int nonblocking_wait_time; /* in us */ |
48 | 62 | ||
49 | struct shtc1_platform_data setup; | 63 | struct shtc1_platform_data setup; |
64 | enum shtcx_chips chip; | ||
50 | 65 | ||
51 | int temperature; /* 1000 * temperature in dgr C */ | 66 | int temperature; /* 1000 * temperature in dgr C */ |
52 | int humidity; /* 1000 * relative humidity in %RH */ | 67 | int humidity; /* 1000 * relative humidity in %RH */ |
@@ -157,13 +172,16 @@ static void shtc1_select_command(struct shtc1_data *data) | |||
157 | data->command = data->setup.blocking_io ? | 172 | data->command = data->setup.blocking_io ? |
158 | shtc1_cmd_measure_blocking_hpm : | 173 | shtc1_cmd_measure_blocking_hpm : |
159 | shtc1_cmd_measure_nonblocking_hpm; | 174 | shtc1_cmd_measure_nonblocking_hpm; |
160 | data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM; | 175 | data->nonblocking_wait_time = (data->chip == shtc1) ? |
161 | 176 | SHTC1_NONBLOCKING_WAIT_TIME_HPM : | |
177 | SHTC3_NONBLOCKING_WAIT_TIME_HPM; | ||
162 | } else { | 178 | } else { |
163 | data->command = data->setup.blocking_io ? | 179 | data->command = data->setup.blocking_io ? |
164 | shtc1_cmd_measure_blocking_lpm : | 180 | shtc1_cmd_measure_blocking_lpm : |
165 | shtc1_cmd_measure_nonblocking_lpm; | 181 | shtc1_cmd_measure_nonblocking_lpm; |
166 | data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM; | 182 | data->nonblocking_wait_time = (data->chip == shtc1) ? |
183 | SHTC1_NONBLOCKING_WAIT_TIME_LPM : | ||
184 | SHTC3_NONBLOCKING_WAIT_TIME_LPM; | ||
167 | } | 185 | } |
168 | } | 186 | } |
169 | 187 | ||
@@ -171,9 +189,11 @@ static int shtc1_probe(struct i2c_client *client, | |||
171 | const struct i2c_device_id *id) | 189 | const struct i2c_device_id *id) |
172 | { | 190 | { |
173 | int ret; | 191 | int ret; |
174 | char id_reg[2]; | 192 | u16 id_reg; |
193 | char id_reg_buf[2]; | ||
175 | struct shtc1_data *data; | 194 | struct shtc1_data *data; |
176 | struct device *hwmon_dev; | 195 | struct device *hwmon_dev; |
196 | enum shtcx_chips chip = id->driver_data; | ||
177 | struct i2c_adapter *adap = client->adapter; | 197 | struct i2c_adapter *adap = client->adapter; |
178 | struct device *dev = &client->dev; | 198 | struct device *dev = &client->dev; |
179 | 199 | ||
@@ -187,13 +207,20 @@ static int shtc1_probe(struct i2c_client *client, | |||
187 | dev_err(dev, "could not send read_id_reg command: %d\n", ret); | 207 | dev_err(dev, "could not send read_id_reg command: %d\n", ret); |
188 | return ret < 0 ? ret : -ENODEV; | 208 | return ret < 0 ? ret : -ENODEV; |
189 | } | 209 | } |
190 | ret = i2c_master_recv(client, id_reg, sizeof(id_reg)); | 210 | ret = i2c_master_recv(client, id_reg_buf, sizeof(id_reg_buf)); |
191 | if (ret != sizeof(id_reg)) { | 211 | if (ret != sizeof(id_reg_buf)) { |
192 | dev_err(dev, "could not read ID register: %d\n", ret); | 212 | dev_err(dev, "could not read ID register: %d\n", ret); |
193 | return -ENODEV; | 213 | return -ENODEV; |
194 | } | 214 | } |
195 | if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) { | 215 | |
196 | dev_err(dev, "ID register doesn't match\n"); | 216 | id_reg = be16_to_cpup((__be16 *)id_reg_buf); |
217 | if (chip == shtc3) { | ||
218 | if ((id_reg & SHTC3_ID_MASK) != SHTC3_ID) { | ||
219 | dev_err(dev, "SHTC3 ID register does not match\n"); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | } else if ((id_reg & SHTC1_ID_MASK) != SHTC1_ID) { | ||
223 | dev_err(dev, "SHTC1 ID register does not match\n"); | ||
197 | return -ENODEV; | 224 | return -ENODEV; |
198 | } | 225 | } |
199 | 226 | ||
@@ -204,6 +231,7 @@ static int shtc1_probe(struct i2c_client *client, | |||
204 | data->setup.blocking_io = false; | 231 | data->setup.blocking_io = false; |
205 | data->setup.high_precision = true; | 232 | data->setup.high_precision = true; |
206 | data->client = client; | 233 | data->client = client; |
234 | data->chip = chip; | ||
207 | 235 | ||
208 | if (client->dev.platform_data) | 236 | if (client->dev.platform_data) |
209 | data->setup = *(struct shtc1_platform_data *)dev->platform_data; | 237 | data->setup = *(struct shtc1_platform_data *)dev->platform_data; |
@@ -222,8 +250,9 @@ static int shtc1_probe(struct i2c_client *client, | |||
222 | 250 | ||
223 | /* device ID table */ | 251 | /* device ID table */ |
224 | static const struct i2c_device_id shtc1_id[] = { | 252 | static const struct i2c_device_id shtc1_id[] = { |
225 | { "shtc1", 0 }, | 253 | { "shtc1", shtc1 }, |
226 | { "shtw1", 0 }, | 254 | { "shtw1", shtc1 }, |
255 | { "shtc3", shtc3 }, | ||
227 | { } | 256 | { } |
228 | }; | 257 | }; |
229 | MODULE_DEVICE_TABLE(i2c, shtc1_id); | 258 | MODULE_DEVICE_TABLE(i2c, shtc1_id); |