1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* Sensirion SHT3x-DIS humidity and temperature sensor driver. |
3 | * The SHT3x comes in many different versions, this driver is for the |
4 | * I2C version only. |
5 | * |
6 | * Copyright (C) 2016 Sensirion AG, Switzerland |
7 | * Author: David Frey <david.frey@sensirion.com> |
8 | * Author: Pascal Sachs <pascal.sachs@sensirion.com> |
9 | */ |
10 | |
11 | #include <asm/page.h> |
12 | #include <linux/crc8.h> |
13 | #include <linux/debugfs.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/err.h> |
16 | #include <linux/hwmon.h> |
17 | #include <linux/hwmon-sysfs.h> |
18 | #include <linux/i2c.h> |
19 | #include <linux/init.h> |
20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> |
22 | #include <linux/slab.h> |
23 | #include <linux/jiffies.h> |
24 | |
25 | /* commands (high repeatability mode) */ |
26 | static const unsigned char sht3x_cmd_measure_single_hpm[] = { 0x24, 0x00 }; |
27 | |
28 | /* commands (medium repeatability mode) */ |
29 | static const unsigned char sht3x_cmd_measure_single_mpm[] = { 0x24, 0x0b }; |
30 | |
31 | /* commands (low repeatability mode) */ |
32 | static const unsigned char sht3x_cmd_measure_single_lpm[] = { 0x24, 0x16 }; |
33 | |
34 | /* commands for periodic mode */ |
35 | static const unsigned char sht3x_cmd_measure_periodic_mode[] = { 0xe0, 0x00 }; |
36 | static const unsigned char sht3x_cmd_break[] = { 0x30, 0x93 }; |
37 | |
38 | /* commands for heater control */ |
39 | static const unsigned char sht3x_cmd_heater_on[] = { 0x30, 0x6d }; |
40 | static const unsigned char sht3x_cmd_heater_off[] = { 0x30, 0x66 }; |
41 | |
42 | /* other commands */ |
43 | static const unsigned char sht3x_cmd_read_status_reg[] = { 0xf3, 0x2d }; |
44 | static const unsigned char sht3x_cmd_clear_status_reg[] = { 0x30, 0x41 }; |
45 | static const unsigned char sht3x_cmd_read_serial_number[] = { 0x37, 0x80 }; |
46 | |
47 | static struct dentry *debugfs; |
48 | |
49 | /* delays for single-shot mode i2c commands, both in us */ |
50 | #define SHT3X_SINGLE_WAIT_TIME_HPM 15000 |
51 | #define SHT3X_SINGLE_WAIT_TIME_MPM 6000 |
52 | #define SHT3X_SINGLE_WAIT_TIME_LPM 4000 |
53 | |
54 | #define SHT3X_WORD_LEN 2 |
55 | #define SHT3X_CMD_LENGTH 2 |
56 | #define SHT3X_CRC8_LEN 1 |
57 | #define SHT3X_RESPONSE_LENGTH 6 |
58 | #define SHT3X_CRC8_POLYNOMIAL 0x31 |
59 | #define SHT3X_CRC8_INIT 0xFF |
60 | #define SHT3X_MIN_TEMPERATURE -45000 |
61 | #define SHT3X_MAX_TEMPERATURE 130000 |
62 | #define SHT3X_MIN_HUMIDITY 0 |
63 | #define SHT3X_MAX_HUMIDITY 100000 |
64 | |
65 | enum sht3x_chips { |
66 | sht3x, |
67 | sts3x, |
68 | }; |
69 | |
70 | enum sht3x_limits { |
71 | limit_max = 0, |
72 | limit_max_hyst, |
73 | limit_min, |
74 | limit_min_hyst, |
75 | }; |
76 | |
77 | enum sht3x_repeatability { |
78 | low_repeatability, |
79 | medium_repeatability, |
80 | high_repeatability, |
81 | }; |
82 | |
83 | DECLARE_CRC8_TABLE(sht3x_crc8_table); |
84 | |
85 | /* periodic measure commands (high repeatability mode) */ |
86 | static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = { |
87 | /* 0.5 measurements per second */ |
88 | {0x20, 0x32}, |
89 | /* 1 measurements per second */ |
90 | {0x21, 0x30}, |
91 | /* 2 measurements per second */ |
92 | {0x22, 0x36}, |
93 | /* 4 measurements per second */ |
94 | {0x23, 0x34}, |
95 | /* 10 measurements per second */ |
96 | {0x27, 0x37}, |
97 | }; |
98 | |
99 | /* periodic measure commands (medium repeatability) */ |
100 | static const char periodic_measure_commands_mpm[][SHT3X_CMD_LENGTH] = { |
101 | /* 0.5 measurements per second */ |
102 | {0x20, 0x24}, |
103 | /* 1 measurements per second */ |
104 | {0x21, 0x26}, |
105 | /* 2 measurements per second */ |
106 | {0x22, 0x20}, |
107 | /* 4 measurements per second */ |
108 | {0x23, 0x22}, |
109 | /* 10 measurements per second */ |
110 | {0x27, 0x21}, |
111 | }; |
112 | |
113 | /* periodic measure commands (low repeatability mode) */ |
114 | static const char periodic_measure_commands_lpm[][SHT3X_CMD_LENGTH] = { |
115 | /* 0.5 measurements per second */ |
116 | {0x20, 0x2f}, |
117 | /* 1 measurements per second */ |
118 | {0x21, 0x2d}, |
119 | /* 2 measurements per second */ |
120 | {0x22, 0x2b}, |
121 | /* 4 measurements per second */ |
122 | {0x23, 0x29}, |
123 | /* 10 measurements per second */ |
124 | {0x27, 0x2a}, |
125 | }; |
126 | |
127 | struct sht3x_limit_commands { |
128 | const char read_command[SHT3X_CMD_LENGTH]; |
129 | const char write_command[SHT3X_CMD_LENGTH]; |
130 | }; |
131 | |
132 | static const struct sht3x_limit_commands limit_commands[] = { |
133 | /* temp1_max, humidity1_max */ |
134 | [limit_max] = { {0xe1, 0x1f}, {0x61, 0x1d} }, |
135 | /* temp_1_max_hyst, humidity1_max_hyst */ |
136 | [limit_max_hyst] = { .read_command: {0xe1, 0x14}, .write_command: {0x61, 0x16} }, |
137 | /* temp1_min, humidity1_min */ |
138 | [limit_min] = { .read_command: {0xe1, 0x02}, .write_command: {0x61, 0x00} }, |
139 | /* temp_1_min_hyst, humidity1_min_hyst */ |
140 | [limit_min_hyst] = { .read_command: {0xe1, 0x09}, .write_command: {0x61, 0x0B} }, |
141 | }; |
142 | |
143 | #define SHT3X_NUM_LIMIT_CMD ARRAY_SIZE(limit_commands) |
144 | |
145 | static const u16 mode_to_update_interval[] = { |
146 | 0, |
147 | 2000, |
148 | 1000, |
149 | 500, |
150 | 250, |
151 | 100, |
152 | }; |
153 | |
154 | static const struct hwmon_channel_info * const sht3x_channel_info[] = { |
155 | HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), |
156 | HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN | |
157 | HWMON_T_MIN_HYST | HWMON_T_MAX | |
158 | HWMON_T_MAX_HYST | HWMON_T_ALARM), |
159 | HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN | |
160 | HWMON_H_MIN_HYST | HWMON_H_MAX | |
161 | HWMON_H_MAX_HYST | HWMON_H_ALARM), |
162 | NULL, |
163 | }; |
164 | |
165 | struct sht3x_data { |
166 | struct i2c_client *client; |
167 | enum sht3x_chips chip_id; |
168 | struct mutex i2c_lock; /* lock for sending i2c commands */ |
169 | struct mutex data_lock; /* lock for updating driver data */ |
170 | struct dentry *sensor_dir; |
171 | |
172 | u8 mode; |
173 | const unsigned char *command; |
174 | u32 wait_time; /* in us*/ |
175 | unsigned long last_update; /* last update in periodic mode*/ |
176 | enum sht3x_repeatability repeatability; |
177 | u32 serial_number; |
178 | |
179 | /* |
180 | * cached values for temperature and humidity and limits |
181 | * the limits arrays have the following order: |
182 | * max, max_hyst, min, min_hyst |
183 | */ |
184 | int temperature; |
185 | int temperature_limits[SHT3X_NUM_LIMIT_CMD]; |
186 | u32 humidity; |
187 | u32 humidity_limits[SHT3X_NUM_LIMIT_CMD]; |
188 | }; |
189 | |
190 | static u8 get_mode_from_update_interval(u16 value) |
191 | { |
192 | size_t index; |
193 | u8 number_of_modes = ARRAY_SIZE(mode_to_update_interval); |
194 | |
195 | if (value == 0) |
196 | return 0; |
197 | |
198 | /* find next faster update interval */ |
199 | for (index = 1; index < number_of_modes; index++) { |
200 | if (mode_to_update_interval[index] <= value) |
201 | return index; |
202 | } |
203 | |
204 | return number_of_modes - 1; |
205 | } |
206 | |
207 | static int sht3x_read_from_command(struct i2c_client *client, |
208 | struct sht3x_data *data, |
209 | const char *command, |
210 | char *buf, int length, u32 wait_time) |
211 | { |
212 | int ret; |
213 | |
214 | mutex_lock(&data->i2c_lock); |
215 | ret = i2c_master_send(client, buf: command, SHT3X_CMD_LENGTH); |
216 | |
217 | if (ret != SHT3X_CMD_LENGTH) { |
218 | ret = ret < 0 ? ret : -EIO; |
219 | goto out; |
220 | } |
221 | |
222 | if (wait_time) |
223 | usleep_range(min: wait_time, max: wait_time + 1000); |
224 | |
225 | ret = i2c_master_recv(client, buf, count: length); |
226 | if (ret != length) { |
227 | ret = ret < 0 ? ret : -EIO; |
228 | goto out; |
229 | } |
230 | |
231 | ret = 0; |
232 | out: |
233 | mutex_unlock(lock: &data->i2c_lock); |
234 | return ret; |
235 | } |
236 | |
237 | static int (u16 raw) |
238 | { |
239 | /* |
240 | * From datasheet: |
241 | * T = -45 + 175 * ST / 2^16 |
242 | * Adapted for integer fixed point (3 digit) arithmetic. |
243 | */ |
244 | return ((21875 * (int)raw) >> 13) - 45000; |
245 | } |
246 | |
247 | static u32 (u16 raw) |
248 | { |
249 | /* |
250 | * From datasheet: |
251 | * RH = 100 * SRH / 2^16 |
252 | * Adapted for integer fixed point (3 digit) arithmetic. |
253 | */ |
254 | return (12500 * (u32)raw) >> 13; |
255 | } |
256 | |
257 | static struct sht3x_data *sht3x_update_client(struct device *dev) |
258 | { |
259 | struct sht3x_data *data = dev_get_drvdata(dev); |
260 | struct i2c_client *client = data->client; |
261 | u16 interval_ms = mode_to_update_interval[data->mode]; |
262 | unsigned long interval_jiffies = msecs_to_jiffies(m: interval_ms); |
263 | unsigned char buf[SHT3X_RESPONSE_LENGTH]; |
264 | u16 val; |
265 | int ret = 0; |
266 | |
267 | mutex_lock(&data->data_lock); |
268 | /* |
269 | * Only update cached readings once per update interval in periodic |
270 | * mode. In single shot mode the sensor measures values on demand, so |
271 | * every time the sysfs interface is called, a measurement is triggered. |
272 | * In periodic mode however, the measurement process is handled |
273 | * internally by the sensor and reading out sensor values only makes |
274 | * sense if a new reading is available. |
275 | */ |
276 | if (time_after(jiffies, data->last_update + interval_jiffies)) { |
277 | ret = sht3x_read_from_command(client, data, command: data->command, buf, |
278 | length: sizeof(buf), wait_time: data->wait_time); |
279 | if (ret) |
280 | goto out; |
281 | |
282 | val = be16_to_cpup(p: (__be16 *)buf); |
283 | data->temperature = sht3x_extract_temperature(raw: val); |
284 | val = be16_to_cpup(p: (__be16 *)(buf + 3)); |
285 | data->humidity = sht3x_extract_humidity(raw: val); |
286 | data->last_update = jiffies; |
287 | } |
288 | |
289 | out: |
290 | mutex_unlock(lock: &data->data_lock); |
291 | if (ret) |
292 | return ERR_PTR(error: ret); |
293 | |
294 | return data; |
295 | } |
296 | |
297 | static int temp1_input_read(struct device *dev) |
298 | { |
299 | struct sht3x_data *data = sht3x_update_client(dev); |
300 | |
301 | if (IS_ERR(ptr: data)) |
302 | return PTR_ERR(ptr: data); |
303 | |
304 | return data->temperature; |
305 | } |
306 | |
307 | static int humidity1_input_read(struct device *dev) |
308 | { |
309 | struct sht3x_data *data = sht3x_update_client(dev); |
310 | |
311 | if (IS_ERR(ptr: data)) |
312 | return PTR_ERR(ptr: data); |
313 | |
314 | return data->humidity; |
315 | } |
316 | |
317 | /* |
318 | * limits_update must only be called from probe or with data_lock held |
319 | */ |
320 | static int limits_update(struct sht3x_data *data) |
321 | { |
322 | int ret; |
323 | u8 index; |
324 | int temperature; |
325 | u32 humidity; |
326 | u16 raw; |
327 | char buffer[SHT3X_RESPONSE_LENGTH]; |
328 | const struct sht3x_limit_commands *commands; |
329 | struct i2c_client *client = data->client; |
330 | |
331 | for (index = 0; index < SHT3X_NUM_LIMIT_CMD; index++) { |
332 | commands = &limit_commands[index]; |
333 | ret = sht3x_read_from_command(client, data, |
334 | command: commands->read_command, buf: buffer, |
335 | SHT3X_RESPONSE_LENGTH, wait_time: 0); |
336 | |
337 | if (ret) |
338 | return ret; |
339 | |
340 | raw = be16_to_cpup(p: (__be16 *)buffer); |
341 | temperature = sht3x_extract_temperature(raw: (raw & 0x01ff) << 7); |
342 | humidity = sht3x_extract_humidity(raw: raw & 0xfe00); |
343 | data->temperature_limits[index] = temperature; |
344 | data->humidity_limits[index] = humidity; |
345 | } |
346 | |
347 | return ret; |
348 | } |
349 | |
350 | static int temp1_limit_read(struct device *dev, int index) |
351 | { |
352 | struct sht3x_data *data = dev_get_drvdata(dev); |
353 | |
354 | return data->temperature_limits[index]; |
355 | } |
356 | |
357 | static int humidity1_limit_read(struct device *dev, int index) |
358 | { |
359 | struct sht3x_data *data = dev_get_drvdata(dev); |
360 | |
361 | return data->humidity_limits[index]; |
362 | } |
363 | |
364 | /* |
365 | * limit_write must only be called with data_lock held |
366 | */ |
367 | static size_t limit_write(struct device *dev, |
368 | u8 index, |
369 | int temperature, |
370 | u32 humidity) |
371 | { |
372 | char buffer[SHT3X_CMD_LENGTH + SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; |
373 | char *position = buffer; |
374 | int ret; |
375 | u16 raw; |
376 | struct sht3x_data *data = dev_get_drvdata(dev); |
377 | struct i2c_client *client = data->client; |
378 | const struct sht3x_limit_commands *commands; |
379 | |
380 | commands = &limit_commands[index]; |
381 | |
382 | memcpy(position, commands->write_command, SHT3X_CMD_LENGTH); |
383 | position += SHT3X_CMD_LENGTH; |
384 | /* |
385 | * ST = (T + 45) / 175 * 2^16 |
386 | * SRH = RH / 100 * 2^16 |
387 | * adapted for fixed point arithmetic and packed the same as |
388 | * in limit_read() |
389 | */ |
390 | raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7); |
391 | raw |= ((humidity * 42950) >> 16) & 0xfe00; |
392 | |
393 | *((__be16 *)position) = cpu_to_be16(raw); |
394 | position += SHT3X_WORD_LEN; |
395 | *position = crc8(table: sht3x_crc8_table, |
396 | pdata: position - SHT3X_WORD_LEN, |
397 | SHT3X_WORD_LEN, |
398 | SHT3X_CRC8_INIT); |
399 | |
400 | mutex_lock(&data->i2c_lock); |
401 | ret = i2c_master_send(client, buf: buffer, count: sizeof(buffer)); |
402 | mutex_unlock(lock: &data->i2c_lock); |
403 | |
404 | if (ret != sizeof(buffer)) |
405 | return ret < 0 ? ret : -EIO; |
406 | |
407 | data->temperature_limits[index] = temperature; |
408 | data->humidity_limits[index] = humidity; |
409 | |
410 | return 0; |
411 | } |
412 | |
413 | static int temp1_limit_write(struct device *dev, int index, int val) |
414 | { |
415 | int temperature; |
416 | int ret; |
417 | struct sht3x_data *data = dev_get_drvdata(dev); |
418 | |
419 | temperature = clamp_val(val, SHT3X_MIN_TEMPERATURE, |
420 | SHT3X_MAX_TEMPERATURE); |
421 | mutex_lock(&data->data_lock); |
422 | ret = limit_write(dev, index, temperature, |
423 | humidity: data->humidity_limits[index]); |
424 | mutex_unlock(lock: &data->data_lock); |
425 | |
426 | return ret; |
427 | } |
428 | |
429 | static int humidity1_limit_write(struct device *dev, int index, int val) |
430 | { |
431 | u32 humidity; |
432 | int ret; |
433 | struct sht3x_data *data = dev_get_drvdata(dev); |
434 | |
435 | humidity = clamp_val(val, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY); |
436 | mutex_lock(&data->data_lock); |
437 | ret = limit_write(dev, index, temperature: data->temperature_limits[index], |
438 | humidity); |
439 | mutex_unlock(lock: &data->data_lock); |
440 | |
441 | return ret; |
442 | } |
443 | |
444 | static void sht3x_select_command(struct sht3x_data *data) |
445 | { |
446 | /* |
447 | * For single-shot mode, only non blocking mode is support, |
448 | * we have to wait ourselves for result. |
449 | */ |
450 | if (data->mode > 0) { |
451 | data->command = sht3x_cmd_measure_periodic_mode; |
452 | data->wait_time = 0; |
453 | } else { |
454 | if (data->repeatability == high_repeatability) { |
455 | data->command = sht3x_cmd_measure_single_hpm; |
456 | data->wait_time = SHT3X_SINGLE_WAIT_TIME_HPM; |
457 | } else if (data->repeatability == medium_repeatability) { |
458 | data->command = sht3x_cmd_measure_single_mpm; |
459 | data->wait_time = SHT3X_SINGLE_WAIT_TIME_MPM; |
460 | } else { |
461 | data->command = sht3x_cmd_measure_single_lpm; |
462 | data->wait_time = SHT3X_SINGLE_WAIT_TIME_LPM; |
463 | } |
464 | } |
465 | } |
466 | |
467 | static int status_register_read(struct device *dev, |
468 | char *buffer, int length) |
469 | { |
470 | int ret; |
471 | struct sht3x_data *data = dev_get_drvdata(dev); |
472 | struct i2c_client *client = data->client; |
473 | |
474 | ret = sht3x_read_from_command(client, data, command: sht3x_cmd_read_status_reg, |
475 | buf: buffer, length, wait_time: 0); |
476 | |
477 | return ret; |
478 | } |
479 | |
480 | static int temp1_alarm_read(struct device *dev) |
481 | { |
482 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; |
483 | int ret; |
484 | |
485 | ret = status_register_read(dev, buffer, |
486 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); |
487 | if (ret) |
488 | return ret; |
489 | |
490 | return !!(buffer[0] & 0x04); |
491 | } |
492 | |
493 | static int humidity1_alarm_read(struct device *dev) |
494 | { |
495 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; |
496 | int ret; |
497 | |
498 | ret = status_register_read(dev, buffer, |
499 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); |
500 | if (ret) |
501 | return ret; |
502 | |
503 | return !!(buffer[0] & 0x08); |
504 | } |
505 | |
506 | static ssize_t heater_enable_show(struct device *dev, |
507 | struct device_attribute *attr, |
508 | char *buf) |
509 | { |
510 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; |
511 | int ret; |
512 | |
513 | ret = status_register_read(dev, buffer, |
514 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); |
515 | if (ret) |
516 | return ret; |
517 | |
518 | return sysfs_emit(buf, fmt: "%d\n" , !!(buffer[0] & 0x20)); |
519 | } |
520 | |
521 | static ssize_t heater_enable_store(struct device *dev, |
522 | struct device_attribute *attr, |
523 | const char *buf, |
524 | size_t count) |
525 | { |
526 | struct sht3x_data *data = dev_get_drvdata(dev); |
527 | struct i2c_client *client = data->client; |
528 | int ret; |
529 | bool status; |
530 | |
531 | ret = kstrtobool(s: buf, res: &status); |
532 | if (ret) |
533 | return ret; |
534 | |
535 | mutex_lock(&data->i2c_lock); |
536 | |
537 | if (status) |
538 | ret = i2c_master_send(client, buf: (char *)&sht3x_cmd_heater_on, |
539 | SHT3X_CMD_LENGTH); |
540 | else |
541 | ret = i2c_master_send(client, buf: (char *)&sht3x_cmd_heater_off, |
542 | SHT3X_CMD_LENGTH); |
543 | |
544 | mutex_unlock(lock: &data->i2c_lock); |
545 | |
546 | return ret; |
547 | } |
548 | |
549 | static int update_interval_read(struct device *dev) |
550 | { |
551 | struct sht3x_data *data = dev_get_drvdata(dev); |
552 | |
553 | return mode_to_update_interval[data->mode]; |
554 | } |
555 | |
556 | static int update_interval_write(struct device *dev, int val) |
557 | { |
558 | u8 mode; |
559 | int ret; |
560 | const char *command; |
561 | struct sht3x_data *data = dev_get_drvdata(dev); |
562 | struct i2c_client *client = data->client; |
563 | |
564 | mode = get_mode_from_update_interval(value: val); |
565 | |
566 | mutex_lock(&data->data_lock); |
567 | /* mode did not change */ |
568 | if (mode == data->mode) { |
569 | mutex_unlock(lock: &data->data_lock); |
570 | return 0; |
571 | } |
572 | |
573 | mutex_lock(&data->i2c_lock); |
574 | /* |
575 | * Abort periodic measure mode. |
576 | * To do any changes to the configuration while in periodic mode, we |
577 | * have to send a break command to the sensor, which then falls back |
578 | * to single shot (mode = 0). |
579 | */ |
580 | if (data->mode > 0) { |
581 | ret = i2c_master_send(client, buf: sht3x_cmd_break, |
582 | SHT3X_CMD_LENGTH); |
583 | if (ret != SHT3X_CMD_LENGTH) |
584 | goto out; |
585 | data->mode = 0; |
586 | } |
587 | |
588 | if (mode > 0) { |
589 | if (data->repeatability == high_repeatability) |
590 | command = periodic_measure_commands_hpm[mode - 1]; |
591 | else if (data->repeatability == medium_repeatability) |
592 | command = periodic_measure_commands_mpm[mode - 1]; |
593 | else |
594 | command = periodic_measure_commands_lpm[mode - 1]; |
595 | |
596 | /* select mode */ |
597 | ret = i2c_master_send(client, buf: command, SHT3X_CMD_LENGTH); |
598 | if (ret != SHT3X_CMD_LENGTH) |
599 | goto out; |
600 | } |
601 | |
602 | /* select mode and command */ |
603 | data->mode = mode; |
604 | sht3x_select_command(data); |
605 | |
606 | out: |
607 | mutex_unlock(lock: &data->i2c_lock); |
608 | mutex_unlock(lock: &data->data_lock); |
609 | if (ret != SHT3X_CMD_LENGTH) |
610 | return ret < 0 ? ret : -EIO; |
611 | |
612 | return 0; |
613 | } |
614 | |
615 | static ssize_t repeatability_show(struct device *dev, |
616 | struct device_attribute *attr, |
617 | char *buf) |
618 | { |
619 | struct sht3x_data *data = dev_get_drvdata(dev); |
620 | |
621 | return sysfs_emit(buf, fmt: "%d\n" , data->repeatability); |
622 | } |
623 | |
624 | static ssize_t repeatability_store(struct device *dev, |
625 | struct device_attribute *attr, |
626 | const char *buf, |
627 | size_t count) |
628 | { |
629 | int ret; |
630 | u8 val; |
631 | |
632 | struct sht3x_data *data = dev_get_drvdata(dev); |
633 | |
634 | ret = kstrtou8(s: buf, base: 0, res: &val); |
635 | if (ret) |
636 | return ret; |
637 | |
638 | if (val > 2) |
639 | return -EINVAL; |
640 | |
641 | data->repeatability = val; |
642 | |
643 | return count; |
644 | } |
645 | |
646 | static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0); |
647 | static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0); |
648 | |
649 | static struct attribute *sht3x_attrs[] = { |
650 | &sensor_dev_attr_heater_enable.dev_attr.attr, |
651 | &sensor_dev_attr_repeatability.dev_attr.attr, |
652 | NULL |
653 | }; |
654 | |
655 | ATTRIBUTE_GROUPS(sht3x); |
656 | |
657 | static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type, |
658 | u32 attr, int channel) |
659 | { |
660 | const struct sht3x_data *chip_data = data; |
661 | |
662 | switch (type) { |
663 | case hwmon_chip: |
664 | switch (attr) { |
665 | case hwmon_chip_update_interval: |
666 | return 0644; |
667 | default: |
668 | break; |
669 | } |
670 | break; |
671 | case hwmon_temp: |
672 | switch (attr) { |
673 | case hwmon_temp_input: |
674 | case hwmon_temp_alarm: |
675 | return 0444; |
676 | case hwmon_temp_max: |
677 | case hwmon_temp_max_hyst: |
678 | case hwmon_temp_min: |
679 | case hwmon_temp_min_hyst: |
680 | return 0644; |
681 | default: |
682 | break; |
683 | } |
684 | break; |
685 | case hwmon_humidity: |
686 | if (chip_data->chip_id == sts3x) |
687 | break; |
688 | switch (attr) { |
689 | case hwmon_humidity_input: |
690 | case hwmon_humidity_alarm: |
691 | return 0444; |
692 | case hwmon_humidity_max: |
693 | case hwmon_humidity_max_hyst: |
694 | case hwmon_humidity_min: |
695 | case hwmon_humidity_min_hyst: |
696 | return 0644; |
697 | default: |
698 | break; |
699 | } |
700 | break; |
701 | default: |
702 | break; |
703 | } |
704 | |
705 | return 0; |
706 | } |
707 | |
708 | static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, |
709 | u32 attr, int channel, long *val) |
710 | { |
711 | enum sht3x_limits index; |
712 | |
713 | switch (type) { |
714 | case hwmon_chip: |
715 | switch (attr) { |
716 | case hwmon_chip_update_interval: |
717 | *val = update_interval_read(dev); |
718 | break; |
719 | default: |
720 | return -EOPNOTSUPP; |
721 | } |
722 | break; |
723 | case hwmon_temp: |
724 | switch (attr) { |
725 | case hwmon_temp_input: |
726 | *val = temp1_input_read(dev); |
727 | break; |
728 | case hwmon_temp_alarm: |
729 | *val = temp1_alarm_read(dev); |
730 | break; |
731 | case hwmon_temp_max: |
732 | index = limit_max; |
733 | *val = temp1_limit_read(dev, index); |
734 | break; |
735 | case hwmon_temp_max_hyst: |
736 | index = limit_max_hyst; |
737 | *val = temp1_limit_read(dev, index); |
738 | break; |
739 | case hwmon_temp_min: |
740 | index = limit_min; |
741 | *val = temp1_limit_read(dev, index); |
742 | break; |
743 | case hwmon_temp_min_hyst: |
744 | index = limit_min_hyst; |
745 | *val = temp1_limit_read(dev, index); |
746 | break; |
747 | default: |
748 | return -EOPNOTSUPP; |
749 | } |
750 | break; |
751 | case hwmon_humidity: |
752 | switch (attr) { |
753 | case hwmon_humidity_input: |
754 | *val = humidity1_input_read(dev); |
755 | break; |
756 | case hwmon_humidity_alarm: |
757 | *val = humidity1_alarm_read(dev); |
758 | break; |
759 | case hwmon_humidity_max: |
760 | index = limit_max; |
761 | *val = humidity1_limit_read(dev, index); |
762 | break; |
763 | case hwmon_humidity_max_hyst: |
764 | index = limit_max_hyst; |
765 | *val = humidity1_limit_read(dev, index); |
766 | break; |
767 | case hwmon_humidity_min: |
768 | index = limit_min; |
769 | *val = humidity1_limit_read(dev, index); |
770 | break; |
771 | case hwmon_humidity_min_hyst: |
772 | index = limit_min_hyst; |
773 | *val = humidity1_limit_read(dev, index); |
774 | break; |
775 | default: |
776 | return -EOPNOTSUPP; |
777 | } |
778 | break; |
779 | default: |
780 | return -EOPNOTSUPP; |
781 | } |
782 | |
783 | return 0; |
784 | } |
785 | |
786 | static int sht3x_write(struct device *dev, enum hwmon_sensor_types type, |
787 | u32 attr, int channel, long val) |
788 | { |
789 | enum sht3x_limits index; |
790 | |
791 | switch (type) { |
792 | case hwmon_chip: |
793 | switch (attr) { |
794 | case hwmon_chip_update_interval: |
795 | return update_interval_write(dev, val); |
796 | default: |
797 | return -EOPNOTSUPP; |
798 | } |
799 | case hwmon_temp: |
800 | switch (attr) { |
801 | case hwmon_temp_max: |
802 | index = limit_max; |
803 | break; |
804 | case hwmon_temp_max_hyst: |
805 | index = limit_max_hyst; |
806 | break; |
807 | case hwmon_temp_min: |
808 | index = limit_min; |
809 | break; |
810 | case hwmon_temp_min_hyst: |
811 | index = limit_min_hyst; |
812 | break; |
813 | default: |
814 | return -EOPNOTSUPP; |
815 | } |
816 | return temp1_limit_write(dev, index, val); |
817 | case hwmon_humidity: |
818 | switch (attr) { |
819 | case hwmon_humidity_max: |
820 | index = limit_max; |
821 | break; |
822 | case hwmon_humidity_max_hyst: |
823 | index = limit_max_hyst; |
824 | break; |
825 | case hwmon_humidity_min: |
826 | index = limit_min; |
827 | break; |
828 | case hwmon_humidity_min_hyst: |
829 | index = limit_min_hyst; |
830 | break; |
831 | default: |
832 | return -EOPNOTSUPP; |
833 | } |
834 | return humidity1_limit_write(dev, index, val); |
835 | default: |
836 | return -EOPNOTSUPP; |
837 | } |
838 | } |
839 | |
840 | static void sht3x_debugfs_init(struct sht3x_data *data) |
841 | { |
842 | char name[32]; |
843 | |
844 | snprintf(buf: name, size: sizeof(name), fmt: "i2c%u-%02x" , |
845 | data->client->adapter->nr, data->client->addr); |
846 | data->sensor_dir = debugfs_create_dir(name, parent: debugfs); |
847 | debugfs_create_u32(name: "serial_number" , mode: 0444, |
848 | parent: data->sensor_dir, value: &data->serial_number); |
849 | } |
850 | |
851 | static void sht3x_debugfs_remove(void *sensor_dir) |
852 | { |
853 | debugfs_remove_recursive(dentry: sensor_dir); |
854 | } |
855 | |
856 | static int sht3x_serial_number_read(struct sht3x_data *data) |
857 | { |
858 | int ret; |
859 | char buffer[SHT3X_RESPONSE_LENGTH]; |
860 | struct i2c_client *client = data->client; |
861 | |
862 | ret = sht3x_read_from_command(client, data, |
863 | command: sht3x_cmd_read_serial_number, |
864 | buf: buffer, |
865 | SHT3X_RESPONSE_LENGTH, wait_time: 0); |
866 | if (ret) |
867 | return ret; |
868 | |
869 | data->serial_number = (buffer[0] << 24) | (buffer[1] << 16) | |
870 | (buffer[3] << 8) | buffer[4]; |
871 | return ret; |
872 | } |
873 | |
874 | static const struct hwmon_ops sht3x_ops = { |
875 | .is_visible = sht3x_is_visible, |
876 | .read = sht3x_read, |
877 | .write = sht3x_write, |
878 | }; |
879 | |
880 | static const struct hwmon_chip_info sht3x_chip_info = { |
881 | .ops = &sht3x_ops, |
882 | .info = sht3x_channel_info, |
883 | }; |
884 | |
885 | /* device ID table */ |
886 | static const struct i2c_device_id sht3x_ids[] = { |
887 | {"sht3x" , sht3x}, |
888 | {"sts3x" , sts3x}, |
889 | {} |
890 | }; |
891 | |
892 | MODULE_DEVICE_TABLE(i2c, sht3x_ids); |
893 | |
894 | static int sht3x_probe(struct i2c_client *client) |
895 | { |
896 | int ret; |
897 | struct sht3x_data *data; |
898 | struct device *hwmon_dev; |
899 | struct i2c_adapter *adap = client->adapter; |
900 | struct device *dev = &client->dev; |
901 | |
902 | /* |
903 | * we require full i2c support since the sht3x uses multi-byte read and |
904 | * writes as well as multi-byte commands which are not supported by |
905 | * the smbus protocol |
906 | */ |
907 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) |
908 | return -ENODEV; |
909 | |
910 | ret = i2c_master_send(client, buf: sht3x_cmd_clear_status_reg, |
911 | SHT3X_CMD_LENGTH); |
912 | if (ret != SHT3X_CMD_LENGTH) |
913 | return ret < 0 ? ret : -ENODEV; |
914 | |
915 | data = devm_kzalloc(dev, size: sizeof(*data), GFP_KERNEL); |
916 | if (!data) |
917 | return -ENOMEM; |
918 | |
919 | data->repeatability = high_repeatability; |
920 | data->mode = 0; |
921 | data->last_update = jiffies - msecs_to_jiffies(m: 3000); |
922 | data->client = client; |
923 | data->chip_id = i2c_match_id(id: sht3x_ids, client)->driver_data; |
924 | crc8_populate_msb(table: sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL); |
925 | |
926 | sht3x_select_command(data); |
927 | |
928 | mutex_init(&data->i2c_lock); |
929 | mutex_init(&data->data_lock); |
930 | |
931 | /* |
932 | * An attempt to read limits register too early |
933 | * causes a NACK response from the chip. |
934 | * Waiting for an empirical delay of 500 us solves the issue. |
935 | */ |
936 | usleep_range(min: 500, max: 600); |
937 | |
938 | ret = limits_update(data); |
939 | if (ret) |
940 | return ret; |
941 | |
942 | ret = sht3x_serial_number_read(data); |
943 | if (ret) { |
944 | dev_dbg(dev, "unable to read serial number\n" ); |
945 | } else { |
946 | sht3x_debugfs_init(data); |
947 | ret = devm_add_action_or_reset(dev, |
948 | sht3x_debugfs_remove, |
949 | data->sensor_dir); |
950 | if (ret) |
951 | return ret; |
952 | } |
953 | |
954 | hwmon_dev = devm_hwmon_device_register_with_info(dev, |
955 | name: client->name, |
956 | drvdata: data, |
957 | info: &sht3x_chip_info, |
958 | extra_groups: sht3x_groups); |
959 | |
960 | if (IS_ERR(ptr: hwmon_dev)) |
961 | dev_dbg(dev, "unable to register hwmon device\n" ); |
962 | |
963 | return PTR_ERR_OR_ZERO(ptr: hwmon_dev); |
964 | } |
965 | |
966 | static struct i2c_driver sht3x_i2c_driver = { |
967 | .driver.name = "sht3x" , |
968 | .probe = sht3x_probe, |
969 | .id_table = sht3x_ids, |
970 | }; |
971 | |
972 | static int __init sht3x_init(void) |
973 | { |
974 | debugfs = debugfs_create_dir(name: "sht3x" , NULL); |
975 | return i2c_add_driver(&sht3x_i2c_driver); |
976 | } |
977 | module_init(sht3x_init); |
978 | |
979 | static void __exit sht3x_cleanup(void) |
980 | { |
981 | debugfs_remove_recursive(dentry: debugfs); |
982 | i2c_del_driver(driver: &sht3x_i2c_driver); |
983 | } |
984 | module_exit(sht3x_cleanup); |
985 | |
986 | MODULE_AUTHOR("David Frey <david.frey@sensirion.com>" ); |
987 | MODULE_AUTHOR("Pascal Sachs <pascal.sachs@sensirion.com>" ); |
988 | MODULE_DESCRIPTION("Sensirion SHT3x humidity and temperature sensor driver" ); |
989 | MODULE_LICENSE("GPL" ); |
990 | |