htu31.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * The driver for Measurement Specialties HTU31 Temperature and Humidity sensor.
  4. *
  5. * Copyright (C) 2025
  6. * Author: Andrei Lalaev <andrey.lalaev@gmail.com>
  7. */
  8. #include <linux/array_size.h>
  9. #include <linux/cleanup.h>
  10. #include <linux/crc8.h>
  11. #include <linux/debugfs.h>
  12. #include <linux/delay.h>
  13. #include <linux/hwmon.h>
  14. #include <linux/hwmon-sysfs.h>
  15. #include <linux/i2c.h>
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #define HTU31_READ_TEMP_HUM_CMD 0x00
  19. #define HTU31_READ_SERIAL_CMD 0x0a
  20. #define HTU31_CONVERSION_CMD 0x5e
  21. #define HTU31_HEATER_OFF_CMD 0x02
  22. #define HTU31_HEATER_ON_CMD 0x04
  23. #define HTU31_TEMP_HUM_LEN 6
  24. /* Conversion time for the highest resolution */
  25. #define HTU31_HUMIDITY_CONV_TIME 10000 /* us */
  26. #define HTU31_TEMPERATURE_CONV_TIME 15000 /* us */
  27. #define HTU31_SERIAL_NUMBER_LEN 3
  28. #define HTU31_SERIAL_NUMBER_CRC_LEN 1
  29. #define HTU31_SERIAL_NUMBER_CRC_OFFSET 3
  30. #define HTU31_CRC8_INIT_VAL 0
  31. #define HTU31_CRC8_POLYNOMIAL 0x31
  32. DECLARE_CRC8_TABLE(htu31_crc8_table);
  33. /**
  34. * struct htu31_data - all the data required to operate a HTU31 chip
  35. * @client: the i2c client associated with the HTU31
  36. * @lock: a mutex to prevent parallel access to the data
  37. * @wait_time: the time needed by sensor to convert values
  38. * @temperature: the latest temperature value in millidegrees
  39. * @humidity: the latest relative humidity value in millipercent
  40. * @serial_number: the serial number of the sensor
  41. * @heater_enable: the internal state of the heater
  42. */
  43. struct htu31_data {
  44. struct i2c_client *client;
  45. struct mutex lock; /* Used to protect against parallel data updates */
  46. long wait_time;
  47. long temperature;
  48. long humidity;
  49. u8 serial_number[HTU31_SERIAL_NUMBER_LEN];
  50. bool heater_enable;
  51. };
  52. static long htu31_temp_to_millicelsius(u16 val)
  53. {
  54. return -40000 + DIV_ROUND_CLOSEST_ULL(165000ULL * val, 65535);
  55. }
  56. static long htu31_relative_humidity(u16 val)
  57. {
  58. return DIV_ROUND_CLOSEST_ULL(100000ULL * val, 65535);
  59. }
  60. static int htu31_data_fetch_command(struct htu31_data *data)
  61. {
  62. struct i2c_client *client = data->client;
  63. u8 conversion_on = HTU31_CONVERSION_CMD;
  64. u8 read_data_cmd = HTU31_READ_TEMP_HUM_CMD;
  65. u8 t_h_buf[HTU31_TEMP_HUM_LEN] = {};
  66. struct i2c_msg msgs[] = {
  67. {
  68. .addr = client->addr,
  69. .flags = 0,
  70. .len = 1,
  71. .buf = &read_data_cmd,
  72. },
  73. {
  74. .addr = client->addr,
  75. .flags = I2C_M_RD,
  76. .len = sizeof(t_h_buf),
  77. .buf = t_h_buf,
  78. },
  79. };
  80. int ret;
  81. u8 crc;
  82. guard(mutex)(&data->lock);
  83. ret = i2c_master_send(client, &conversion_on, 1);
  84. if (ret != 1) {
  85. ret = ret < 0 ? ret : -EIO;
  86. dev_err(&client->dev,
  87. "Conversion command is failed. Error code: %d\n", ret);
  88. return ret;
  89. }
  90. fsleep(data->wait_time);
  91. ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  92. if (ret != ARRAY_SIZE(msgs)) {
  93. ret = ret < 0 ? ret : -EIO;
  94. dev_err(&client->dev,
  95. "T&H command is failed. Error code: %d\n", ret);
  96. return ret;
  97. }
  98. crc = crc8(htu31_crc8_table, &t_h_buf[0], 2, HTU31_CRC8_INIT_VAL);
  99. if (crc != t_h_buf[2]) {
  100. dev_err(&client->dev, "Temperature CRC mismatch\n");
  101. return -EIO;
  102. }
  103. crc = crc8(htu31_crc8_table, &t_h_buf[3], 2, HTU31_CRC8_INIT_VAL);
  104. if (crc != t_h_buf[5]) {
  105. dev_err(&client->dev, "Humidity CRC mismatch\n");
  106. return -EIO;
  107. }
  108. data->temperature = htu31_temp_to_millicelsius(be16_to_cpup((__be16 *)&t_h_buf[0]));
  109. data->humidity = htu31_relative_humidity(be16_to_cpup((__be16 *)&t_h_buf[3]));
  110. return 0;
  111. }
  112. static umode_t htu31_is_visible(const void *data, enum hwmon_sensor_types type,
  113. u32 attr, int channel)
  114. {
  115. switch (type) {
  116. case hwmon_temp:
  117. case hwmon_humidity:
  118. return 0444;
  119. default:
  120. return 0;
  121. }
  122. }
  123. static int htu31_read(struct device *dev, enum hwmon_sensor_types type,
  124. u32 attr, int channel, long *val)
  125. {
  126. struct htu31_data *data = dev_get_drvdata(dev);
  127. int ret;
  128. ret = htu31_data_fetch_command(data);
  129. if (ret < 0)
  130. return ret;
  131. switch (type) {
  132. case hwmon_temp:
  133. if (attr != hwmon_temp_input)
  134. return -EINVAL;
  135. *val = data->temperature;
  136. break;
  137. case hwmon_humidity:
  138. if (attr != hwmon_humidity_input)
  139. return -EINVAL;
  140. *val = data->humidity;
  141. break;
  142. default:
  143. return -EOPNOTSUPP;
  144. }
  145. return 0;
  146. }
  147. static int htu31_read_serial_number(struct htu31_data *data)
  148. {
  149. struct i2c_client *client = data->client;
  150. u8 read_sn_cmd = HTU31_READ_SERIAL_CMD;
  151. u8 sn_buf[HTU31_SERIAL_NUMBER_LEN + HTU31_SERIAL_NUMBER_CRC_LEN];
  152. struct i2c_msg msgs[] = {
  153. {
  154. .addr = client->addr,
  155. .flags = 0,
  156. .len = 1,
  157. .buf = &read_sn_cmd,
  158. },
  159. {
  160. .addr = client->addr,
  161. .flags = I2C_M_RD,
  162. .len = sizeof(sn_buf),
  163. .buf = sn_buf,
  164. },
  165. };
  166. int ret;
  167. u8 crc;
  168. ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  169. if (ret < 0)
  170. return ret;
  171. crc = crc8(htu31_crc8_table, sn_buf, HTU31_SERIAL_NUMBER_LEN, HTU31_CRC8_INIT_VAL);
  172. if (crc != sn_buf[HTU31_SERIAL_NUMBER_CRC_OFFSET]) {
  173. dev_err(&client->dev, "Serial number CRC mismatch\n");
  174. return -EIO;
  175. }
  176. memcpy(data->serial_number, sn_buf, HTU31_SERIAL_NUMBER_LEN);
  177. return 0;
  178. }
  179. static ssize_t heater_enable_show(struct device *dev,
  180. struct device_attribute *attr,
  181. char *buf)
  182. {
  183. struct htu31_data *data = dev_get_drvdata(dev);
  184. return sysfs_emit(buf, "%d\n", data->heater_enable);
  185. }
  186. static ssize_t heater_enable_store(struct device *dev,
  187. struct device_attribute *attr,
  188. const char *buf,
  189. size_t count)
  190. {
  191. struct htu31_data *data = dev_get_drvdata(dev);
  192. u8 heater_cmd;
  193. bool status;
  194. int ret;
  195. ret = kstrtobool(buf, &status);
  196. if (ret)
  197. return ret;
  198. heater_cmd = status ? HTU31_HEATER_ON_CMD : HTU31_HEATER_OFF_CMD;
  199. guard(mutex)(&data->lock);
  200. ret = i2c_master_send(data->client, &heater_cmd, 1);
  201. if (ret < 0)
  202. return ret;
  203. data->heater_enable = status;
  204. return count;
  205. }
  206. static DEVICE_ATTR_RW(heater_enable);
  207. static int serial_number_show(struct seq_file *seq_file,
  208. void *unused)
  209. {
  210. struct htu31_data *data = seq_file->private;
  211. seq_printf(seq_file, "%X%X%X\n", data->serial_number[0],
  212. data->serial_number[1], data->serial_number[2]);
  213. return 0;
  214. }
  215. DEFINE_SHOW_ATTRIBUTE(serial_number);
  216. static struct attribute *htu31_attrs[] = {
  217. &dev_attr_heater_enable.attr,
  218. NULL
  219. };
  220. ATTRIBUTE_GROUPS(htu31);
  221. static const struct hwmon_channel_info * const htu31_info[] = {
  222. HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
  223. HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT),
  224. NULL
  225. };
  226. static const struct hwmon_ops htu31_hwmon_ops = {
  227. .is_visible = htu31_is_visible,
  228. .read = htu31_read,
  229. };
  230. static const struct hwmon_chip_info htu31_chip_info = {
  231. .info = htu31_info,
  232. .ops = &htu31_hwmon_ops,
  233. };
  234. static int htu31_probe(struct i2c_client *client)
  235. {
  236. struct device *dev = &client->dev;
  237. struct device *hwmon_dev;
  238. struct htu31_data *data;
  239. int ret;
  240. data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  241. if (!data)
  242. return -ENOMEM;
  243. data->client = client;
  244. data->wait_time = HTU31_TEMPERATURE_CONV_TIME + HTU31_HUMIDITY_CONV_TIME;
  245. ret = devm_mutex_init(dev, &data->lock);
  246. if (ret)
  247. return ret;
  248. crc8_populate_msb(htu31_crc8_table, HTU31_CRC8_POLYNOMIAL);
  249. ret = htu31_read_serial_number(data);
  250. if (ret) {
  251. dev_err(dev, "Failed to read serial number\n");
  252. return ret;
  253. }
  254. debugfs_create_file("serial_number",
  255. 0444,
  256. client->debugfs,
  257. data,
  258. &serial_number_fops);
  259. hwmon_dev = devm_hwmon_device_register_with_info(dev,
  260. client->name,
  261. data,
  262. &htu31_chip_info,
  263. htu31_groups);
  264. return PTR_ERR_OR_ZERO(hwmon_dev);
  265. }
  266. static const struct i2c_device_id htu31_id[] = {
  267. { "htu31" },
  268. { }
  269. };
  270. MODULE_DEVICE_TABLE(i2c, htu31_id);
  271. #if IS_ENABLED(CONFIG_OF)
  272. static const struct of_device_id htu31_of_match[] = {
  273. { .compatible = "meas,htu31" },
  274. { }
  275. };
  276. MODULE_DEVICE_TABLE(of, htu31_of_match);
  277. #endif
  278. static struct i2c_driver htu31_driver = {
  279. .driver = {
  280. .name = "htu31",
  281. .of_match_table = of_match_ptr(htu31_of_match),
  282. },
  283. .probe = htu31_probe,
  284. .id_table = htu31_id,
  285. };
  286. module_i2c_driver(htu31_driver);
  287. MODULE_AUTHOR("Andrei Lalaev <andrey.lalaev@gmail.com>");
  288. MODULE_DESCRIPTION("HTU31 Temperature and Humidity sensor driver");
  289. MODULE_LICENSE("GPL");