1 // SPDX-License-Identifier: GPL-2.0+
3 * hdc3020.c - Support for the TI HDC3020,HDC3021 and HDC3022
4 * temperature + relative humidity sensors
8 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH
10 * Datasheet: https://www.ti.com/lit/ds/symlink/hdc3020.pdf
13 #include <linux/bitfield.h>
14 #include <linux/bitops.h>
15 #include <linux/cleanup.h>
16 #include <linux/crc8.h>
17 #include <linux/delay.h>
18 #include <linux/i2c.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/module.h>
22 #include <linux/mutex.h>
23 #include <linux/units.h>
25 #include <asm/unaligned.h>
27 #include <linux/iio/events.h>
28 #include <linux/iio/iio.h>
30 #define HDC3020_S_AUTO_10HZ_MOD0 0x2737
31 #define HDC3020_S_STATUS 0x3041
32 #define HDC3020_HEATER_DISABLE 0x3066
33 #define HDC3020_HEATER_ENABLE 0x306D
34 #define HDC3020_HEATER_CONFIG 0x306E
35 #define HDC3020_EXIT_AUTO 0x3093
36 #define HDC3020_S_T_RH_THRESH_LOW 0x6100
37 #define HDC3020_S_T_RH_THRESH_LOW_CLR 0x610B
38 #define HDC3020_S_T_RH_THRESH_HIGH_CLR 0x6116
39 #define HDC3020_S_T_RH_THRESH_HIGH 0x611D
40 #define HDC3020_R_T_RH_AUTO 0xE000
41 #define HDC3020_R_T_LOW_AUTO 0xE002
42 #define HDC3020_R_T_HIGH_AUTO 0xE003
43 #define HDC3020_R_RH_LOW_AUTO 0xE004
44 #define HDC3020_R_RH_HIGH_AUTO 0xE005
45 #define HDC3020_R_T_RH_THRESH_LOW 0xE102
46 #define HDC3020_R_T_RH_THRESH_LOW_CLR 0xE109
47 #define HDC3020_R_T_RH_THRESH_HIGH_CLR 0xE114
48 #define HDC3020_R_T_RH_THRESH_HIGH 0xE11F
49 #define HDC3020_R_STATUS 0xF32D
51 #define HDC3020_THRESH_TEMP_MASK GENMASK(8, 0)
52 #define HDC3020_THRESH_TEMP_TRUNC_SHIFT 7
53 #define HDC3020_THRESH_HUM_MASK GENMASK(15, 9)
54 #define HDC3020_THRESH_HUM_TRUNC_SHIFT 9
56 #define HDC3020_STATUS_T_LOW_ALERT BIT(6)
57 #define HDC3020_STATUS_T_HIGH_ALERT BIT(7)
58 #define HDC3020_STATUS_RH_LOW_ALERT BIT(8)
59 #define HDC3020_STATUS_RH_HIGH_ALERT BIT(9)
61 #define HDC3020_READ_RETRY_TIMES 10
62 #define HDC3020_BUSY_DELAY_MS 10
64 #define HDC3020_CRC8_POLYNOMIAL 0x31
66 #define HDC3020_MIN_TEMP -40
67 #define HDC3020_MAX_TEMP 125
70 struct i2c_client *client;
72 * Ensure that the sensor configuration (currently only heater is
73 * supported) will not be changed during the process of reading
74 * sensor data (this driver will try HDC3020_READ_RETRY_TIMES times
75 * if the device does not respond).
80 static const int hdc3020_heater_vals[] = {0, 1, 0x3FFF};
82 static const struct iio_event_spec hdc3020_t_rh_event[] = {
84 .type = IIO_EV_TYPE_THRESH,
85 .dir = IIO_EV_DIR_RISING,
86 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
87 BIT(IIO_EV_INFO_HYSTERESIS),
90 .type = IIO_EV_TYPE_THRESH,
91 .dir = IIO_EV_DIR_FALLING,
92 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
93 BIT(IIO_EV_INFO_HYSTERESIS),
97 static const struct iio_chan_spec hdc3020_channels[] = {
100 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
101 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
102 BIT(IIO_CHAN_INFO_TROUGH) | BIT(IIO_CHAN_INFO_OFFSET),
103 .event_spec = hdc3020_t_rh_event,
104 .num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
107 .type = IIO_HUMIDITYRELATIVE,
108 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
109 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
110 BIT(IIO_CHAN_INFO_TROUGH),
111 .event_spec = hdc3020_t_rh_event,
112 .num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
116 * For setting the internal heater, which can be switched on to
117 * prevent or remove any condensation that may develop when the
118 * ambient environment approaches its dew point temperature.
121 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
122 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
127 DECLARE_CRC8_TABLE(hdc3020_crc8_table);
129 static int hdc3020_write_bytes(struct hdc3020_data *data, u8 *buf, u8 len)
131 struct i2c_client *client = data->client;
135 msg.addr = client->addr;
141 * During the measurement process, HDC3020 will not return data.
142 * So wait for a while and try again
144 for (cnt = 0; cnt < HDC3020_READ_RETRY_TIMES; cnt++) {
145 ret = i2c_transfer(client->adapter, &msg, 1);
149 mdelay(HDC3020_BUSY_DELAY_MS);
151 dev_err(&client->dev, "Could not write sensor command\n");
157 int hdc3020_read_bytes(struct hdc3020_data *data, u16 reg, u8 *buf, int len)
161 struct i2c_client *client = data->client;
162 struct i2c_msg msg[2] = {
164 .addr = client->addr,
170 .addr = client->addr,
177 put_unaligned_be16(reg, reg_buf);
179 * During the measurement process, HDC3020 will not return data.
180 * So wait for a while and try again
182 for (cnt = 0; cnt < HDC3020_READ_RETRY_TIMES; cnt++) {
183 ret = i2c_transfer(client->adapter, msg, 2);
187 mdelay(HDC3020_BUSY_DELAY_MS);
189 dev_err(&client->dev, "Could not read sensor data\n");
194 static int hdc3020_read_be16(struct hdc3020_data *data, u16 reg)
199 ret = hdc3020_read_bytes(data, reg, buf, 3);
203 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
207 return get_unaligned_be16(buf);
210 static int hdc3020_exec_cmd(struct hdc3020_data *data, u16 reg)
214 put_unaligned_be16(reg, reg_buf);
215 return hdc3020_write_bytes(data, reg_buf, 2);
218 static int hdc3020_read_measurement(struct hdc3020_data *data,
219 enum iio_chan_type type, int *val)
224 ret = hdc3020_read_bytes(data, HDC3020_R_T_RH_AUTO, buf, 6);
228 /* CRC check of the temperature measurement */
229 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
233 /* CRC check of the relative humidity measurement */
234 crc = crc8(hdc3020_crc8_table, buf + 3, 2, CRC8_INIT_VALUE);
238 if (type == IIO_TEMP)
239 *val = get_unaligned_be16(buf);
240 else if (type == IIO_HUMIDITYRELATIVE)
241 *val = get_unaligned_be16(&buf[3]);
248 static int hdc3020_read_raw(struct iio_dev *indio_dev,
249 struct iio_chan_spec const *chan, int *val,
250 int *val2, long mask)
252 struct hdc3020_data *data = iio_priv(indio_dev);
255 if (chan->type != IIO_TEMP && chan->type != IIO_HUMIDITYRELATIVE)
259 case IIO_CHAN_INFO_RAW: {
260 guard(mutex)(&data->lock);
261 ret = hdc3020_read_measurement(data, chan->type, val);
267 case IIO_CHAN_INFO_PEAK: {
268 guard(mutex)(&data->lock);
269 if (chan->type == IIO_TEMP)
270 ret = hdc3020_read_be16(data, HDC3020_R_T_HIGH_AUTO);
272 ret = hdc3020_read_be16(data, HDC3020_R_RH_HIGH_AUTO);
280 case IIO_CHAN_INFO_TROUGH: {
281 guard(mutex)(&data->lock);
282 if (chan->type == IIO_TEMP)
283 ret = hdc3020_read_be16(data, HDC3020_R_T_LOW_AUTO);
285 ret = hdc3020_read_be16(data, HDC3020_R_RH_LOW_AUTO);
293 case IIO_CHAN_INFO_SCALE:
295 if (chan->type == IIO_TEMP)
299 return IIO_VAL_FRACTIONAL;
301 case IIO_CHAN_INFO_OFFSET:
302 if (chan->type != IIO_TEMP)
313 static int hdc3020_read_available(struct iio_dev *indio_dev,
314 struct iio_chan_spec const *chan,
316 int *type, int *length, long mask)
318 if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_CURRENT)
321 *vals = hdc3020_heater_vals;
324 return IIO_AVAIL_RANGE;
327 static int hdc3020_update_heater(struct hdc3020_data *data, int val)
332 if (val < hdc3020_heater_vals[0] || val > hdc3020_heater_vals[2])
336 hdc3020_exec_cmd(data, HDC3020_HEATER_DISABLE);
338 put_unaligned_be16(HDC3020_HEATER_CONFIG, buf);
339 put_unaligned_be16(val & GENMASK(13, 0), &buf[2]);
340 buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
341 ret = hdc3020_write_bytes(data, buf, 5);
345 return hdc3020_exec_cmd(data, HDC3020_HEATER_ENABLE);
348 static int hdc3020_write_raw(struct iio_dev *indio_dev,
349 struct iio_chan_spec const *chan,
350 int val, int val2, long mask)
352 struct hdc3020_data *data = iio_priv(indio_dev);
355 case IIO_CHAN_INFO_RAW:
356 if (chan->type != IIO_CURRENT)
359 guard(mutex)(&data->lock);
360 return hdc3020_update_heater(data, val);
366 static int hdc3020_write_thresh(struct iio_dev *indio_dev,
367 const struct iio_chan_spec *chan,
368 enum iio_event_type type,
369 enum iio_event_direction dir,
370 enum iio_event_info info,
373 struct hdc3020_data *data = iio_priv(indio_dev);
379 /* Supported temperature range is from –40 to 125 degree celsius */
380 if (val < HDC3020_MIN_TEMP || val > HDC3020_MAX_TEMP)
383 /* Select threshold register */
384 if (info == IIO_EV_INFO_VALUE) {
385 if (dir == IIO_EV_DIR_RISING)
386 reg = HDC3020_S_T_RH_THRESH_HIGH;
388 reg = HDC3020_S_T_RH_THRESH_LOW;
390 if (dir == IIO_EV_DIR_RISING)
391 reg = HDC3020_S_T_RH_THRESH_HIGH_CLR;
393 reg = HDC3020_S_T_RH_THRESH_LOW_CLR;
396 guard(mutex)(&data->lock);
397 ret = hdc3020_read_be16(data, reg);
401 switch (chan->type) {
404 * Calculate temperature threshold, shift it down to get the
405 * truncated threshold representation in the 9LSBs while keeping
406 * the current humidity threshold in the 7 MSBs.
408 tmp = ((u64)(((val + 45) * MICRO) + val2)) * 65535ULL;
409 tmp = div_u64(tmp, MICRO * 175);
410 val = tmp >> HDC3020_THRESH_TEMP_TRUNC_SHIFT;
411 val = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, val);
412 val |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, ret) <<
413 HDC3020_THRESH_HUM_TRUNC_SHIFT);
415 case IIO_HUMIDITYRELATIVE:
417 * Calculate humidity threshold, shift it down and up to get the
418 * truncated threshold representation in the 7MSBs while keeping
419 * the current temperature threshold in the 9 LSBs.
421 tmp = ((u64)((val * MICRO) + val2)) * 65535ULL;
422 tmp = div_u64(tmp, MICRO * 100);
423 val = tmp >> HDC3020_THRESH_HUM_TRUNC_SHIFT;
424 val = FIELD_PREP(HDC3020_THRESH_HUM_MASK, val);
425 val |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
431 put_unaligned_be16(reg, buf);
432 put_unaligned_be16(val, buf + 2);
433 buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
434 return hdc3020_write_bytes(data, buf, 5);
437 static int hdc3020_read_thresh(struct iio_dev *indio_dev,
438 const struct iio_chan_spec *chan,
439 enum iio_event_type type,
440 enum iio_event_direction dir,
441 enum iio_event_info info,
444 struct hdc3020_data *data = iio_priv(indio_dev);
448 /* Select threshold register */
449 if (info == IIO_EV_INFO_VALUE) {
450 if (dir == IIO_EV_DIR_RISING)
451 reg = HDC3020_R_T_RH_THRESH_HIGH;
453 reg = HDC3020_R_T_RH_THRESH_LOW;
455 if (dir == IIO_EV_DIR_RISING)
456 reg = HDC3020_R_T_RH_THRESH_HIGH_CLR;
458 reg = HDC3020_R_T_RH_THRESH_LOW_CLR;
461 guard(mutex)(&data->lock);
462 ret = hdc3020_read_be16(data, reg);
466 switch (chan->type) {
469 * Get the temperature threshold from 9 LSBs, shift them to get
470 * the truncated temperature threshold representation and
471 * calculate the threshold according to the formula in the
474 *val = FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
475 *val = *val << HDC3020_THRESH_TEMP_TRUNC_SHIFT;
476 *val = -2949075 + (175 * (*val));
478 return IIO_VAL_FRACTIONAL;
479 case IIO_HUMIDITYRELATIVE:
481 * Get the humidity threshold from 7 MSBs, shift them to get the
482 * truncated humidity threshold representation and calculate the
483 * threshold according to the formula in the datasheet.
485 *val = FIELD_GET(HDC3020_THRESH_HUM_MASK, ret);
486 *val = (*val << HDC3020_THRESH_HUM_TRUNC_SHIFT) * 100;
488 return IIO_VAL_FRACTIONAL;
494 static irqreturn_t hdc3020_interrupt_handler(int irq, void *private)
496 struct iio_dev *indio_dev = private;
497 struct hdc3020_data *data;
501 data = iio_priv(indio_dev);
502 ret = hdc3020_read_be16(data, HDC3020_R_STATUS);
506 if (!(ret & (HDC3020_STATUS_T_HIGH_ALERT | HDC3020_STATUS_T_LOW_ALERT |
507 HDC3020_STATUS_RH_HIGH_ALERT | HDC3020_STATUS_RH_LOW_ALERT)))
510 time = iio_get_time_ns(indio_dev);
511 if (ret & HDC3020_STATUS_T_HIGH_ALERT)
512 iio_push_event(indio_dev,
513 IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
519 if (ret & HDC3020_STATUS_T_LOW_ALERT)
520 iio_push_event(indio_dev,
521 IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
527 if (ret & HDC3020_STATUS_RH_HIGH_ALERT)
528 iio_push_event(indio_dev,
529 IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
535 if (ret & HDC3020_STATUS_RH_LOW_ALERT)
536 iio_push_event(indio_dev,
537 IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
546 static const struct iio_info hdc3020_info = {
547 .read_raw = hdc3020_read_raw,
548 .write_raw = hdc3020_write_raw,
549 .read_avail = hdc3020_read_available,
550 .read_event_value = hdc3020_read_thresh,
551 .write_event_value = hdc3020_write_thresh,
554 static void hdc3020_stop(void *data)
556 hdc3020_exec_cmd((struct hdc3020_data *)data, HDC3020_EXIT_AUTO);
559 static int hdc3020_probe(struct i2c_client *client)
561 struct iio_dev *indio_dev;
562 struct hdc3020_data *data;
565 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
568 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
572 data = iio_priv(indio_dev);
573 data->client = client;
574 mutex_init(&data->lock);
576 crc8_populate_msb(hdc3020_crc8_table, HDC3020_CRC8_POLYNOMIAL);
578 indio_dev->name = "hdc3020";
579 indio_dev->modes = INDIO_DIRECT_MODE;
580 indio_dev->info = &hdc3020_info;
581 indio_dev->channels = hdc3020_channels;
582 indio_dev->num_channels = ARRAY_SIZE(hdc3020_channels);
584 ret = devm_request_threaded_irq(&client->dev, client->irq,
585 NULL, hdc3020_interrupt_handler,
586 IRQF_ONESHOT, "hdc3020",
589 return dev_err_probe(&client->dev, ret,
590 "Failed to request IRQ\n");
593 * The alert output is activated by default upon power up,
594 * hardware reset, and soft reset. Clear the status register.
596 ret = hdc3020_exec_cmd(data, HDC3020_S_STATUS);
601 ret = hdc3020_exec_cmd(data, HDC3020_S_AUTO_10HZ_MOD0);
603 return dev_err_probe(&client->dev, ret,
604 "Unable to set up measurement\n");
606 ret = devm_add_action_or_reset(&data->client->dev, hdc3020_stop, data);
610 ret = devm_iio_device_register(&data->client->dev, indio_dev);
612 return dev_err_probe(&client->dev, ret, "Failed to add device");
617 static const struct i2c_device_id hdc3020_id[] = {
623 MODULE_DEVICE_TABLE(i2c, hdc3020_id);
625 static const struct of_device_id hdc3020_dt_ids[] = {
626 { .compatible = "ti,hdc3020" },
627 { .compatible = "ti,hdc3021" },
628 { .compatible = "ti,hdc3022" },
631 MODULE_DEVICE_TABLE(of, hdc3020_dt_ids);
633 static struct i2c_driver hdc3020_driver = {
636 .of_match_table = hdc3020_dt_ids,
638 .probe = hdc3020_probe,
639 .id_table = hdc3020_id,
641 module_i2c_driver(hdc3020_driver);
643 MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>");
644 MODULE_AUTHOR("Li peiyu <579lpy@gmail.com>");
645 MODULE_DESCRIPTION("TI HDC3020 humidity and temperature sensor driver");
646 MODULE_LICENSE("GPL");