2 * STMicroelectronics hts221 sensor driver
4 * Copyright 2016 STMicroelectronics Inc.
6 * Lorenzo Bianconi <lorenzo.bianconi@st.com>
8 * Licensed under the GPL-2.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/iio/sysfs.h>
15 #include <linux/delay.h>
17 #include <linux/regmap.h>
18 #include <linux/bitfield.h>
22 #define HTS221_REG_WHOAMI_ADDR 0x0f
23 #define HTS221_REG_WHOAMI_VAL 0xbc
25 #define HTS221_REG_CNTRL1_ADDR 0x20
26 #define HTS221_REG_CNTRL2_ADDR 0x21
28 #define HTS221_REG_AVG_ADDR 0x10
29 #define HTS221_REG_H_OUT_L 0x28
30 #define HTS221_REG_T_OUT_L 0x2a
32 #define HTS221_HUMIDITY_AVG_MASK 0x07
33 #define HTS221_TEMP_AVG_MASK 0x38
35 #define HTS221_ODR_MASK 0x03
36 #define HTS221_BDU_MASK BIT(2)
37 #define HTS221_ENABLE_MASK BIT(7)
39 /* calibration registers */
40 #define HTS221_REG_0RH_CAL_X_H 0x36
41 #define HTS221_REG_1RH_CAL_X_H 0x3a
42 #define HTS221_REG_0RH_CAL_Y_H 0x30
43 #define HTS221_REG_1RH_CAL_Y_H 0x31
44 #define HTS221_REG_0T_CAL_X_L 0x3c
45 #define HTS221_REG_1T_CAL_X_L 0x3e
46 #define HTS221_REG_0T_CAL_Y_H 0x32
47 #define HTS221_REG_1T_CAL_Y_H 0x33
48 #define HTS221_REG_T1_T0_CAL_Y_H 0x35
55 #define HTS221_AVG_DEPTH 8
59 u16 avg_avl
[HTS221_AVG_DEPTH
];
62 static const struct hts221_odr hts221_odr_table
[] = {
63 { 1, 0x01 }, /* 1Hz */
64 { 7, 0x02 }, /* 7Hz */
65 { 13, 0x03 }, /* 12.5Hz */
68 static const struct hts221_avg hts221_avg_list
[] = {
70 .addr
= HTS221_REG_AVG_ADDR
,
71 .mask
= HTS221_HUMIDITY_AVG_MASK
,
84 .addr
= HTS221_REG_AVG_ADDR
,
85 .mask
= HTS221_TEMP_AVG_MASK
,
99 static const struct iio_chan_spec hts221_channels
[] = {
101 .type
= IIO_HUMIDITYRELATIVE
,
102 .address
= HTS221_REG_H_OUT_L
,
103 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) |
104 BIT(IIO_CHAN_INFO_OFFSET
) |
105 BIT(IIO_CHAN_INFO_SCALE
) |
106 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO
),
107 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_SAMP_FREQ
),
113 .endianness
= IIO_LE
,
118 .address
= HTS221_REG_T_OUT_L
,
119 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) |
120 BIT(IIO_CHAN_INFO_OFFSET
) |
121 BIT(IIO_CHAN_INFO_SCALE
) |
122 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO
),
123 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_SAMP_FREQ
),
129 .endianness
= IIO_LE
,
132 IIO_CHAN_SOFT_TIMESTAMP(2),
135 static int hts221_check_whoami(struct hts221_hw
*hw
)
139 err
= regmap_read(hw
->regmap
, HTS221_REG_WHOAMI_ADDR
, &data
);
141 dev_err(hw
->dev
, "failed to read whoami register\n");
145 if (data
!= HTS221_REG_WHOAMI_VAL
) {
146 dev_err(hw
->dev
, "wrong whoami {%02x vs %02x}\n",
147 data
, HTS221_REG_WHOAMI_VAL
);
154 static int hts221_update_odr(struct hts221_hw
*hw
, u8 odr
)
158 for (i
= 0; i
< ARRAY_SIZE(hts221_odr_table
); i
++)
159 if (hts221_odr_table
[i
].hz
== odr
)
162 if (i
== ARRAY_SIZE(hts221_odr_table
))
165 err
= regmap_update_bits(hw
->regmap
, HTS221_REG_CNTRL1_ADDR
,
167 FIELD_PREP(HTS221_ODR_MASK
,
168 hts221_odr_table
[i
].val
));
177 static int hts221_update_avg(struct hts221_hw
*hw
,
178 enum hts221_sensor_type type
,
181 const struct hts221_avg
*avg
= &hts221_avg_list
[type
];
184 for (i
= 0; i
< HTS221_AVG_DEPTH
; i
++)
185 if (avg
->avg_avl
[i
] == val
)
188 if (i
== HTS221_AVG_DEPTH
)
191 data
= ((i
<< __ffs(avg
->mask
)) & avg
->mask
);
192 err
= regmap_update_bits(hw
->regmap
, avg
->addr
,
197 hw
->sensors
[type
].cur_avg_idx
= i
;
202 static ssize_t
hts221_sysfs_sampling_freq(struct device
*dev
,
203 struct device_attribute
*attr
,
209 for (i
= 0; i
< ARRAY_SIZE(hts221_odr_table
); i
++)
210 len
+= scnprintf(buf
+ len
, PAGE_SIZE
- len
, "%d ",
211 hts221_odr_table
[i
].hz
);
218 hts221_sysfs_rh_oversampling_avail(struct device
*dev
,
219 struct device_attribute
*attr
,
222 const struct hts221_avg
*avg
= &hts221_avg_list
[HTS221_SENSOR_H
];
226 for (i
= 0; i
< ARRAY_SIZE(avg
->avg_avl
); i
++)
227 len
+= scnprintf(buf
+ len
, PAGE_SIZE
- len
, "%d ",
235 hts221_sysfs_temp_oversampling_avail(struct device
*dev
,
236 struct device_attribute
*attr
,
239 const struct hts221_avg
*avg
= &hts221_avg_list
[HTS221_SENSOR_T
];
243 for (i
= 0; i
< ARRAY_SIZE(avg
->avg_avl
); i
++)
244 len
+= scnprintf(buf
+ len
, PAGE_SIZE
- len
, "%d ",
251 int hts221_set_enable(struct hts221_hw
*hw
, bool enable
)
255 err
= regmap_update_bits(hw
->regmap
, HTS221_REG_CNTRL1_ADDR
,
257 FIELD_PREP(HTS221_ENABLE_MASK
, enable
));
261 hw
->enabled
= enable
;
266 static int hts221_parse_temp_caldata(struct hts221_hw
*hw
)
268 int err
, *slope
, *b_gen
, cal0
, cal1
;
269 s16 cal_x0
, cal_x1
, cal_y0
, cal_y1
;
272 err
= regmap_read(hw
->regmap
, HTS221_REG_0T_CAL_Y_H
, &cal0
);
276 err
= regmap_read(hw
->regmap
, HTS221_REG_T1_T0_CAL_Y_H
, &cal1
);
279 cal_y0
= ((cal1
& 0x3) << 8) | cal0
;
281 err
= regmap_read(hw
->regmap
, HTS221_REG_1T_CAL_Y_H
, &cal0
);
284 cal_y1
= (((cal1
& 0xc) >> 2) << 8) | cal0
;
286 err
= regmap_bulk_read(hw
->regmap
, HTS221_REG_0T_CAL_X_L
,
290 cal_x0
= le16_to_cpu(val
);
292 err
= regmap_bulk_read(hw
->regmap
, HTS221_REG_1T_CAL_X_L
,
296 cal_x1
= le16_to_cpu(val
);
298 slope
= &hw
->sensors
[HTS221_SENSOR_T
].slope
;
299 b_gen
= &hw
->sensors
[HTS221_SENSOR_T
].b_gen
;
301 *slope
= ((cal_y1
- cal_y0
) * 8000) / (cal_x1
- cal_x0
);
302 *b_gen
= (((s32
)cal_x1
* cal_y0
- (s32
)cal_x0
* cal_y1
) * 1000) /
309 static int hts221_parse_rh_caldata(struct hts221_hw
*hw
)
311 int err
, *slope
, *b_gen
, data
;
312 s16 cal_x0
, cal_x1
, cal_y0
, cal_y1
;
315 err
= regmap_read(hw
->regmap
, HTS221_REG_0RH_CAL_Y_H
, &data
);
320 err
= regmap_read(hw
->regmap
, HTS221_REG_1RH_CAL_Y_H
, &data
);
325 err
= regmap_bulk_read(hw
->regmap
, HTS221_REG_0RH_CAL_X_H
,
329 cal_x0
= le16_to_cpu(val
);
331 err
= regmap_bulk_read(hw
->regmap
, HTS221_REG_1RH_CAL_X_H
,
335 cal_x1
= le16_to_cpu(val
);
337 slope
= &hw
->sensors
[HTS221_SENSOR_H
].slope
;
338 b_gen
= &hw
->sensors
[HTS221_SENSOR_H
].b_gen
;
340 *slope
= ((cal_y1
- cal_y0
) * 8000) / (cal_x1
- cal_x0
);
341 *b_gen
= (((s32
)cal_x1
* cal_y0
- (s32
)cal_x0
* cal_y1
) * 1000) /
348 static int hts221_get_sensor_scale(struct hts221_hw
*hw
,
349 enum iio_chan_type ch_type
,
356 case IIO_HUMIDITYRELATIVE
:
357 data
= hw
->sensors
[HTS221_SENSOR_H
].slope
;
358 div
= (1 << 4) * 1000;
361 data
= hw
->sensors
[HTS221_SENSOR_T
].slope
;
362 div
= (1 << 6) * 1000;
368 tmp
= div_s64(data
* 1000000000LL, div
);
369 tmp
= div_s64_rem(tmp
, 1000000000LL, &rem
);
374 return IIO_VAL_INT_PLUS_NANO
;
377 static int hts221_get_sensor_offset(struct hts221_hw
*hw
,
378 enum iio_chan_type ch_type
,
385 case IIO_HUMIDITYRELATIVE
:
386 data
= hw
->sensors
[HTS221_SENSOR_H
].b_gen
;
387 div
= hw
->sensors
[HTS221_SENSOR_H
].slope
;
390 data
= hw
->sensors
[HTS221_SENSOR_T
].b_gen
;
391 div
= hw
->sensors
[HTS221_SENSOR_T
].slope
;
397 tmp
= div_s64(data
* 1000000000LL, div
);
398 tmp
= div_s64_rem(tmp
, 1000000000LL, &rem
);
403 return IIO_VAL_INT_PLUS_NANO
;
406 static int hts221_read_oneshot(struct hts221_hw
*hw
, u8 addr
, int *val
)
411 err
= hts221_set_enable(hw
, true);
417 err
= regmap_bulk_read(hw
->regmap
, addr
, &data
, sizeof(data
));
421 hts221_set_enable(hw
, false);
423 *val
= (s16
)le16_to_cpu(data
);
428 static int hts221_read_raw(struct iio_dev
*iio_dev
,
429 struct iio_chan_spec
const *ch
,
430 int *val
, int *val2
, long mask
)
432 struct hts221_hw
*hw
= iio_priv(iio_dev
);
435 ret
= iio_device_claim_direct_mode(iio_dev
);
440 case IIO_CHAN_INFO_RAW
:
441 ret
= hts221_read_oneshot(hw
, ch
->address
, val
);
443 case IIO_CHAN_INFO_SCALE
:
444 ret
= hts221_get_sensor_scale(hw
, ch
->type
, val
, val2
);
446 case IIO_CHAN_INFO_OFFSET
:
447 ret
= hts221_get_sensor_offset(hw
, ch
->type
, val
, val2
);
449 case IIO_CHAN_INFO_SAMP_FREQ
:
453 case IIO_CHAN_INFO_OVERSAMPLING_RATIO
: {
455 const struct hts221_avg
*avg
;
458 case IIO_HUMIDITYRELATIVE
:
459 avg
= &hts221_avg_list
[HTS221_SENSOR_H
];
460 idx
= hw
->sensors
[HTS221_SENSOR_H
].cur_avg_idx
;
461 *val
= avg
->avg_avl
[idx
];
465 avg
= &hts221_avg_list
[HTS221_SENSOR_T
];
466 idx
= hw
->sensors
[HTS221_SENSOR_T
].cur_avg_idx
;
467 *val
= avg
->avg_avl
[idx
];
481 iio_device_release_direct_mode(iio_dev
);
486 static int hts221_write_raw(struct iio_dev
*iio_dev
,
487 struct iio_chan_spec
const *chan
,
488 int val
, int val2
, long mask
)
490 struct hts221_hw
*hw
= iio_priv(iio_dev
);
493 ret
= iio_device_claim_direct_mode(iio_dev
);
498 case IIO_CHAN_INFO_SAMP_FREQ
:
499 ret
= hts221_update_odr(hw
, val
);
501 case IIO_CHAN_INFO_OVERSAMPLING_RATIO
:
502 switch (chan
->type
) {
503 case IIO_HUMIDITYRELATIVE
:
504 ret
= hts221_update_avg(hw
, HTS221_SENSOR_H
, val
);
507 ret
= hts221_update_avg(hw
, HTS221_SENSOR_T
, val
);
519 iio_device_release_direct_mode(iio_dev
);
524 static int hts221_validate_trigger(struct iio_dev
*iio_dev
,
525 struct iio_trigger
*trig
)
527 struct hts221_hw
*hw
= iio_priv(iio_dev
);
529 return hw
->trig
== trig
? 0 : -EINVAL
;
532 static IIO_DEVICE_ATTR(in_humidity_oversampling_ratio_available
, S_IRUGO
,
533 hts221_sysfs_rh_oversampling_avail
, NULL
, 0);
534 static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available
, S_IRUGO
,
535 hts221_sysfs_temp_oversampling_avail
, NULL
, 0);
536 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hts221_sysfs_sampling_freq
);
538 static struct attribute
*hts221_attributes
[] = {
539 &iio_dev_attr_sampling_frequency_available
.dev_attr
.attr
,
540 &iio_dev_attr_in_humidity_oversampling_ratio_available
.dev_attr
.attr
,
541 &iio_dev_attr_in_temp_oversampling_ratio_available
.dev_attr
.attr
,
545 static const struct attribute_group hts221_attribute_group
= {
546 .attrs
= hts221_attributes
,
549 static const struct iio_info hts221_info
= {
550 .attrs
= &hts221_attribute_group
,
551 .read_raw
= hts221_read_raw
,
552 .write_raw
= hts221_write_raw
,
553 .validate_trigger
= hts221_validate_trigger
,
556 static const unsigned long hts221_scan_masks
[] = {0x3, 0x0};
558 int hts221_probe(struct device
*dev
, int irq
, const char *name
,
559 struct regmap
*regmap
)
561 struct iio_dev
*iio_dev
;
562 struct hts221_hw
*hw
;
566 iio_dev
= devm_iio_device_alloc(dev
, sizeof(*hw
));
570 dev_set_drvdata(dev
, (void *)iio_dev
);
572 hw
= iio_priv(iio_dev
);
578 err
= hts221_check_whoami(hw
);
582 iio_dev
->modes
= INDIO_DIRECT_MODE
;
583 iio_dev
->dev
.parent
= hw
->dev
;
584 iio_dev
->available_scan_masks
= hts221_scan_masks
;
585 iio_dev
->channels
= hts221_channels
;
586 iio_dev
->num_channels
= ARRAY_SIZE(hts221_channels
);
587 iio_dev
->name
= HTS221_DEV_NAME
;
588 iio_dev
->info
= &hts221_info
;
590 /* enable Block Data Update */
591 err
= regmap_update_bits(hw
->regmap
, HTS221_REG_CNTRL1_ADDR
,
593 FIELD_PREP(HTS221_BDU_MASK
, 1));
597 err
= hts221_update_odr(hw
, hts221_odr_table
[0].hz
);
601 /* configure humidity sensor */
602 err
= hts221_parse_rh_caldata(hw
);
604 dev_err(hw
->dev
, "failed to get rh calibration data\n");
608 data
= hts221_avg_list
[HTS221_SENSOR_H
].avg_avl
[3];
609 err
= hts221_update_avg(hw
, HTS221_SENSOR_H
, data
);
611 dev_err(hw
->dev
, "failed to set rh oversampling ratio\n");
615 /* configure temperature sensor */
616 err
= hts221_parse_temp_caldata(hw
);
619 "failed to get temperature calibration data\n");
623 data
= hts221_avg_list
[HTS221_SENSOR_T
].avg_avl
[3];
624 err
= hts221_update_avg(hw
, HTS221_SENSOR_T
, data
);
627 "failed to set temperature oversampling ratio\n");
632 err
= hts221_allocate_buffers(hw
);
636 err
= hts221_allocate_trigger(hw
);
641 return devm_iio_device_register(hw
->dev
, iio_dev
);
643 EXPORT_SYMBOL(hts221_probe
);
645 static int __maybe_unused
hts221_suspend(struct device
*dev
)
647 struct iio_dev
*iio_dev
= dev_get_drvdata(dev
);
648 struct hts221_hw
*hw
= iio_priv(iio_dev
);
650 return regmap_update_bits(hw
->regmap
, HTS221_REG_CNTRL1_ADDR
,
652 FIELD_PREP(HTS221_ENABLE_MASK
, false));
655 static int __maybe_unused
hts221_resume(struct device
*dev
)
657 struct iio_dev
*iio_dev
= dev_get_drvdata(dev
);
658 struct hts221_hw
*hw
= iio_priv(iio_dev
);
662 err
= regmap_update_bits(hw
->regmap
, HTS221_REG_CNTRL1_ADDR
,
664 FIELD_PREP(HTS221_ENABLE_MASK
,
669 const struct dev_pm_ops hts221_pm_ops
= {
670 SET_SYSTEM_SLEEP_PM_OPS(hts221_suspend
, hts221_resume
)
672 EXPORT_SYMBOL(hts221_pm_ops
);
674 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
675 MODULE_DESCRIPTION("STMicroelectronics hts221 sensor driver");
676 MODULE_LICENSE("GPL v2");