1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 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' 6 * during power-up. 7 * 8 * 9 * Copyright (C) 2023 SYS TEC electronic AG 10 * Author: Andre Werner <andre.werner@systec-electronic.com> 11 */ 12 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> 24 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 */ 31 32 #define HS3001_RESPONSE_LENGTH 4 33 34 #define HS3001_FIXPOINT_ARITH 1000U 35 36 #define HS3001_MASK_HUMIDITY_0X3FFF GENMASK(13, 0) 37 #define HS3001_MASK_STATUS_0XC0 GENMASK(7, 6) 38 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 */ 42 43 struct hs3001_data { 44 struct i2c_client *client; 45 u32 wait_time; /* in us */ 46 int temperature; /* in milli degree */ 47 u32 humidity; /* in milli % */ 48 }; 49 50 static int hs3001_extract_temperature(u16 raw) 51 { 52 /* fixpoint arithmetic 1 digit */ 53 u32 temp = (raw >> 2) * HS3001_FIXPOINT_ARITH * 165; 54 55 temp /= (1 << 14) - 1; 56 57 return (int)temp - 40 * HS3001_FIXPOINT_ARITH; 58 } 59 60 static u32 hs3001_extract_humidity(u16 raw) 61 { 62 u32 hum = (raw & HS3001_MASK_HUMIDITY_0X3FFF) * HS3001_FIXPOINT_ARITH * 100; 63 64 return hum / (1 << 14) - 1; 65 } 66 67 static int hs3001_data_fetch_command(struct i2c_client *client, 68 struct hs3001_data *data) 69 { 70 int ret; 71 u8 buf[HS3001_RESPONSE_LENGTH]; 72 u8 hs3001_status; 73 74 ret = i2c_master_recv(client, buf, HS3001_RESPONSE_LENGTH); 75 if (ret != HS3001_RESPONSE_LENGTH) { 76 ret = ret < 0 ? ret : -EIO; 77 dev_dbg(&client->dev, 78 "Error in i2c communication. Error code: %d.\n", ret); 79 return ret; 80 } 81 82 hs3001_status = FIELD_GET(HS3001_MASK_STATUS_0XC0, buf[0]); 83 if (hs3001_status == HS3001_DATA_STALE) { 84 dev_dbg(&client->dev, "Sensor busy.\n"); 85 return -EBUSY; 86 } 87 if (hs3001_status != HS3001_DATA_VALID) { 88 dev_dbg(&client->dev, "Data invalid.\n"); 89 return -EIO; 90 } 91 92 data->humidity = 93 hs3001_extract_humidity(be16_to_cpup((__be16 *)&buf[0])); 94 data->temperature = 95 hs3001_extract_temperature(be16_to_cpup((__be16 *)&buf[2])); 96 97 return 0; 98 } 99 100 static umode_t hs3001_is_visible(const void *data, enum hwmon_sensor_types type, 101 u32 attr, int channel) 102 { 103 /* Both, humidity and temperature can only be read. */ 104 return 0444; 105 } 106 107 static int hs3001_read(struct device *dev, enum hwmon_sensor_types type, 108 u32 attr, int channel, long *val) 109 { 110 struct hs3001_data *data = dev_get_drvdata(dev); 111 struct i2c_client *client = data->client; 112 int ret; 113 114 ret = i2c_master_send(client, NULL, 0); 115 if (ret < 0) 116 return ret; 117 118 /* 119 * Sensor needs some time to process measurement depending on 120 * resolution (ref. datasheet) 121 */ 122 fsleep(data->wait_time); 123 124 ret = hs3001_data_fetch_command(client, data); 125 if (ret < 0) 126 return ret; 127 128 switch (type) { 129 case hwmon_temp: 130 switch (attr) { 131 case hwmon_temp_input: 132 *val = data->temperature; 133 break; 134 default: 135 return -EINVAL; 136 } 137 break; 138 case hwmon_humidity: 139 switch (attr) { 140 case hwmon_humidity_input: 141 *val = data->humidity; 142 break; 143 default: 144 return -EINVAL; 145 } 146 break; 147 default: 148 return -EINVAL; 149 } 150 151 return 0; 152 } 153 154 static const struct hwmon_channel_info *hs3001_info[] = { 155 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 156 HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT), 157 NULL 158 }; 159 160 static const struct hwmon_ops hs3001_hwmon_ops = { 161 .is_visible = hs3001_is_visible, 162 .read = hs3001_read, 163 }; 164 165 static const struct hwmon_chip_info hs3001_chip_info = { 166 .ops = &hs3001_hwmon_ops, 167 .info = hs3001_info, 168 }; 169 170 /* device ID table */ 171 static const struct i2c_device_id hs3001_ids[] = { 172 { "hs3001" }, 173 { }, 174 }; 175 176 MODULE_DEVICE_TABLE(i2c, hs3001_ids); 177 178 static const struct of_device_id hs3001_of_match[] = { 179 {.compatible = "renesas,hs3001"}, 180 { }, 181 }; 182 183 MODULE_DEVICE_TABLE(of, hs3001_of_match); 184 185 static int hs3001_probe(struct i2c_client *client) 186 { 187 struct hs3001_data *data; 188 struct device *hwmon_dev; 189 struct device *dev = &client->dev; 190 191 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 192 return -EOPNOTSUPP; 193 194 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 195 if (!data) 196 return -ENOMEM; 197 198 data->client = client; 199 200 /* 201 * Measurement time = wake-up time + measurement time temperature 202 * + measurement time humidity. This is currently static, because 203 * enabling programming mode is not supported, yet. 204 */ 205 data->wait_time = (HS3001_WAKEUP_TIME + HS3001_14BIT_RESOLUTION + 206 HS3001_14BIT_RESOLUTION); 207 208 hwmon_dev = devm_hwmon_device_register_with_info(dev, 209 client->name, 210 data, 211 &hs3001_chip_info, 212 NULL); 213 214 if (IS_ERR(hwmon_dev)) 215 return dev_err_probe(dev, PTR_ERR(hwmon_dev), 216 "Unable to register hwmon device.\n"); 217 218 return 0; 219 } 220 221 static struct i2c_driver hs3001_i2c_driver = { 222 .driver = { 223 .name = "hs3001", 224 .of_match_table = hs3001_of_match, 225 }, 226 .probe = hs3001_probe, 227 .id_table = hs3001_ids, 228 }; 229 230 module_i2c_driver(hs3001_i2c_driver); 231 232 MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>"); 233 MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver"); 234 MODULE_LICENSE("GPL"); 235