1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21a539d37STomas Pop /* Sensirion SHTC1 humidity and temperature sensor driver 31a539d37STomas Pop * 41a539d37STomas Pop * Copyright (C) 2014 Sensirion AG, Switzerland 51a539d37STomas Pop * Author: Johannes Winkelmann <johannes.winkelmann@sensirion.com> 61a539d37STomas Pop */ 71a539d37STomas Pop 81a539d37STomas Pop #include <linux/module.h> 91a539d37STomas Pop #include <linux/init.h> 101a539d37STomas Pop #include <linux/slab.h> 111a539d37STomas Pop #include <linux/i2c.h> 121a539d37STomas Pop #include <linux/hwmon.h> 131a539d37STomas Pop #include <linux/hwmon-sysfs.h> 141a539d37STomas Pop #include <linux/err.h> 151a539d37STomas Pop #include <linux/delay.h> 161a539d37STomas Pop #include <linux/platform_data/shtc1.h> 171a539d37STomas Pop 181a539d37STomas Pop /* commands (high precision mode) */ 191a539d37STomas Pop static const unsigned char shtc1_cmd_measure_blocking_hpm[] = { 0x7C, 0xA2 }; 201a539d37STomas Pop static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 }; 211a539d37STomas Pop 221a539d37STomas Pop /* commands (low precision mode) */ 231a539d37STomas Pop static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 }; 241a539d37STomas Pop static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c }; 251a539d37STomas Pop 261a539d37STomas Pop /* command for reading the ID register */ 271a539d37STomas Pop static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 }; 281a539d37STomas Pop 291a539d37STomas Pop /* constants for reading the ID register */ 301a539d37STomas Pop #define SHTC1_ID 0x07 311a539d37STomas Pop #define SHTC1_ID_REG_MASK 0x1f 321a539d37STomas Pop 331a539d37STomas Pop /* delays for non-blocking i2c commands, both in us */ 341a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 351a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000 361a539d37STomas Pop 371a539d37STomas Pop #define SHTC1_CMD_LENGTH 2 381a539d37STomas Pop #define SHTC1_RESPONSE_LENGTH 6 391a539d37STomas Pop 401a539d37STomas Pop struct shtc1_data { 411a539d37STomas Pop struct i2c_client *client; 421a539d37STomas Pop struct mutex update_lock; 431a539d37STomas Pop bool valid; 441a539d37STomas Pop unsigned long last_updated; /* in jiffies */ 451a539d37STomas Pop 461a539d37STomas Pop const unsigned char *command; 471a539d37STomas Pop unsigned int nonblocking_wait_time; /* in us */ 481a539d37STomas Pop 491a539d37STomas Pop struct shtc1_platform_data setup; 501a539d37STomas Pop 511a539d37STomas Pop int temperature; /* 1000 * temperature in dgr C */ 521a539d37STomas Pop int humidity; /* 1000 * relative humidity in %RH */ 531a539d37STomas Pop }; 541a539d37STomas Pop 551a539d37STomas Pop static int shtc1_update_values(struct i2c_client *client, 561a539d37STomas Pop struct shtc1_data *data, 571a539d37STomas Pop char *buf, int bufsize) 581a539d37STomas Pop { 591a539d37STomas Pop int ret = i2c_master_send(client, data->command, SHTC1_CMD_LENGTH); 601a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 611a539d37STomas Pop dev_err(&client->dev, "failed to send command: %d\n", ret); 621a539d37STomas Pop return ret < 0 ? ret : -EIO; 631a539d37STomas Pop } 641a539d37STomas Pop 651a539d37STomas Pop /* 661a539d37STomas Pop * In blocking mode (clock stretching mode) the I2C bus 671a539d37STomas Pop * is blocked for other traffic, thus the call to i2c_master_recv() 681a539d37STomas Pop * will wait until the data is ready. For non blocking mode, we 691a539d37STomas Pop * have to wait ourselves. 701a539d37STomas Pop */ 711a539d37STomas Pop if (!data->setup.blocking_io) 721a539d37STomas Pop usleep_range(data->nonblocking_wait_time, 731a539d37STomas Pop data->nonblocking_wait_time + 1000); 741a539d37STomas Pop 751a539d37STomas Pop ret = i2c_master_recv(client, buf, bufsize); 761a539d37STomas Pop if (ret != bufsize) { 771a539d37STomas Pop dev_err(&client->dev, "failed to read values: %d\n", ret); 781a539d37STomas Pop return ret < 0 ? ret : -EIO; 791a539d37STomas Pop } 801a539d37STomas Pop 811a539d37STomas Pop return 0; 821a539d37STomas Pop } 831a539d37STomas Pop 841a539d37STomas Pop /* sysfs attributes */ 851a539d37STomas Pop static struct shtc1_data *shtc1_update_client(struct device *dev) 861a539d37STomas Pop { 871a539d37STomas Pop struct shtc1_data *data = dev_get_drvdata(dev); 881a539d37STomas Pop struct i2c_client *client = data->client; 891a539d37STomas Pop unsigned char buf[SHTC1_RESPONSE_LENGTH]; 901a539d37STomas Pop int val; 911a539d37STomas Pop int ret = 0; 921a539d37STomas Pop 931a539d37STomas Pop mutex_lock(&data->update_lock); 941a539d37STomas Pop 951a539d37STomas Pop if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { 961a539d37STomas Pop ret = shtc1_update_values(client, data, buf, sizeof(buf)); 971a539d37STomas Pop if (ret) 981a539d37STomas Pop goto out; 991a539d37STomas Pop 1001a539d37STomas Pop /* 1011a539d37STomas Pop * From datasheet: 1021a539d37STomas Pop * T = -45 + 175 * ST / 2^16 1031a539d37STomas Pop * RH = 100 * SRH / 2^16 1041a539d37STomas Pop * 1051a539d37STomas Pop * Adapted for integer fixed point (3 digit) arithmetic. 1061a539d37STomas Pop */ 1071a539d37STomas Pop val = be16_to_cpup((__be16 *)buf); 1081a539d37STomas Pop data->temperature = ((21875 * val) >> 13) - 45000; 1091a539d37STomas Pop val = be16_to_cpup((__be16 *)(buf + 3)); 1101a539d37STomas Pop data->humidity = ((12500 * val) >> 13); 1111a539d37STomas Pop 1121a539d37STomas Pop data->last_updated = jiffies; 1131a539d37STomas Pop data->valid = true; 1141a539d37STomas Pop } 1151a539d37STomas Pop 1161a539d37STomas Pop out: 1171a539d37STomas Pop mutex_unlock(&data->update_lock); 1181a539d37STomas Pop 1191a539d37STomas Pop return ret == 0 ? data : ERR_PTR(ret); 1201a539d37STomas Pop } 1211a539d37STomas Pop 1221a539d37STomas Pop static ssize_t temp1_input_show(struct device *dev, 1231a539d37STomas Pop struct device_attribute *attr, 1241a539d37STomas Pop char *buf) 1251a539d37STomas Pop { 1261a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1271a539d37STomas Pop if (IS_ERR(data)) 1281a539d37STomas Pop return PTR_ERR(data); 1291a539d37STomas Pop 1301a539d37STomas Pop return sprintf(buf, "%d\n", data->temperature); 1311a539d37STomas Pop } 1321a539d37STomas Pop 1331a539d37STomas Pop static ssize_t humidity1_input_show(struct device *dev, 1341a539d37STomas Pop struct device_attribute *attr, char *buf) 1351a539d37STomas Pop { 1361a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1371a539d37STomas Pop if (IS_ERR(data)) 1381a539d37STomas Pop return PTR_ERR(data); 1391a539d37STomas Pop 1401a539d37STomas Pop return sprintf(buf, "%d\n", data->humidity); 1411a539d37STomas Pop } 1421a539d37STomas Pop 1431a539d37STomas Pop static DEVICE_ATTR_RO(temp1_input); 1441a539d37STomas Pop static DEVICE_ATTR_RO(humidity1_input); 1451a539d37STomas Pop 1461a539d37STomas Pop static struct attribute *shtc1_attrs[] = { 1471a539d37STomas Pop &dev_attr_temp1_input.attr, 1481a539d37STomas Pop &dev_attr_humidity1_input.attr, 1491a539d37STomas Pop NULL 1501a539d37STomas Pop }; 1511a539d37STomas Pop 1521a539d37STomas Pop ATTRIBUTE_GROUPS(shtc1); 1531a539d37STomas Pop 1541a539d37STomas Pop static void shtc1_select_command(struct shtc1_data *data) 1551a539d37STomas Pop { 1561a539d37STomas Pop if (data->setup.high_precision) { 1571a539d37STomas Pop data->command = data->setup.blocking_io ? 1581a539d37STomas Pop shtc1_cmd_measure_blocking_hpm : 1591a539d37STomas Pop shtc1_cmd_measure_nonblocking_hpm; 1601a539d37STomas Pop data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM; 1611a539d37STomas Pop 1621a539d37STomas Pop } else { 1631a539d37STomas Pop data->command = data->setup.blocking_io ? 1641a539d37STomas Pop shtc1_cmd_measure_blocking_lpm : 1651a539d37STomas Pop shtc1_cmd_measure_nonblocking_lpm; 1661a539d37STomas Pop data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM; 1671a539d37STomas Pop } 1681a539d37STomas Pop } 1691a539d37STomas Pop 1701a539d37STomas Pop static int shtc1_probe(struct i2c_client *client, 1711a539d37STomas Pop const struct i2c_device_id *id) 1721a539d37STomas Pop { 1731a539d37STomas Pop int ret; 1741a539d37STomas Pop char id_reg[2]; 1751a539d37STomas Pop struct shtc1_data *data; 1761a539d37STomas Pop struct device *hwmon_dev; 1771a539d37STomas Pop struct i2c_adapter *adap = client->adapter; 1781a539d37STomas Pop struct device *dev = &client->dev; 1791a539d37STomas Pop 1801a539d37STomas Pop if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) { 1811a539d37STomas Pop dev_err(dev, "plain i2c transactions not supported\n"); 1821a539d37STomas Pop return -ENODEV; 1831a539d37STomas Pop } 1841a539d37STomas Pop 1851a539d37STomas Pop ret = i2c_master_send(client, shtc1_cmd_read_id_reg, SHTC1_CMD_LENGTH); 1861a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 1871a539d37STomas Pop dev_err(dev, "could not send read_id_reg command: %d\n", ret); 1881a539d37STomas Pop return ret < 0 ? ret : -ENODEV; 1891a539d37STomas Pop } 1901a539d37STomas Pop ret = i2c_master_recv(client, id_reg, sizeof(id_reg)); 1911a539d37STomas Pop if (ret != sizeof(id_reg)) { 1921a539d37STomas Pop dev_err(dev, "could not read ID register: %d\n", ret); 1931a539d37STomas Pop return -ENODEV; 1941a539d37STomas Pop } 1951a539d37STomas Pop if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) { 1961a539d37STomas Pop dev_err(dev, "ID register doesn't match\n"); 1971a539d37STomas Pop return -ENODEV; 1981a539d37STomas Pop } 1991a539d37STomas Pop 2001a539d37STomas Pop data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 2011a539d37STomas Pop if (!data) 2021a539d37STomas Pop return -ENOMEM; 2031a539d37STomas Pop 2041a539d37STomas Pop data->setup.blocking_io = false; 2051a539d37STomas Pop data->setup.high_precision = true; 2061a539d37STomas Pop data->client = client; 2071a539d37STomas Pop 2081a539d37STomas Pop if (client->dev.platform_data) 2091a539d37STomas Pop data->setup = *(struct shtc1_platform_data *)dev->platform_data; 2101a539d37STomas Pop shtc1_select_command(data); 2111a539d37STomas Pop mutex_init(&data->update_lock); 2121a539d37STomas Pop 2131a539d37STomas Pop hwmon_dev = devm_hwmon_device_register_with_groups(dev, 2141a539d37STomas Pop client->name, 2151a539d37STomas Pop data, 2161a539d37STomas Pop shtc1_groups); 2171a539d37STomas Pop if (IS_ERR(hwmon_dev)) 2181a539d37STomas Pop dev_dbg(dev, "unable to register hwmon device\n"); 2191a539d37STomas Pop 2201a539d37STomas Pop return PTR_ERR_OR_ZERO(hwmon_dev); 2211a539d37STomas Pop } 2221a539d37STomas Pop 2231a539d37STomas Pop /* device ID table */ 2241a539d37STomas Pop static const struct i2c_device_id shtc1_id[] = { 2251a539d37STomas Pop { "shtc1", 0 }, 2261a539d37STomas Pop { "shtw1", 0 }, 2271a539d37STomas Pop { } 2281a539d37STomas Pop }; 2291a539d37STomas Pop MODULE_DEVICE_TABLE(i2c, shtc1_id); 2301a539d37STomas Pop 2311a539d37STomas Pop static struct i2c_driver shtc1_i2c_driver = { 2321a539d37STomas Pop .driver.name = "shtc1", 2331a539d37STomas Pop .probe = shtc1_probe, 2341a539d37STomas Pop .id_table = shtc1_id, 2351a539d37STomas Pop }; 2361a539d37STomas Pop 2371a539d37STomas Pop module_i2c_driver(shtc1_i2c_driver); 2381a539d37STomas Pop 2391a539d37STomas Pop MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>"); 2401a539d37STomas Pop MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver"); 2411a539d37STomas Pop MODULE_LICENSE("GPL"); 242