1c942fddfSThomas 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 29*ffd96868SDan Robertson /* 30*ffd96868SDan Robertson * constants for reading the ID register 31*ffd96868SDan Robertson * SHTC1: 0x0007 with mask 0x003f 32*ffd96868SDan Robertson * SHTW1: 0x0007 with mask 0x003f 33*ffd96868SDan Robertson * SHTC3: 0x0807 with mask 0x083f 34*ffd96868SDan Robertson */ 35*ffd96868SDan Robertson #define SHTC3_ID 0x0807 36*ffd96868SDan Robertson #define SHTC3_ID_MASK 0x083f 37*ffd96868SDan Robertson #define SHTC1_ID 0x0007 38*ffd96868SDan Robertson #define SHTC1_ID_MASK 0x003f 391a539d37STomas Pop 401a539d37STomas Pop /* delays for non-blocking i2c commands, both in us */ 411a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 421a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000 43*ffd96868SDan Robertson #define SHTC3_NONBLOCKING_WAIT_TIME_HPM 12100 44*ffd96868SDan Robertson #define SHTC3_NONBLOCKING_WAIT_TIME_LPM 800 451a539d37STomas Pop 461a539d37STomas Pop #define SHTC1_CMD_LENGTH 2 471a539d37STomas Pop #define SHTC1_RESPONSE_LENGTH 6 481a539d37STomas Pop 49*ffd96868SDan Robertson enum shtcx_chips { 50*ffd96868SDan Robertson shtc1, 51*ffd96868SDan Robertson shtc3, 52*ffd96868SDan Robertson }; 53*ffd96868SDan Robertson 541a539d37STomas Pop struct shtc1_data { 551a539d37STomas Pop struct i2c_client *client; 561a539d37STomas Pop struct mutex update_lock; 571a539d37STomas Pop bool valid; 581a539d37STomas Pop unsigned long last_updated; /* in jiffies */ 591a539d37STomas Pop 601a539d37STomas Pop const unsigned char *command; 611a539d37STomas Pop unsigned int nonblocking_wait_time; /* in us */ 621a539d37STomas Pop 631a539d37STomas Pop struct shtc1_platform_data setup; 64*ffd96868SDan Robertson enum shtcx_chips chip; 651a539d37STomas Pop 661a539d37STomas Pop int temperature; /* 1000 * temperature in dgr C */ 671a539d37STomas Pop int humidity; /* 1000 * relative humidity in %RH */ 681a539d37STomas Pop }; 691a539d37STomas Pop 701a539d37STomas Pop static int shtc1_update_values(struct i2c_client *client, 711a539d37STomas Pop struct shtc1_data *data, 721a539d37STomas Pop char *buf, int bufsize) 731a539d37STomas Pop { 741a539d37STomas Pop int ret = i2c_master_send(client, data->command, SHTC1_CMD_LENGTH); 751a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 761a539d37STomas Pop dev_err(&client->dev, "failed to send command: %d\n", ret); 771a539d37STomas Pop return ret < 0 ? ret : -EIO; 781a539d37STomas Pop } 791a539d37STomas Pop 801a539d37STomas Pop /* 811a539d37STomas Pop * In blocking mode (clock stretching mode) the I2C bus 821a539d37STomas Pop * is blocked for other traffic, thus the call to i2c_master_recv() 831a539d37STomas Pop * will wait until the data is ready. For non blocking mode, we 841a539d37STomas Pop * have to wait ourselves. 851a539d37STomas Pop */ 861a539d37STomas Pop if (!data->setup.blocking_io) 871a539d37STomas Pop usleep_range(data->nonblocking_wait_time, 881a539d37STomas Pop data->nonblocking_wait_time + 1000); 891a539d37STomas Pop 901a539d37STomas Pop ret = i2c_master_recv(client, buf, bufsize); 911a539d37STomas Pop if (ret != bufsize) { 921a539d37STomas Pop dev_err(&client->dev, "failed to read values: %d\n", ret); 931a539d37STomas Pop return ret < 0 ? ret : -EIO; 941a539d37STomas Pop } 951a539d37STomas Pop 961a539d37STomas Pop return 0; 971a539d37STomas Pop } 981a539d37STomas Pop 991a539d37STomas Pop /* sysfs attributes */ 1001a539d37STomas Pop static struct shtc1_data *shtc1_update_client(struct device *dev) 1011a539d37STomas Pop { 1021a539d37STomas Pop struct shtc1_data *data = dev_get_drvdata(dev); 1031a539d37STomas Pop struct i2c_client *client = data->client; 1041a539d37STomas Pop unsigned char buf[SHTC1_RESPONSE_LENGTH]; 1051a539d37STomas Pop int val; 1061a539d37STomas Pop int ret = 0; 1071a539d37STomas Pop 1081a539d37STomas Pop mutex_lock(&data->update_lock); 1091a539d37STomas Pop 1101a539d37STomas Pop if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { 1111a539d37STomas Pop ret = shtc1_update_values(client, data, buf, sizeof(buf)); 1121a539d37STomas Pop if (ret) 1131a539d37STomas Pop goto out; 1141a539d37STomas Pop 1151a539d37STomas Pop /* 1161a539d37STomas Pop * From datasheet: 1171a539d37STomas Pop * T = -45 + 175 * ST / 2^16 1181a539d37STomas Pop * RH = 100 * SRH / 2^16 1191a539d37STomas Pop * 1201a539d37STomas Pop * Adapted for integer fixed point (3 digit) arithmetic. 1211a539d37STomas Pop */ 1221a539d37STomas Pop val = be16_to_cpup((__be16 *)buf); 1231a539d37STomas Pop data->temperature = ((21875 * val) >> 13) - 45000; 1241a539d37STomas Pop val = be16_to_cpup((__be16 *)(buf + 3)); 1251a539d37STomas Pop data->humidity = ((12500 * val) >> 13); 1261a539d37STomas Pop 1271a539d37STomas Pop data->last_updated = jiffies; 1281a539d37STomas Pop data->valid = true; 1291a539d37STomas Pop } 1301a539d37STomas Pop 1311a539d37STomas Pop out: 1321a539d37STomas Pop mutex_unlock(&data->update_lock); 1331a539d37STomas Pop 1341a539d37STomas Pop return ret == 0 ? data : ERR_PTR(ret); 1351a539d37STomas Pop } 1361a539d37STomas Pop 1371a539d37STomas Pop static ssize_t temp1_input_show(struct device *dev, 1381a539d37STomas Pop struct device_attribute *attr, 1391a539d37STomas Pop char *buf) 1401a539d37STomas Pop { 1411a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1421a539d37STomas Pop if (IS_ERR(data)) 1431a539d37STomas Pop return PTR_ERR(data); 1441a539d37STomas Pop 1451a539d37STomas Pop return sprintf(buf, "%d\n", data->temperature); 1461a539d37STomas Pop } 1471a539d37STomas Pop 1481a539d37STomas Pop static ssize_t humidity1_input_show(struct device *dev, 1491a539d37STomas Pop struct device_attribute *attr, char *buf) 1501a539d37STomas Pop { 1511a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1521a539d37STomas Pop if (IS_ERR(data)) 1531a539d37STomas Pop return PTR_ERR(data); 1541a539d37STomas Pop 1551a539d37STomas Pop return sprintf(buf, "%d\n", data->humidity); 1561a539d37STomas Pop } 1571a539d37STomas Pop 1581a539d37STomas Pop static DEVICE_ATTR_RO(temp1_input); 1591a539d37STomas Pop static DEVICE_ATTR_RO(humidity1_input); 1601a539d37STomas Pop 1611a539d37STomas Pop static struct attribute *shtc1_attrs[] = { 1621a539d37STomas Pop &dev_attr_temp1_input.attr, 1631a539d37STomas Pop &dev_attr_humidity1_input.attr, 1641a539d37STomas Pop NULL 1651a539d37STomas Pop }; 1661a539d37STomas Pop 1671a539d37STomas Pop ATTRIBUTE_GROUPS(shtc1); 1681a539d37STomas Pop 1691a539d37STomas Pop static void shtc1_select_command(struct shtc1_data *data) 1701a539d37STomas Pop { 1711a539d37STomas Pop if (data->setup.high_precision) { 1721a539d37STomas Pop data->command = data->setup.blocking_io ? 1731a539d37STomas Pop shtc1_cmd_measure_blocking_hpm : 1741a539d37STomas Pop shtc1_cmd_measure_nonblocking_hpm; 175*ffd96868SDan Robertson data->nonblocking_wait_time = (data->chip == shtc1) ? 176*ffd96868SDan Robertson SHTC1_NONBLOCKING_WAIT_TIME_HPM : 177*ffd96868SDan Robertson SHTC3_NONBLOCKING_WAIT_TIME_HPM; 1781a539d37STomas Pop } else { 1791a539d37STomas Pop data->command = data->setup.blocking_io ? 1801a539d37STomas Pop shtc1_cmd_measure_blocking_lpm : 1811a539d37STomas Pop shtc1_cmd_measure_nonblocking_lpm; 182*ffd96868SDan Robertson data->nonblocking_wait_time = (data->chip == shtc1) ? 183*ffd96868SDan Robertson SHTC1_NONBLOCKING_WAIT_TIME_LPM : 184*ffd96868SDan Robertson SHTC3_NONBLOCKING_WAIT_TIME_LPM; 1851a539d37STomas Pop } 1861a539d37STomas Pop } 1871a539d37STomas Pop 1881a539d37STomas Pop static int shtc1_probe(struct i2c_client *client, 1891a539d37STomas Pop const struct i2c_device_id *id) 1901a539d37STomas Pop { 1911a539d37STomas Pop int ret; 192*ffd96868SDan Robertson u16 id_reg; 193*ffd96868SDan Robertson char id_reg_buf[2]; 1941a539d37STomas Pop struct shtc1_data *data; 1951a539d37STomas Pop struct device *hwmon_dev; 196*ffd96868SDan Robertson enum shtcx_chips chip = id->driver_data; 1971a539d37STomas Pop struct i2c_adapter *adap = client->adapter; 1981a539d37STomas Pop struct device *dev = &client->dev; 1991a539d37STomas Pop 2001a539d37STomas Pop if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) { 2011a539d37STomas Pop dev_err(dev, "plain i2c transactions not supported\n"); 2021a539d37STomas Pop return -ENODEV; 2031a539d37STomas Pop } 2041a539d37STomas Pop 2051a539d37STomas Pop ret = i2c_master_send(client, shtc1_cmd_read_id_reg, SHTC1_CMD_LENGTH); 2061a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 2071a539d37STomas Pop dev_err(dev, "could not send read_id_reg command: %d\n", ret); 2081a539d37STomas Pop return ret < 0 ? ret : -ENODEV; 2091a539d37STomas Pop } 210*ffd96868SDan Robertson ret = i2c_master_recv(client, id_reg_buf, sizeof(id_reg_buf)); 211*ffd96868SDan Robertson if (ret != sizeof(id_reg_buf)) { 2121a539d37STomas Pop dev_err(dev, "could not read ID register: %d\n", ret); 2131a539d37STomas Pop return -ENODEV; 2141a539d37STomas Pop } 215*ffd96868SDan Robertson 216*ffd96868SDan Robertson id_reg = be16_to_cpup((__be16 *)id_reg_buf); 217*ffd96868SDan Robertson if (chip == shtc3) { 218*ffd96868SDan Robertson if ((id_reg & SHTC3_ID_MASK) != SHTC3_ID) { 219*ffd96868SDan Robertson dev_err(dev, "SHTC3 ID register does not match\n"); 220*ffd96868SDan Robertson return -ENODEV; 221*ffd96868SDan Robertson } 222*ffd96868SDan Robertson } else if ((id_reg & SHTC1_ID_MASK) != SHTC1_ID) { 223*ffd96868SDan Robertson dev_err(dev, "SHTC1 ID register does not match\n"); 2241a539d37STomas Pop return -ENODEV; 2251a539d37STomas Pop } 2261a539d37STomas Pop 2271a539d37STomas Pop data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 2281a539d37STomas Pop if (!data) 2291a539d37STomas Pop return -ENOMEM; 2301a539d37STomas Pop 2311a539d37STomas Pop data->setup.blocking_io = false; 2321a539d37STomas Pop data->setup.high_precision = true; 2331a539d37STomas Pop data->client = client; 234*ffd96868SDan Robertson data->chip = chip; 2351a539d37STomas Pop 2361a539d37STomas Pop if (client->dev.platform_data) 2371a539d37STomas Pop data->setup = *(struct shtc1_platform_data *)dev->platform_data; 2381a539d37STomas Pop shtc1_select_command(data); 2391a539d37STomas Pop mutex_init(&data->update_lock); 2401a539d37STomas Pop 2411a539d37STomas Pop hwmon_dev = devm_hwmon_device_register_with_groups(dev, 2421a539d37STomas Pop client->name, 2431a539d37STomas Pop data, 2441a539d37STomas Pop shtc1_groups); 2451a539d37STomas Pop if (IS_ERR(hwmon_dev)) 2461a539d37STomas Pop dev_dbg(dev, "unable to register hwmon device\n"); 2471a539d37STomas Pop 2481a539d37STomas Pop return PTR_ERR_OR_ZERO(hwmon_dev); 2491a539d37STomas Pop } 2501a539d37STomas Pop 2511a539d37STomas Pop /* device ID table */ 2521a539d37STomas Pop static const struct i2c_device_id shtc1_id[] = { 253*ffd96868SDan Robertson { "shtc1", shtc1 }, 254*ffd96868SDan Robertson { "shtw1", shtc1 }, 255*ffd96868SDan Robertson { "shtc3", shtc3 }, 2561a539d37STomas Pop { } 2571a539d37STomas Pop }; 2581a539d37STomas Pop MODULE_DEVICE_TABLE(i2c, shtc1_id); 2591a539d37STomas Pop 2601a539d37STomas Pop static struct i2c_driver shtc1_i2c_driver = { 2611a539d37STomas Pop .driver.name = "shtc1", 2621a539d37STomas Pop .probe = shtc1_probe, 2631a539d37STomas Pop .id_table = shtc1_id, 2641a539d37STomas Pop }; 2651a539d37STomas Pop 2661a539d37STomas Pop module_i2c_driver(shtc1_i2c_driver); 2671a539d37STomas Pop 2681a539d37STomas Pop MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>"); 2691a539d37STomas Pop MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver"); 2701a539d37STomas Pop MODULE_LICENSE("GPL"); 271