1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This is a non-complete driver implementation for the
4 * HS3001 humidity and temperature sensor and compatibles. It does not include
5 * the configuration possibilities, where it needs to be set to 'programming mode'
9 * Copyright (C) 2023 SYS TEC electronic AG
10 * Author: Andre Werner <andre.werner@systec-electronic.com>
13 #include <linux/bitfield.h>
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/hwmon.h>
17 #include <linux/i2c.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/of_device.h>
22 #include <linux/slab.h>
23 #include <linux/types.h>
25 /* Measurement times */
26 #define HS3001_WAKEUP_TIME 100 /* us */
27 #define HS3001_8BIT_RESOLUTION 550 /* us */
28 #define HS3001_10BIT_RESOLUTION 1310 /* us */
29 #define HS3001_12BIT_RESOLUTION 4500 /* us */
30 #define HS3001_14BIT_RESOLUTION 16900 /* us */
32 #define HS3001_RESPONSE_LENGTH 4
34 #define HS3001_FIXPOINT_ARITH 1000U
36 #define HS3001_MASK_HUMIDITY_0X3FFF GENMASK(13, 0)
37 #define HS3001_MASK_STATUS_0XC0 GENMASK(7, 6)
39 /* Definitions for Status Bits of A/D Data */
40 #define HS3001_DATA_VALID 0x00 /* Valid Data */
41 #define HS3001_DATA_STALE 0x01 /* Stale Data */
44 struct i2c_client
*client
;
45 struct mutex i2c_lock
; /* lock for sending i2c commands */
46 u32 wait_time
; /* in us */
47 int temperature
; /* in milli degree */
48 u32 humidity
; /* in milli % */
51 static int hs3001_extract_temperature(u16 raw
)
53 /* fixpoint arithmetic 1 digit */
54 u32 temp
= (raw
>> 2) * HS3001_FIXPOINT_ARITH
* 165;
56 temp
/= (1 << 14) - 1;
58 return (int)temp
- 40 * HS3001_FIXPOINT_ARITH
;
61 static u32
hs3001_extract_humidity(u16 raw
)
63 u32 hum
= (raw
& HS3001_MASK_HUMIDITY_0X3FFF
) * HS3001_FIXPOINT_ARITH
* 100;
65 return hum
/ (1 << 14) - 1;
68 static int hs3001_data_fetch_command(struct i2c_client
*client
,
69 struct hs3001_data
*data
)
72 u8 buf
[HS3001_RESPONSE_LENGTH
];
75 ret
= i2c_master_recv(client
, buf
, HS3001_RESPONSE_LENGTH
);
76 if (ret
!= HS3001_RESPONSE_LENGTH
) {
77 ret
= ret
< 0 ? ret
: -EIO
;
79 "Error in i2c communication. Error code: %d.\n", ret
);
83 hs3001_status
= FIELD_GET(HS3001_MASK_STATUS_0XC0
, buf
[0]);
84 if (hs3001_status
== HS3001_DATA_STALE
) {
85 dev_dbg(&client
->dev
, "Sensor busy.\n");
88 if (hs3001_status
!= HS3001_DATA_VALID
) {
89 dev_dbg(&client
->dev
, "Data invalid.\n");
94 hs3001_extract_humidity(be16_to_cpup((__be16
*)&buf
[0]));
96 hs3001_extract_temperature(be16_to_cpup((__be16
*)&buf
[2]));
101 static umode_t
hs3001_is_visible(const void *data
, enum hwmon_sensor_types type
,
102 u32 attr
, int channel
)
104 /* Both, humidity and temperature can only be read. */
108 static int hs3001_read(struct device
*dev
, enum hwmon_sensor_types type
,
109 u32 attr
, int channel
, long *val
)
111 struct hs3001_data
*data
= dev_get_drvdata(dev
);
112 struct i2c_client
*client
= data
->client
;
115 mutex_lock(&data
->i2c_lock
);
116 ret
= i2c_master_send(client
, NULL
, 0);
118 mutex_unlock(&data
->i2c_lock
);
123 * Sensor needs some time to process measurement depending on
124 * resolution (ref. datasheet)
126 fsleep(data
->wait_time
);
128 ret
= hs3001_data_fetch_command(client
, data
);
129 mutex_unlock(&data
->i2c_lock
);
137 case hwmon_temp_input
:
138 *val
= data
->temperature
;
146 case hwmon_humidity_input
:
147 *val
= data
->humidity
;
160 static const struct hwmon_channel_info
*hs3001_info
[] = {
161 HWMON_CHANNEL_INFO(temp
, HWMON_T_INPUT
),
162 HWMON_CHANNEL_INFO(humidity
, HWMON_H_INPUT
),
166 static const struct hwmon_ops hs3001_hwmon_ops
= {
167 .is_visible
= hs3001_is_visible
,
171 static const struct hwmon_chip_info hs3001_chip_info
= {
172 .ops
= &hs3001_hwmon_ops
,
176 /* device ID table */
177 static const struct i2c_device_id hs3001_ids
[] = {
182 MODULE_DEVICE_TABLE(i2c
, hs3001_ids
);
184 static const struct of_device_id hs3001_of_match
[] = {
185 {.compatible
= "renesas,hs3001"},
189 MODULE_DEVICE_TABLE(of
, hs3001_of_match
);
191 static int hs3001_probe(struct i2c_client
*client
)
193 struct hs3001_data
*data
;
194 struct device
*hwmon_dev
;
195 struct device
*dev
= &client
->dev
;
197 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
))
200 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
204 data
->client
= client
;
207 * Measurement time = wake-up time + measurement time temperature
208 * + measurement time humidity. This is currently static, because
209 * enabling programming mode is not supported, yet.
211 data
->wait_time
= (HS3001_WAKEUP_TIME
+ HS3001_14BIT_RESOLUTION
+
212 HS3001_14BIT_RESOLUTION
);
214 mutex_init(&data
->i2c_lock
);
216 hwmon_dev
= devm_hwmon_device_register_with_info(dev
,
222 if (IS_ERR(hwmon_dev
))
223 return dev_err_probe(dev
, PTR_ERR(hwmon_dev
),
224 "Unable to register hwmon device.\n");
229 static struct i2c_driver hs3001_i2c_driver
= {
232 .of_match_table
= hs3001_of_match
,
234 .probe
= hs3001_probe
,
235 .id_table
= hs3001_ids
,
238 module_i2c_driver(hs3001_i2c_driver
);
240 MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>");
241 MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver");
242 MODULE_LICENSE("GPL");