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> 17*be7373b6SChris Ruehl #include <linux/of.h> 181a539d37STomas Pop 191a539d37STomas Pop /* commands (high precision mode) */ 201a539d37STomas Pop static const unsigned char shtc1_cmd_measure_blocking_hpm[] = { 0x7C, 0xA2 }; 211a539d37STomas Pop static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 }; 221a539d37STomas Pop 231a539d37STomas Pop /* commands (low precision mode) */ 241a539d37STomas Pop static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 }; 251a539d37STomas Pop static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c }; 261a539d37STomas Pop 271a539d37STomas Pop /* command for reading the ID register */ 281a539d37STomas Pop static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 }; 291a539d37STomas Pop 30ffd96868SDan Robertson /* 31ffd96868SDan Robertson * constants for reading the ID register 32ffd96868SDan Robertson * SHTC1: 0x0007 with mask 0x003f 33ffd96868SDan Robertson * SHTW1: 0x0007 with mask 0x003f 34ffd96868SDan Robertson * SHTC3: 0x0807 with mask 0x083f 35ffd96868SDan Robertson */ 36ffd96868SDan Robertson #define SHTC3_ID 0x0807 37ffd96868SDan Robertson #define SHTC3_ID_MASK 0x083f 38ffd96868SDan Robertson #define SHTC1_ID 0x0007 39ffd96868SDan Robertson #define SHTC1_ID_MASK 0x003f 401a539d37STomas Pop 411a539d37STomas Pop /* delays for non-blocking i2c commands, both in us */ 421a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 431a539d37STomas Pop #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000 44ffd96868SDan Robertson #define SHTC3_NONBLOCKING_WAIT_TIME_HPM 12100 45ffd96868SDan Robertson #define SHTC3_NONBLOCKING_WAIT_TIME_LPM 800 461a539d37STomas Pop 471a539d37STomas Pop #define SHTC1_CMD_LENGTH 2 481a539d37STomas Pop #define SHTC1_RESPONSE_LENGTH 6 491a539d37STomas Pop 50ffd96868SDan Robertson enum shtcx_chips { 51ffd96868SDan Robertson shtc1, 52ffd96868SDan Robertson shtc3, 53ffd96868SDan Robertson }; 54ffd96868SDan Robertson 551a539d37STomas Pop struct shtc1_data { 561a539d37STomas Pop struct i2c_client *client; 571a539d37STomas Pop struct mutex update_lock; 581a539d37STomas Pop bool valid; 591a539d37STomas Pop unsigned long last_updated; /* in jiffies */ 601a539d37STomas Pop 611a539d37STomas Pop const unsigned char *command; 621a539d37STomas Pop unsigned int nonblocking_wait_time; /* in us */ 631a539d37STomas Pop 641a539d37STomas Pop struct shtc1_platform_data setup; 65ffd96868SDan Robertson enum shtcx_chips chip; 661a539d37STomas Pop 671a539d37STomas Pop int temperature; /* 1000 * temperature in dgr C */ 681a539d37STomas Pop int humidity; /* 1000 * relative humidity in %RH */ 691a539d37STomas Pop }; 701a539d37STomas Pop 711a539d37STomas Pop static int shtc1_update_values(struct i2c_client *client, 721a539d37STomas Pop struct shtc1_data *data, 731a539d37STomas Pop char *buf, int bufsize) 741a539d37STomas Pop { 751a539d37STomas Pop int ret = i2c_master_send(client, data->command, SHTC1_CMD_LENGTH); 761a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 771a539d37STomas Pop dev_err(&client->dev, "failed to send command: %d\n", ret); 781a539d37STomas Pop return ret < 0 ? ret : -EIO; 791a539d37STomas Pop } 801a539d37STomas Pop 811a539d37STomas Pop /* 821a539d37STomas Pop * In blocking mode (clock stretching mode) the I2C bus 831a539d37STomas Pop * is blocked for other traffic, thus the call to i2c_master_recv() 841a539d37STomas Pop * will wait until the data is ready. For non blocking mode, we 851a539d37STomas Pop * have to wait ourselves. 861a539d37STomas Pop */ 871a539d37STomas Pop if (!data->setup.blocking_io) 881a539d37STomas Pop usleep_range(data->nonblocking_wait_time, 891a539d37STomas Pop data->nonblocking_wait_time + 1000); 901a539d37STomas Pop 911a539d37STomas Pop ret = i2c_master_recv(client, buf, bufsize); 921a539d37STomas Pop if (ret != bufsize) { 931a539d37STomas Pop dev_err(&client->dev, "failed to read values: %d\n", ret); 941a539d37STomas Pop return ret < 0 ? ret : -EIO; 951a539d37STomas Pop } 961a539d37STomas Pop 971a539d37STomas Pop return 0; 981a539d37STomas Pop } 991a539d37STomas Pop 1001a539d37STomas Pop /* sysfs attributes */ 1011a539d37STomas Pop static struct shtc1_data *shtc1_update_client(struct device *dev) 1021a539d37STomas Pop { 1031a539d37STomas Pop struct shtc1_data *data = dev_get_drvdata(dev); 1041a539d37STomas Pop struct i2c_client *client = data->client; 1051a539d37STomas Pop unsigned char buf[SHTC1_RESPONSE_LENGTH]; 1061a539d37STomas Pop int val; 1071a539d37STomas Pop int ret = 0; 1081a539d37STomas Pop 1091a539d37STomas Pop mutex_lock(&data->update_lock); 1101a539d37STomas Pop 1111a539d37STomas Pop if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { 1121a539d37STomas Pop ret = shtc1_update_values(client, data, buf, sizeof(buf)); 1131a539d37STomas Pop if (ret) 1141a539d37STomas Pop goto out; 1151a539d37STomas Pop 1161a539d37STomas Pop /* 1171a539d37STomas Pop * From datasheet: 1181a539d37STomas Pop * T = -45 + 175 * ST / 2^16 1191a539d37STomas Pop * RH = 100 * SRH / 2^16 1201a539d37STomas Pop * 1211a539d37STomas Pop * Adapted for integer fixed point (3 digit) arithmetic. 1221a539d37STomas Pop */ 1231a539d37STomas Pop val = be16_to_cpup((__be16 *)buf); 1241a539d37STomas Pop data->temperature = ((21875 * val) >> 13) - 45000; 1251a539d37STomas Pop val = be16_to_cpup((__be16 *)(buf + 3)); 1261a539d37STomas Pop data->humidity = ((12500 * val) >> 13); 1271a539d37STomas Pop 1281a539d37STomas Pop data->last_updated = jiffies; 1291a539d37STomas Pop data->valid = true; 1301a539d37STomas Pop } 1311a539d37STomas Pop 1321a539d37STomas Pop out: 1331a539d37STomas Pop mutex_unlock(&data->update_lock); 1341a539d37STomas Pop 1351a539d37STomas Pop return ret == 0 ? data : ERR_PTR(ret); 1361a539d37STomas Pop } 1371a539d37STomas Pop 1381a539d37STomas Pop static ssize_t temp1_input_show(struct device *dev, 1391a539d37STomas Pop struct device_attribute *attr, 1401a539d37STomas Pop char *buf) 1411a539d37STomas Pop { 1421a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1431a539d37STomas Pop if (IS_ERR(data)) 1441a539d37STomas Pop return PTR_ERR(data); 1451a539d37STomas Pop 1461a539d37STomas Pop return sprintf(buf, "%d\n", data->temperature); 1471a539d37STomas Pop } 1481a539d37STomas Pop 1491a539d37STomas Pop static ssize_t humidity1_input_show(struct device *dev, 1501a539d37STomas Pop struct device_attribute *attr, char *buf) 1511a539d37STomas Pop { 1521a539d37STomas Pop struct shtc1_data *data = shtc1_update_client(dev); 1531a539d37STomas Pop if (IS_ERR(data)) 1541a539d37STomas Pop return PTR_ERR(data); 1551a539d37STomas Pop 1561a539d37STomas Pop return sprintf(buf, "%d\n", data->humidity); 1571a539d37STomas Pop } 1581a539d37STomas Pop 1591a539d37STomas Pop static DEVICE_ATTR_RO(temp1_input); 1601a539d37STomas Pop static DEVICE_ATTR_RO(humidity1_input); 1611a539d37STomas Pop 1621a539d37STomas Pop static struct attribute *shtc1_attrs[] = { 1631a539d37STomas Pop &dev_attr_temp1_input.attr, 1641a539d37STomas Pop &dev_attr_humidity1_input.attr, 1651a539d37STomas Pop NULL 1661a539d37STomas Pop }; 1671a539d37STomas Pop 1681a539d37STomas Pop ATTRIBUTE_GROUPS(shtc1); 1691a539d37STomas Pop 1701a539d37STomas Pop static void shtc1_select_command(struct shtc1_data *data) 1711a539d37STomas Pop { 1721a539d37STomas Pop if (data->setup.high_precision) { 1731a539d37STomas Pop data->command = data->setup.blocking_io ? 1741a539d37STomas Pop shtc1_cmd_measure_blocking_hpm : 1751a539d37STomas Pop shtc1_cmd_measure_nonblocking_hpm; 176ffd96868SDan Robertson data->nonblocking_wait_time = (data->chip == shtc1) ? 177ffd96868SDan Robertson SHTC1_NONBLOCKING_WAIT_TIME_HPM : 178ffd96868SDan Robertson SHTC3_NONBLOCKING_WAIT_TIME_HPM; 1791a539d37STomas Pop } else { 1801a539d37STomas Pop data->command = data->setup.blocking_io ? 1811a539d37STomas Pop shtc1_cmd_measure_blocking_lpm : 1821a539d37STomas Pop shtc1_cmd_measure_nonblocking_lpm; 183ffd96868SDan Robertson data->nonblocking_wait_time = (data->chip == shtc1) ? 184ffd96868SDan Robertson SHTC1_NONBLOCKING_WAIT_TIME_LPM : 185ffd96868SDan Robertson SHTC3_NONBLOCKING_WAIT_TIME_LPM; 1861a539d37STomas Pop } 1871a539d37STomas Pop } 1881a539d37STomas Pop 18967487038SStephen Kitt static const struct i2c_device_id shtc1_id[]; 19067487038SStephen Kitt 19167487038SStephen Kitt static int shtc1_probe(struct i2c_client *client) 1921a539d37STomas Pop { 1931a539d37STomas Pop int ret; 194ffd96868SDan Robertson u16 id_reg; 195ffd96868SDan Robertson char id_reg_buf[2]; 1961a539d37STomas Pop struct shtc1_data *data; 1971a539d37STomas Pop struct device *hwmon_dev; 19867487038SStephen Kitt enum shtcx_chips chip = i2c_match_id(shtc1_id, client)->driver_data; 1991a539d37STomas Pop struct i2c_adapter *adap = client->adapter; 2001a539d37STomas Pop struct device *dev = &client->dev; 201*be7373b6SChris Ruehl struct device_node *np = dev->of_node; 2021a539d37STomas Pop 2031a539d37STomas Pop if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) { 2041a539d37STomas Pop dev_err(dev, "plain i2c transactions not supported\n"); 2051a539d37STomas Pop return -ENODEV; 2061a539d37STomas Pop } 2071a539d37STomas Pop 2081a539d37STomas Pop ret = i2c_master_send(client, shtc1_cmd_read_id_reg, SHTC1_CMD_LENGTH); 2091a539d37STomas Pop if (ret != SHTC1_CMD_LENGTH) { 2101a539d37STomas Pop dev_err(dev, "could not send read_id_reg command: %d\n", ret); 2111a539d37STomas Pop return ret < 0 ? ret : -ENODEV; 2121a539d37STomas Pop } 213ffd96868SDan Robertson ret = i2c_master_recv(client, id_reg_buf, sizeof(id_reg_buf)); 214ffd96868SDan Robertson if (ret != sizeof(id_reg_buf)) { 2151a539d37STomas Pop dev_err(dev, "could not read ID register: %d\n", ret); 2161a539d37STomas Pop return -ENODEV; 2171a539d37STomas Pop } 218ffd96868SDan Robertson 219ffd96868SDan Robertson id_reg = be16_to_cpup((__be16 *)id_reg_buf); 220ffd96868SDan Robertson if (chip == shtc3) { 221ffd96868SDan Robertson if ((id_reg & SHTC3_ID_MASK) != SHTC3_ID) { 222ffd96868SDan Robertson dev_err(dev, "SHTC3 ID register does not match\n"); 223ffd96868SDan Robertson return -ENODEV; 224ffd96868SDan Robertson } 225ffd96868SDan Robertson } else if ((id_reg & SHTC1_ID_MASK) != SHTC1_ID) { 226ffd96868SDan Robertson dev_err(dev, "SHTC1 ID register does not match\n"); 2271a539d37STomas Pop return -ENODEV; 2281a539d37STomas Pop } 2291a539d37STomas Pop 2301a539d37STomas Pop data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 2311a539d37STomas Pop if (!data) 2321a539d37STomas Pop return -ENOMEM; 2331a539d37STomas Pop 2341a539d37STomas Pop data->setup.blocking_io = false; 2351a539d37STomas Pop data->setup.high_precision = true; 2361a539d37STomas Pop data->client = client; 237ffd96868SDan Robertson data->chip = chip; 2381a539d37STomas Pop 239*be7373b6SChris Ruehl if (np) { 240*be7373b6SChris Ruehl data->setup.blocking_io = of_property_read_bool(np, "sensirion,blocking-io"); 241*be7373b6SChris Ruehl data->setup.high_precision = !of_property_read_bool(np, "sensicon,low-precision"); 242*be7373b6SChris Ruehl } else { 2431a539d37STomas Pop if (client->dev.platform_data) 2441a539d37STomas Pop data->setup = *(struct shtc1_platform_data *)dev->platform_data; 245*be7373b6SChris Ruehl } 246*be7373b6SChris Ruehl 2471a539d37STomas Pop shtc1_select_command(data); 2481a539d37STomas Pop mutex_init(&data->update_lock); 2491a539d37STomas Pop 2501a539d37STomas Pop hwmon_dev = devm_hwmon_device_register_with_groups(dev, 2511a539d37STomas Pop client->name, 2521a539d37STomas Pop data, 2531a539d37STomas Pop shtc1_groups); 2541a539d37STomas Pop if (IS_ERR(hwmon_dev)) 2551a539d37STomas Pop dev_dbg(dev, "unable to register hwmon device\n"); 2561a539d37STomas Pop 2571a539d37STomas Pop return PTR_ERR_OR_ZERO(hwmon_dev); 2581a539d37STomas Pop } 2591a539d37STomas Pop 2601a539d37STomas Pop /* device ID table */ 2611a539d37STomas Pop static const struct i2c_device_id shtc1_id[] = { 262ffd96868SDan Robertson { "shtc1", shtc1 }, 263ffd96868SDan Robertson { "shtw1", shtc1 }, 264ffd96868SDan Robertson { "shtc3", shtc3 }, 2651a539d37STomas Pop { } 2661a539d37STomas Pop }; 2671a539d37STomas Pop MODULE_DEVICE_TABLE(i2c, shtc1_id); 2681a539d37STomas Pop 269*be7373b6SChris Ruehl static const struct of_device_id shtc1_of_match[] = { 270*be7373b6SChris Ruehl { .compatible = "sensirion,shtc1" }, 271*be7373b6SChris Ruehl { .compatible = "sensirion,shtw1" }, 272*be7373b6SChris Ruehl { .compatible = "sensirion,shtc3" }, 273*be7373b6SChris Ruehl { } 274*be7373b6SChris Ruehl }; 275*be7373b6SChris Ruehl MODULE_DEVICE_TABLE(of, shtc1_of_match); 276*be7373b6SChris Ruehl 2771a539d37STomas Pop static struct i2c_driver shtc1_i2c_driver = { 278*be7373b6SChris Ruehl .driver = { 279*be7373b6SChris Ruehl .name = "shtc1", 280*be7373b6SChris Ruehl .of_match_table = shtc1_of_match, 281*be7373b6SChris Ruehl }, 28267487038SStephen Kitt .probe_new = shtc1_probe, 2831a539d37STomas Pop .id_table = shtc1_id, 2841a539d37STomas Pop }; 2851a539d37STomas Pop 2861a539d37STomas Pop module_i2c_driver(shtc1_i2c_driver); 2871a539d37STomas Pop 2881a539d37STomas Pop MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>"); 2891a539d37STomas Pop MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver"); 2901a539d37STomas Pop MODULE_LICENSE("GPL"); 291