17f07ec0fSandrea.merello /* 27f07ec0fSandrea.merello * STTS751 sensor driver 37f07ec0fSandrea.merello * 47f07ec0fSandrea.merello * Copyright (C) 2016-2017 Istituto Italiano di Tecnologia - RBCS - EDL 57f07ec0fSandrea.merello * Robotics, Brain and Cognitive Sciences department 67f07ec0fSandrea.merello * Electronic Design Laboratory 77f07ec0fSandrea.merello * 87f07ec0fSandrea.merello * Written by Andrea Merello <andrea.merello@gmail.com> 97f07ec0fSandrea.merello * 107f07ec0fSandrea.merello * Based on LM95241 driver and LM90 driver 117f07ec0fSandrea.merello * 127f07ec0fSandrea.merello * This program is free software; you can redistribute it and/or modify 137f07ec0fSandrea.merello * it under the terms of the GNU General Public License as published by 147f07ec0fSandrea.merello * the Free Software Foundation; either version 2 of the License, or 157f07ec0fSandrea.merello * (at your option) any later version. 167f07ec0fSandrea.merello * 177f07ec0fSandrea.merello * This program is distributed in the hope that it will be useful, 187f07ec0fSandrea.merello * but WITHOUT ANY WARRANTY; without even the implied warranty of 197f07ec0fSandrea.merello * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 207f07ec0fSandrea.merello * GNU General Public License for more details. 217f07ec0fSandrea.merello */ 227f07ec0fSandrea.merello 237f07ec0fSandrea.merello #include <linux/bitops.h> 247f07ec0fSandrea.merello #include <linux/err.h> 257f07ec0fSandrea.merello #include <linux/hwmon.h> 267f07ec0fSandrea.merello #include <linux/hwmon-sysfs.h> 277f07ec0fSandrea.merello #include <linux/i2c.h> 287f07ec0fSandrea.merello #include <linux/init.h> 297f07ec0fSandrea.merello #include <linux/interrupt.h> 307f07ec0fSandrea.merello #include <linux/jiffies.h> 317f07ec0fSandrea.merello #include <linux/module.h> 327f07ec0fSandrea.merello #include <linux/mutex.h> 337f07ec0fSandrea.merello #include <linux/property.h> 347f07ec0fSandrea.merello #include <linux/slab.h> 357f07ec0fSandrea.merello #include <linux/sysfs.h> 367f07ec0fSandrea.merello #include <linux/util_macros.h> 377f07ec0fSandrea.merello 387f07ec0fSandrea.merello #define DEVNAME "stts751" 397f07ec0fSandrea.merello 407f07ec0fSandrea.merello static const unsigned short normal_i2c[] = { 417f07ec0fSandrea.merello 0x48, 0x49, 0x38, 0x39, /* STTS751-0 */ 427f07ec0fSandrea.merello 0x4A, 0x4B, 0x3A, 0x3B, /* STTS751-1 */ 437f07ec0fSandrea.merello I2C_CLIENT_END }; 447f07ec0fSandrea.merello 457f07ec0fSandrea.merello #define STTS751_REG_TEMP_H 0x00 467f07ec0fSandrea.merello #define STTS751_REG_STATUS 0x01 477f07ec0fSandrea.merello #define STTS751_STATUS_TRIPT BIT(0) 487f07ec0fSandrea.merello #define STTS751_STATUS_TRIPL BIT(5) 497f07ec0fSandrea.merello #define STTS751_STATUS_TRIPH BIT(6) 507f07ec0fSandrea.merello #define STTS751_REG_TEMP_L 0x02 517f07ec0fSandrea.merello #define STTS751_REG_CONF 0x03 527f07ec0fSandrea.merello #define STTS751_CONF_RES_MASK 0x0C 537f07ec0fSandrea.merello #define STTS751_CONF_RES_SHIFT 2 547f07ec0fSandrea.merello #define STTS751_CONF_EVENT_DIS BIT(7) 557f07ec0fSandrea.merello #define STTS751_CONF_STOP BIT(6) 567f07ec0fSandrea.merello #define STTS751_REG_RATE 0x04 577f07ec0fSandrea.merello #define STTS751_REG_HLIM_H 0x05 587f07ec0fSandrea.merello #define STTS751_REG_HLIM_L 0x06 597f07ec0fSandrea.merello #define STTS751_REG_LLIM_H 0x07 607f07ec0fSandrea.merello #define STTS751_REG_LLIM_L 0x08 617f07ec0fSandrea.merello #define STTS751_REG_TLIM 0x20 627f07ec0fSandrea.merello #define STTS751_REG_HYST 0x21 637f07ec0fSandrea.merello #define STTS751_REG_SMBUS_TO 0x22 647f07ec0fSandrea.merello 657f07ec0fSandrea.merello #define STTS751_REG_PROD_ID 0xFD 667f07ec0fSandrea.merello #define STTS751_REG_MAN_ID 0xFE 677f07ec0fSandrea.merello #define STTS751_REG_REV_ID 0xFF 687f07ec0fSandrea.merello 697f07ec0fSandrea.merello #define STTS751_0_PROD_ID 0x00 707f07ec0fSandrea.merello #define STTS751_1_PROD_ID 0x01 717f07ec0fSandrea.merello #define ST_MAN_ID 0x53 727f07ec0fSandrea.merello 737f07ec0fSandrea.merello /* 747f07ec0fSandrea.merello * Possible update intervals are (in mS): 757f07ec0fSandrea.merello * 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 62.5, 31.25 767f07ec0fSandrea.merello * However we are not going to complicate things too much and we stick to the 777f07ec0fSandrea.merello * approx value in mS. 787f07ec0fSandrea.merello */ 797f07ec0fSandrea.merello static const int stts751_intervals[] = { 807f07ec0fSandrea.merello 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 63, 31 817f07ec0fSandrea.merello }; 827f07ec0fSandrea.merello 837f07ec0fSandrea.merello static const struct i2c_device_id stts751_id[] = { 847f07ec0fSandrea.merello { "stts751", 0 }, 857f07ec0fSandrea.merello { } 867f07ec0fSandrea.merello }; 877f07ec0fSandrea.merello 881c1a7b75SJavier Martinez Canillas static const struct of_device_id stts751_of_match[] = { 891c1a7b75SJavier Martinez Canillas { .compatible = "stts751" }, 901c1a7b75SJavier Martinez Canillas { }, 911c1a7b75SJavier Martinez Canillas }; 921c1a7b75SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, stts751_of_match); 931c1a7b75SJavier Martinez Canillas 947f07ec0fSandrea.merello struct stts751_priv { 957f07ec0fSandrea.merello struct device *dev; 967f07ec0fSandrea.merello struct i2c_client *client; 977f07ec0fSandrea.merello struct mutex access_lock; 987f07ec0fSandrea.merello u8 interval; 997f07ec0fSandrea.merello int res; 1007f07ec0fSandrea.merello int event_max, event_min; 1017f07ec0fSandrea.merello int therm; 1027f07ec0fSandrea.merello int hyst; 1037f07ec0fSandrea.merello bool smbus_timeout; 1047f07ec0fSandrea.merello int temp; 1057f07ec0fSandrea.merello unsigned long last_update, last_alert_update; 1067f07ec0fSandrea.merello u8 config; 1077f07ec0fSandrea.merello bool min_alert, max_alert, therm_trip; 1087f07ec0fSandrea.merello bool data_valid, alert_valid; 1097f07ec0fSandrea.merello bool notify_max, notify_min; 1107f07ec0fSandrea.merello }; 1117f07ec0fSandrea.merello 1127f07ec0fSandrea.merello /* 1137f07ec0fSandrea.merello * These functions converts temperature from HW format to integer format and 1147f07ec0fSandrea.merello * vice-vers. They are (mostly) taken from lm90 driver. Unit is in mC. 1157f07ec0fSandrea.merello */ 1167f07ec0fSandrea.merello static int stts751_to_deg(s16 hw_val) 1177f07ec0fSandrea.merello { 1187f07ec0fSandrea.merello return hw_val * 125 / 32; 1197f07ec0fSandrea.merello } 1207f07ec0fSandrea.merello 1217f07ec0fSandrea.merello static s32 stts751_to_hw(int val) 1227f07ec0fSandrea.merello { 1237f07ec0fSandrea.merello return DIV_ROUND_CLOSEST(val, 125) * 32; 1247f07ec0fSandrea.merello } 1257f07ec0fSandrea.merello 1267f07ec0fSandrea.merello static int stts751_adjust_resolution(struct stts751_priv *priv) 1277f07ec0fSandrea.merello { 1287f07ec0fSandrea.merello u8 res; 1297f07ec0fSandrea.merello 1307f07ec0fSandrea.merello switch (priv->interval) { 1317f07ec0fSandrea.merello case 9: 1327f07ec0fSandrea.merello /* 10 bits */ 1337f07ec0fSandrea.merello res = 0; 1347f07ec0fSandrea.merello break; 1357f07ec0fSandrea.merello case 8: 1367f07ec0fSandrea.merello /* 11 bits */ 1377f07ec0fSandrea.merello res = 1; 1387f07ec0fSandrea.merello break; 1397f07ec0fSandrea.merello default: 1407f07ec0fSandrea.merello /* 12 bits */ 1417f07ec0fSandrea.merello res = 3; 1427f07ec0fSandrea.merello break; 1437f07ec0fSandrea.merello } 1447f07ec0fSandrea.merello 1457f07ec0fSandrea.merello if (priv->res == res) 1467f07ec0fSandrea.merello return 0; 1477f07ec0fSandrea.merello 1487f07ec0fSandrea.merello priv->config &= ~STTS751_CONF_RES_MASK; 1497f07ec0fSandrea.merello priv->config |= res << STTS751_CONF_RES_SHIFT; 1507f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting res %d. config %x", 1517f07ec0fSandrea.merello res, priv->config); 1527f07ec0fSandrea.merello priv->res = res; 1537f07ec0fSandrea.merello 1547f07ec0fSandrea.merello return i2c_smbus_write_byte_data(priv->client, 1557f07ec0fSandrea.merello STTS751_REG_CONF, priv->config); 1567f07ec0fSandrea.merello } 1577f07ec0fSandrea.merello 1587f07ec0fSandrea.merello static int stts751_update_temp(struct stts751_priv *priv) 1597f07ec0fSandrea.merello { 1607f07ec0fSandrea.merello s32 integer1, integer2, frac; 1617f07ec0fSandrea.merello 1627f07ec0fSandrea.merello /* 1637f07ec0fSandrea.merello * There is a trick here, like in the lm90 driver. We have to read two 1647f07ec0fSandrea.merello * registers to get the sensor temperature, but we have to beware a 1657f07ec0fSandrea.merello * conversion could occur between the readings. We could use the 1667f07ec0fSandrea.merello * one-shot conversion register, but we don't want to do this (disables 1677f07ec0fSandrea.merello * hardware monitoring). So the solution used here is to read the high 1687f07ec0fSandrea.merello * byte once, then the low byte, then the high byte again. If the new 1697f07ec0fSandrea.merello * high byte matches the old one, then we have a valid reading. Else we 1707f07ec0fSandrea.merello * have to read the low byte again, and now we believe we have a correct 1717f07ec0fSandrea.merello * reading. 1727f07ec0fSandrea.merello */ 1737f07ec0fSandrea.merello integer1 = i2c_smbus_read_byte_data(priv->client, STTS751_REG_TEMP_H); 1747f07ec0fSandrea.merello if (integer1 < 0) { 1757f07ec0fSandrea.merello dev_dbg(&priv->client->dev, 1767f07ec0fSandrea.merello "I2C read failed (temp H). ret: %x\n", integer1); 1777f07ec0fSandrea.merello return integer1; 1787f07ec0fSandrea.merello } 1797f07ec0fSandrea.merello 1807f07ec0fSandrea.merello frac = i2c_smbus_read_byte_data(priv->client, STTS751_REG_TEMP_L); 1817f07ec0fSandrea.merello if (frac < 0) { 1827f07ec0fSandrea.merello dev_dbg(&priv->client->dev, 1837f07ec0fSandrea.merello "I2C read failed (temp L). ret: %x\n", frac); 1847f07ec0fSandrea.merello return frac; 1857f07ec0fSandrea.merello } 1867f07ec0fSandrea.merello 1877f07ec0fSandrea.merello integer2 = i2c_smbus_read_byte_data(priv->client, STTS751_REG_TEMP_H); 1887f07ec0fSandrea.merello if (integer2 < 0) { 1897f07ec0fSandrea.merello dev_dbg(&priv->client->dev, 1907f07ec0fSandrea.merello "I2C 2nd read failed (temp H). ret: %x\n", integer2); 1917f07ec0fSandrea.merello return integer2; 1927f07ec0fSandrea.merello } 1937f07ec0fSandrea.merello 1947f07ec0fSandrea.merello if (integer1 != integer2) { 1957f07ec0fSandrea.merello frac = i2c_smbus_read_byte_data(priv->client, 1967f07ec0fSandrea.merello STTS751_REG_TEMP_L); 1977f07ec0fSandrea.merello if (frac < 0) { 1987f07ec0fSandrea.merello dev_dbg(&priv->client->dev, 1997f07ec0fSandrea.merello "I2C 2nd read failed (temp L). ret: %x\n", 2007f07ec0fSandrea.merello frac); 2017f07ec0fSandrea.merello return frac; 2027f07ec0fSandrea.merello } 2037f07ec0fSandrea.merello } 2047f07ec0fSandrea.merello 2057f07ec0fSandrea.merello priv->temp = stts751_to_deg((integer1 << 8) | frac); 2067f07ec0fSandrea.merello return 0; 2077f07ec0fSandrea.merello } 2087f07ec0fSandrea.merello 2097f07ec0fSandrea.merello static int stts751_set_temp_reg16(struct stts751_priv *priv, int temp, 2107f07ec0fSandrea.merello u8 hreg, u8 lreg) 2117f07ec0fSandrea.merello { 2127f07ec0fSandrea.merello s32 hwval; 2137f07ec0fSandrea.merello int ret; 2147f07ec0fSandrea.merello 2157f07ec0fSandrea.merello hwval = stts751_to_hw(temp); 2167f07ec0fSandrea.merello 2177f07ec0fSandrea.merello ret = i2c_smbus_write_byte_data(priv->client, hreg, hwval >> 8); 2187f07ec0fSandrea.merello if (ret) 2197f07ec0fSandrea.merello return ret; 2207f07ec0fSandrea.merello 2217f07ec0fSandrea.merello return i2c_smbus_write_byte_data(priv->client, lreg, hwval & 0xff); 2227f07ec0fSandrea.merello } 2237f07ec0fSandrea.merello 2247f07ec0fSandrea.merello static int stts751_set_temp_reg8(struct stts751_priv *priv, int temp, u8 reg) 2257f07ec0fSandrea.merello { 2267f07ec0fSandrea.merello s32 hwval; 2277f07ec0fSandrea.merello 2287f07ec0fSandrea.merello hwval = stts751_to_hw(temp); 2297f07ec0fSandrea.merello return i2c_smbus_write_byte_data(priv->client, reg, hwval >> 8); 2307f07ec0fSandrea.merello } 2317f07ec0fSandrea.merello 2327f07ec0fSandrea.merello static int stts751_read_reg16(struct stts751_priv *priv, int *temp, 2337f07ec0fSandrea.merello u8 hreg, u8 lreg) 2347f07ec0fSandrea.merello { 2357f07ec0fSandrea.merello int integer, frac; 2367f07ec0fSandrea.merello 2377f07ec0fSandrea.merello integer = i2c_smbus_read_byte_data(priv->client, hreg); 2387f07ec0fSandrea.merello if (integer < 0) 2397f07ec0fSandrea.merello return integer; 2407f07ec0fSandrea.merello 2417f07ec0fSandrea.merello frac = i2c_smbus_read_byte_data(priv->client, lreg); 2427f07ec0fSandrea.merello if (frac < 0) 2437f07ec0fSandrea.merello return frac; 2447f07ec0fSandrea.merello 2457f07ec0fSandrea.merello *temp = stts751_to_deg((integer << 8) | frac); 2467f07ec0fSandrea.merello 2477f07ec0fSandrea.merello return 0; 2487f07ec0fSandrea.merello } 2497f07ec0fSandrea.merello 2507f07ec0fSandrea.merello static int stts751_read_reg8(struct stts751_priv *priv, int *temp, u8 reg) 2517f07ec0fSandrea.merello { 2527f07ec0fSandrea.merello int integer; 2537f07ec0fSandrea.merello 2547f07ec0fSandrea.merello integer = i2c_smbus_read_byte_data(priv->client, reg); 2557f07ec0fSandrea.merello if (integer < 0) 2567f07ec0fSandrea.merello return integer; 2577f07ec0fSandrea.merello 2587f07ec0fSandrea.merello *temp = stts751_to_deg(integer << 8); 2597f07ec0fSandrea.merello 2607f07ec0fSandrea.merello return 0; 2617f07ec0fSandrea.merello } 2627f07ec0fSandrea.merello 2637f07ec0fSandrea.merello /* 2647f07ec0fSandrea.merello * Update alert flags without waiting for cache to expire. We detects alerts 2657f07ec0fSandrea.merello * immediately for the sake of the alert handler; we still need to deal with 2667f07ec0fSandrea.merello * caching to workaround the fact that alarm flags int the status register, 2677f07ec0fSandrea.merello * despite what the datasheet claims, gets always cleared on read. 2687f07ec0fSandrea.merello */ 2697f07ec0fSandrea.merello static int stts751_update_alert(struct stts751_priv *priv) 2707f07ec0fSandrea.merello { 2717f07ec0fSandrea.merello int ret; 2727f07ec0fSandrea.merello bool conv_done; 2737f07ec0fSandrea.merello int cache_time = msecs_to_jiffies(stts751_intervals[priv->interval]); 2747f07ec0fSandrea.merello 2757f07ec0fSandrea.merello /* 2767f07ec0fSandrea.merello * Add another 10% because if we run faster than the HW conversion 2777f07ec0fSandrea.merello * rate we will end up in reporting incorrectly alarms. 2787f07ec0fSandrea.merello */ 2797f07ec0fSandrea.merello cache_time += cache_time / 10; 2807f07ec0fSandrea.merello 2817f07ec0fSandrea.merello ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_STATUS); 2827f07ec0fSandrea.merello if (ret < 0) 2837f07ec0fSandrea.merello return ret; 2847f07ec0fSandrea.merello 2857f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "status reg %x\n", ret); 2867f07ec0fSandrea.merello conv_done = ret & (STTS751_STATUS_TRIPH | STTS751_STATUS_TRIPL); 2877f07ec0fSandrea.merello /* 2887f07ec0fSandrea.merello * Reset the cache if the cache time expired, or if we are sure 2897f07ec0fSandrea.merello * we have valid data from a device conversion, or if we know 2907f07ec0fSandrea.merello * our cache has been never written. 2917f07ec0fSandrea.merello * 2927f07ec0fSandrea.merello * Note that when the cache has been never written the point is 2937f07ec0fSandrea.merello * to correctly initialize the timestamp, rather than clearing 2947f07ec0fSandrea.merello * the cache values. 2957f07ec0fSandrea.merello * 2967f07ec0fSandrea.merello * Note that updating the cache timestamp when we get an alarm flag 2977f07ec0fSandrea.merello * is required, otherwise we could incorrectly report alarms to be zero. 2987f07ec0fSandrea.merello */ 2997f07ec0fSandrea.merello if (time_after(jiffies, priv->last_alert_update + cache_time) || 3007f07ec0fSandrea.merello conv_done || !priv->alert_valid) { 3017f07ec0fSandrea.merello priv->max_alert = false; 3027f07ec0fSandrea.merello priv->min_alert = false; 3037f07ec0fSandrea.merello priv->alert_valid = true; 3047f07ec0fSandrea.merello priv->last_alert_update = jiffies; 3057f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "invalidating alert cache\n"); 3067f07ec0fSandrea.merello } 3077f07ec0fSandrea.merello 3087f07ec0fSandrea.merello priv->max_alert |= !!(ret & STTS751_STATUS_TRIPH); 3097f07ec0fSandrea.merello priv->min_alert |= !!(ret & STTS751_STATUS_TRIPL); 3107f07ec0fSandrea.merello priv->therm_trip = !!(ret & STTS751_STATUS_TRIPT); 3117f07ec0fSandrea.merello 3127f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "max_alert: %d, min_alert: %d, therm_trip: %d\n", 3137f07ec0fSandrea.merello priv->max_alert, priv->min_alert, priv->therm_trip); 3147f07ec0fSandrea.merello 3157f07ec0fSandrea.merello return 0; 3167f07ec0fSandrea.merello } 3177f07ec0fSandrea.merello 3187f07ec0fSandrea.merello static void stts751_alert(struct i2c_client *client, 3197f07ec0fSandrea.merello enum i2c_alert_protocol type, unsigned int data) 3207f07ec0fSandrea.merello { 3217f07ec0fSandrea.merello int ret; 3227f07ec0fSandrea.merello struct stts751_priv *priv = i2c_get_clientdata(client); 3237f07ec0fSandrea.merello 3247f07ec0fSandrea.merello if (type != I2C_PROTOCOL_SMBUS_ALERT) 3257f07ec0fSandrea.merello return; 3267f07ec0fSandrea.merello 3277f07ec0fSandrea.merello dev_dbg(&client->dev, "alert!"); 3287f07ec0fSandrea.merello 3297f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 3307f07ec0fSandrea.merello ret = stts751_update_alert(priv); 3317f07ec0fSandrea.merello if (ret < 0) { 3327f07ec0fSandrea.merello /* default to worst case */ 3337f07ec0fSandrea.merello priv->max_alert = true; 3347f07ec0fSandrea.merello priv->min_alert = true; 3357f07ec0fSandrea.merello 3367f07ec0fSandrea.merello dev_warn(priv->dev, 3377f07ec0fSandrea.merello "Alert received, but can't communicate to the device. Triggering all alarms!"); 3387f07ec0fSandrea.merello } 3397f07ec0fSandrea.merello 3407f07ec0fSandrea.merello if (priv->max_alert) { 3417f07ec0fSandrea.merello if (priv->notify_max) 3427f07ec0fSandrea.merello dev_notice(priv->dev, "got alert for HIGH temperature"); 3437f07ec0fSandrea.merello priv->notify_max = false; 3447f07ec0fSandrea.merello 3457f07ec0fSandrea.merello /* unblock alert poll */ 3467f07ec0fSandrea.merello sysfs_notify(&priv->dev->kobj, NULL, "temp1_max_alarm"); 3477f07ec0fSandrea.merello } 3487f07ec0fSandrea.merello 3497f07ec0fSandrea.merello if (priv->min_alert) { 3507f07ec0fSandrea.merello if (priv->notify_min) 3517f07ec0fSandrea.merello dev_notice(priv->dev, "got alert for LOW temperature"); 3527f07ec0fSandrea.merello priv->notify_min = false; 3537f07ec0fSandrea.merello 3547f07ec0fSandrea.merello /* unblock alert poll */ 3557f07ec0fSandrea.merello sysfs_notify(&priv->dev->kobj, NULL, "temp1_min_alarm"); 3567f07ec0fSandrea.merello } 3577f07ec0fSandrea.merello 3587f07ec0fSandrea.merello if (priv->min_alert || priv->max_alert) 3597f07ec0fSandrea.merello kobject_uevent(&priv->dev->kobj, KOBJ_CHANGE); 3607f07ec0fSandrea.merello 3617f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 3627f07ec0fSandrea.merello } 3637f07ec0fSandrea.merello 3647f07ec0fSandrea.merello static int stts751_update(struct stts751_priv *priv) 3657f07ec0fSandrea.merello { 3667f07ec0fSandrea.merello int ret; 3677f07ec0fSandrea.merello int cache_time = msecs_to_jiffies(stts751_intervals[priv->interval]); 3687f07ec0fSandrea.merello 3697f07ec0fSandrea.merello if (time_after(jiffies, priv->last_update + cache_time) || 3707f07ec0fSandrea.merello !priv->data_valid) { 3717f07ec0fSandrea.merello ret = stts751_update_temp(priv); 3727f07ec0fSandrea.merello if (ret) 3737f07ec0fSandrea.merello return ret; 3747f07ec0fSandrea.merello 3757f07ec0fSandrea.merello ret = stts751_update_alert(priv); 3767f07ec0fSandrea.merello if (ret) 3777f07ec0fSandrea.merello return ret; 3787f07ec0fSandrea.merello priv->data_valid = true; 3797f07ec0fSandrea.merello priv->last_update = jiffies; 3807f07ec0fSandrea.merello } 3817f07ec0fSandrea.merello 3827f07ec0fSandrea.merello return 0; 3837f07ec0fSandrea.merello } 3847f07ec0fSandrea.merello 3857f07ec0fSandrea.merello static ssize_t show_max_alarm(struct device *dev, struct device_attribute *attr, 3867f07ec0fSandrea.merello char *buf) 3877f07ec0fSandrea.merello { 3887f07ec0fSandrea.merello int ret; 3897f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 3907f07ec0fSandrea.merello 3917f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 3927f07ec0fSandrea.merello ret = stts751_update(priv); 3937f07ec0fSandrea.merello if (!ret) 3947f07ec0fSandrea.merello priv->notify_max = true; 3957f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 3967f07ec0fSandrea.merello if (ret < 0) 3977f07ec0fSandrea.merello return ret; 3987f07ec0fSandrea.merello 3997f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->max_alert); 4007f07ec0fSandrea.merello } 4017f07ec0fSandrea.merello 4027f07ec0fSandrea.merello static ssize_t show_min_alarm(struct device *dev, struct device_attribute *attr, 4037f07ec0fSandrea.merello char *buf) 4047f07ec0fSandrea.merello { 4057f07ec0fSandrea.merello int ret; 4067f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4077f07ec0fSandrea.merello 4087f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 4097f07ec0fSandrea.merello ret = stts751_update(priv); 4107f07ec0fSandrea.merello if (!ret) 4117f07ec0fSandrea.merello priv->notify_min = true; 4127f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 4137f07ec0fSandrea.merello if (ret < 0) 4147f07ec0fSandrea.merello return ret; 4157f07ec0fSandrea.merello 4167f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->min_alert); 4177f07ec0fSandrea.merello } 4187f07ec0fSandrea.merello 4197f07ec0fSandrea.merello static ssize_t show_input(struct device *dev, struct device_attribute *attr, 4207f07ec0fSandrea.merello char *buf) 4217f07ec0fSandrea.merello { 4227f07ec0fSandrea.merello int ret; 4237f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4247f07ec0fSandrea.merello 4257f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 4267f07ec0fSandrea.merello ret = stts751_update(priv); 4277f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 4287f07ec0fSandrea.merello if (ret < 0) 4297f07ec0fSandrea.merello return ret; 4307f07ec0fSandrea.merello 4317f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->temp); 4327f07ec0fSandrea.merello } 4337f07ec0fSandrea.merello 4347f07ec0fSandrea.merello static ssize_t show_therm(struct device *dev, struct device_attribute *attr, 4357f07ec0fSandrea.merello char *buf) 4367f07ec0fSandrea.merello { 4377f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4387f07ec0fSandrea.merello 4397f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->therm); 4407f07ec0fSandrea.merello } 4417f07ec0fSandrea.merello 4427f07ec0fSandrea.merello static ssize_t set_therm(struct device *dev, struct device_attribute *attr, 4437f07ec0fSandrea.merello const char *buf, size_t count) 4447f07ec0fSandrea.merello { 4457f07ec0fSandrea.merello int ret; 4467f07ec0fSandrea.merello long temp; 4477f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4487f07ec0fSandrea.merello 4497f07ec0fSandrea.merello if (kstrtol(buf, 10, &temp) < 0) 4507f07ec0fSandrea.merello return -EINVAL; 4517f07ec0fSandrea.merello 4527f07ec0fSandrea.merello /* HW works in range -64C to +127.937C */ 4537f07ec0fSandrea.merello temp = clamp_val(temp, -64000, 127937); 4547f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 4557f07ec0fSandrea.merello ret = stts751_set_temp_reg8(priv, temp, STTS751_REG_TLIM); 4567f07ec0fSandrea.merello if (ret) 4577f07ec0fSandrea.merello goto exit; 4587f07ec0fSandrea.merello 4597f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting therm %ld", temp); 4607f07ec0fSandrea.merello 4617f07ec0fSandrea.merello /* 4627f07ec0fSandrea.merello * hysteresis reg is relative to therm, so the HW does not need to be 4637f07ec0fSandrea.merello * adjusted, we need to update our local copy only. 4647f07ec0fSandrea.merello */ 4657f07ec0fSandrea.merello priv->hyst = temp - (priv->therm - priv->hyst); 4667f07ec0fSandrea.merello priv->therm = temp; 4677f07ec0fSandrea.merello 4687f07ec0fSandrea.merello exit: 4697f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 4707f07ec0fSandrea.merello if (ret) 4717f07ec0fSandrea.merello return ret; 4727f07ec0fSandrea.merello 4737f07ec0fSandrea.merello return count; 4747f07ec0fSandrea.merello } 4757f07ec0fSandrea.merello 4767f07ec0fSandrea.merello static ssize_t show_hyst(struct device *dev, struct device_attribute *attr, 4777f07ec0fSandrea.merello char *buf) 4787f07ec0fSandrea.merello { 4797f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4807f07ec0fSandrea.merello 4817f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->hyst); 4827f07ec0fSandrea.merello } 4837f07ec0fSandrea.merello 4847f07ec0fSandrea.merello static ssize_t set_hyst(struct device *dev, struct device_attribute *attr, 4857f07ec0fSandrea.merello const char *buf, size_t count) 4867f07ec0fSandrea.merello { 4877f07ec0fSandrea.merello int ret; 4887f07ec0fSandrea.merello long temp; 4897f07ec0fSandrea.merello 4907f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 4917f07ec0fSandrea.merello 4927f07ec0fSandrea.merello if (kstrtol(buf, 10, &temp) < 0) 4937f07ec0fSandrea.merello return -EINVAL; 4947f07ec0fSandrea.merello 4957f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 4967f07ec0fSandrea.merello /* HW works in range -64C to +127.937C */ 4977f07ec0fSandrea.merello temp = clamp_val(temp, -64000, priv->therm); 4987f07ec0fSandrea.merello priv->hyst = temp; 4997f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting hyst %ld", temp); 5007f07ec0fSandrea.merello temp = priv->therm - temp; 5017f07ec0fSandrea.merello ret = stts751_set_temp_reg8(priv, temp, STTS751_REG_HYST); 5027f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 5037f07ec0fSandrea.merello if (ret) 5047f07ec0fSandrea.merello return ret; 5057f07ec0fSandrea.merello 5067f07ec0fSandrea.merello return count; 5077f07ec0fSandrea.merello } 5087f07ec0fSandrea.merello 5097f07ec0fSandrea.merello static ssize_t show_therm_trip(struct device *dev, 5107f07ec0fSandrea.merello struct device_attribute *attr, char *buf) 5117f07ec0fSandrea.merello { 5127f07ec0fSandrea.merello int ret; 5137f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5147f07ec0fSandrea.merello 5157f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 5167f07ec0fSandrea.merello ret = stts751_update(priv); 5177f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 5187f07ec0fSandrea.merello if (ret < 0) 5197f07ec0fSandrea.merello return ret; 5207f07ec0fSandrea.merello 5217f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->therm_trip); 5227f07ec0fSandrea.merello } 5237f07ec0fSandrea.merello 5247f07ec0fSandrea.merello static ssize_t show_max(struct device *dev, struct device_attribute *attr, 5257f07ec0fSandrea.merello char *buf) 5267f07ec0fSandrea.merello { 5277f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5287f07ec0fSandrea.merello 5297f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->event_max); 5307f07ec0fSandrea.merello } 5317f07ec0fSandrea.merello 5327f07ec0fSandrea.merello static ssize_t set_max(struct device *dev, struct device_attribute *attr, 5337f07ec0fSandrea.merello const char *buf, size_t count) 5347f07ec0fSandrea.merello { 5357f07ec0fSandrea.merello int ret; 5367f07ec0fSandrea.merello long temp; 5377f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5387f07ec0fSandrea.merello 5397f07ec0fSandrea.merello if (kstrtol(buf, 10, &temp) < 0) 5407f07ec0fSandrea.merello return -EINVAL; 5417f07ec0fSandrea.merello 5427f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 5437f07ec0fSandrea.merello /* HW works in range -64C to +127.937C */ 5447f07ec0fSandrea.merello temp = clamp_val(temp, priv->event_min, 127937); 5457f07ec0fSandrea.merello ret = stts751_set_temp_reg16(priv, temp, 5467f07ec0fSandrea.merello STTS751_REG_HLIM_H, STTS751_REG_HLIM_L); 5477f07ec0fSandrea.merello if (ret) 5487f07ec0fSandrea.merello goto exit; 5497f07ec0fSandrea.merello 5507f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting event max %ld", temp); 5517f07ec0fSandrea.merello priv->event_max = temp; 5527f07ec0fSandrea.merello ret = count; 5537f07ec0fSandrea.merello exit: 5547f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 5557f07ec0fSandrea.merello return ret; 5567f07ec0fSandrea.merello } 5577f07ec0fSandrea.merello 5587f07ec0fSandrea.merello static ssize_t show_min(struct device *dev, struct device_attribute *attr, 5597f07ec0fSandrea.merello char *buf) 5607f07ec0fSandrea.merello { 5617f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5627f07ec0fSandrea.merello 5637f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", priv->event_min); 5647f07ec0fSandrea.merello } 5657f07ec0fSandrea.merello 5667f07ec0fSandrea.merello static ssize_t set_min(struct device *dev, struct device_attribute *attr, 5677f07ec0fSandrea.merello const char *buf, size_t count) 5687f07ec0fSandrea.merello { 5697f07ec0fSandrea.merello int ret; 5707f07ec0fSandrea.merello long temp; 5717f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5727f07ec0fSandrea.merello 5737f07ec0fSandrea.merello if (kstrtol(buf, 10, &temp) < 0) 5747f07ec0fSandrea.merello return -EINVAL; 5757f07ec0fSandrea.merello 5767f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 5777f07ec0fSandrea.merello /* HW works in range -64C to +127.937C */ 5787f07ec0fSandrea.merello temp = clamp_val(temp, -64000, priv->event_max); 5797f07ec0fSandrea.merello ret = stts751_set_temp_reg16(priv, temp, 5807f07ec0fSandrea.merello STTS751_REG_LLIM_H, STTS751_REG_LLIM_L); 5817f07ec0fSandrea.merello if (ret) 5827f07ec0fSandrea.merello goto exit; 5837f07ec0fSandrea.merello 5847f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting event min %ld", temp); 5857f07ec0fSandrea.merello priv->event_min = temp; 5867f07ec0fSandrea.merello ret = count; 5877f07ec0fSandrea.merello exit: 5887f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 5897f07ec0fSandrea.merello return ret; 5907f07ec0fSandrea.merello } 5917f07ec0fSandrea.merello 5927f07ec0fSandrea.merello static ssize_t show_interval(struct device *dev, struct device_attribute *attr, 5937f07ec0fSandrea.merello char *buf) 5947f07ec0fSandrea.merello { 5957f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 5967f07ec0fSandrea.merello 5977f07ec0fSandrea.merello return snprintf(buf, PAGE_SIZE - 1, "%d\n", 5987f07ec0fSandrea.merello stts751_intervals[priv->interval]); 5997f07ec0fSandrea.merello } 6007f07ec0fSandrea.merello 6017f07ec0fSandrea.merello static ssize_t set_interval(struct device *dev, struct device_attribute *attr, 6027f07ec0fSandrea.merello const char *buf, size_t count) 6037f07ec0fSandrea.merello { 6047f07ec0fSandrea.merello unsigned long val; 6057f07ec0fSandrea.merello int idx; 6067f07ec0fSandrea.merello int ret = count; 6077f07ec0fSandrea.merello struct stts751_priv *priv = dev_get_drvdata(dev); 6087f07ec0fSandrea.merello 6097f07ec0fSandrea.merello if (kstrtoul(buf, 10, &val) < 0) 6107f07ec0fSandrea.merello return -EINVAL; 6117f07ec0fSandrea.merello 6127f07ec0fSandrea.merello idx = find_closest_descending(val, stts751_intervals, 6137f07ec0fSandrea.merello ARRAY_SIZE(stts751_intervals)); 6147f07ec0fSandrea.merello 6157f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "setting interval. req:%lu, idx: %d, val: %d", 6167f07ec0fSandrea.merello val, idx, stts751_intervals[idx]); 6177f07ec0fSandrea.merello 6187f07ec0fSandrea.merello mutex_lock(&priv->access_lock); 6197f07ec0fSandrea.merello if (priv->interval == idx) 6207f07ec0fSandrea.merello goto exit; 6217f07ec0fSandrea.merello 6227f07ec0fSandrea.merello /* 6237f07ec0fSandrea.merello * In early development stages I've become suspicious about the chip 6247f07ec0fSandrea.merello * starting to misbehave if I ever set, even briefly, an invalid 6257f07ec0fSandrea.merello * configuration. While I'm not sure this is really needed, be 6267f07ec0fSandrea.merello * conservative and set rate/resolution in such an order that avoids 6277f07ec0fSandrea.merello * passing through an invalid configuration. 6287f07ec0fSandrea.merello */ 6297f07ec0fSandrea.merello 6307f07ec0fSandrea.merello /* speed up: lower the resolution, then modify convrate */ 6317f07ec0fSandrea.merello if (priv->interval < idx) { 6327f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "lower resolution, then modify convrate"); 6337f07ec0fSandrea.merello priv->interval = idx; 6347f07ec0fSandrea.merello ret = stts751_adjust_resolution(priv); 6357f07ec0fSandrea.merello if (ret) 6367f07ec0fSandrea.merello goto exit; 6377f07ec0fSandrea.merello } 6387f07ec0fSandrea.merello 6397f07ec0fSandrea.merello ret = i2c_smbus_write_byte_data(priv->client, STTS751_REG_RATE, idx); 6407f07ec0fSandrea.merello if (ret) 6417f07ec0fSandrea.merello goto exit; 6427f07ec0fSandrea.merello /* slow down: modify convrate, then raise resolution */ 6437f07ec0fSandrea.merello if (priv->interval != idx) { 6447f07ec0fSandrea.merello dev_dbg(&priv->client->dev, "modify convrate, then raise resolution"); 6457f07ec0fSandrea.merello priv->interval = idx; 6467f07ec0fSandrea.merello ret = stts751_adjust_resolution(priv); 6477f07ec0fSandrea.merello if (ret) 6487f07ec0fSandrea.merello goto exit; 6497f07ec0fSandrea.merello } 6507f07ec0fSandrea.merello ret = count; 6517f07ec0fSandrea.merello exit: 6527f07ec0fSandrea.merello mutex_unlock(&priv->access_lock); 6537f07ec0fSandrea.merello 6547f07ec0fSandrea.merello return ret; 6557f07ec0fSandrea.merello } 6567f07ec0fSandrea.merello 6577f07ec0fSandrea.merello static int stts751_detect(struct i2c_client *new_client, 6587f07ec0fSandrea.merello struct i2c_board_info *info) 6597f07ec0fSandrea.merello { 6607f07ec0fSandrea.merello struct i2c_adapter *adapter = new_client->adapter; 6617f07ec0fSandrea.merello const char *name; 6627f07ec0fSandrea.merello int tmp; 6637f07ec0fSandrea.merello 6647f07ec0fSandrea.merello if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 6657f07ec0fSandrea.merello return -ENODEV; 6667f07ec0fSandrea.merello 6677f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_MAN_ID); 6687f07ec0fSandrea.merello if (tmp != ST_MAN_ID) 6697f07ec0fSandrea.merello return -ENODEV; 6707f07ec0fSandrea.merello 6717f07ec0fSandrea.merello /* lower temperaure registers always have bits 0-3 set to zero */ 6727f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_TEMP_L); 6737f07ec0fSandrea.merello if (tmp & 0xf) 6747f07ec0fSandrea.merello return -ENODEV; 6757f07ec0fSandrea.merello 6767f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_HLIM_L); 6777f07ec0fSandrea.merello if (tmp & 0xf) 6787f07ec0fSandrea.merello return -ENODEV; 6797f07ec0fSandrea.merello 6807f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_LLIM_L); 6817f07ec0fSandrea.merello if (tmp & 0xf) 6827f07ec0fSandrea.merello return -ENODEV; 6837f07ec0fSandrea.merello 6847f07ec0fSandrea.merello /* smbus timeout register always have bits 0-7 set to zero */ 6857f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_SMBUS_TO); 6867f07ec0fSandrea.merello if (tmp & 0x7f) 6877f07ec0fSandrea.merello return -ENODEV; 6887f07ec0fSandrea.merello 6897f07ec0fSandrea.merello tmp = i2c_smbus_read_byte_data(new_client, STTS751_REG_PROD_ID); 6907f07ec0fSandrea.merello 6917f07ec0fSandrea.merello switch (tmp) { 6927f07ec0fSandrea.merello case STTS751_0_PROD_ID: 6937f07ec0fSandrea.merello name = "STTS751-0"; 6947f07ec0fSandrea.merello break; 6957f07ec0fSandrea.merello case STTS751_1_PROD_ID: 6967f07ec0fSandrea.merello name = "STTS751-1"; 6977f07ec0fSandrea.merello break; 6987f07ec0fSandrea.merello default: 6997f07ec0fSandrea.merello return -ENODEV; 7007f07ec0fSandrea.merello } 7017f07ec0fSandrea.merello dev_dbg(&new_client->dev, "Chip %s detected", name); 7027f07ec0fSandrea.merello 7037f07ec0fSandrea.merello strlcpy(info->type, stts751_id[0].name, I2C_NAME_SIZE); 7047f07ec0fSandrea.merello return 0; 7057f07ec0fSandrea.merello } 7067f07ec0fSandrea.merello 7077f07ec0fSandrea.merello static int stts751_read_chip_config(struct stts751_priv *priv) 7087f07ec0fSandrea.merello { 7097f07ec0fSandrea.merello int ret; 7107f07ec0fSandrea.merello int tmp; 7117f07ec0fSandrea.merello 7127f07ec0fSandrea.merello ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_CONF); 7137f07ec0fSandrea.merello if (ret < 0) 7147f07ec0fSandrea.merello return ret; 7157f07ec0fSandrea.merello priv->config = ret; 7167f07ec0fSandrea.merello priv->res = (ret & STTS751_CONF_RES_MASK) >> STTS751_CONF_RES_SHIFT; 7177f07ec0fSandrea.merello 7187f07ec0fSandrea.merello ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); 7197f07ec0fSandrea.merello if (ret < 0) 7207f07ec0fSandrea.merello return ret; 7213be6bd69SAnton Vasilyev if (ret >= ARRAY_SIZE(stts751_intervals)) { 7223be6bd69SAnton Vasilyev dev_err(priv->dev, "Unrecognized conversion rate 0x%x\n", ret); 7233be6bd69SAnton Vasilyev return -ENODEV; 7243be6bd69SAnton Vasilyev } 7257f07ec0fSandrea.merello priv->interval = ret; 7267f07ec0fSandrea.merello 7277f07ec0fSandrea.merello ret = stts751_read_reg16(priv, &priv->event_max, 7287f07ec0fSandrea.merello STTS751_REG_HLIM_H, STTS751_REG_HLIM_L); 7297f07ec0fSandrea.merello if (ret) 7307f07ec0fSandrea.merello return ret; 7317f07ec0fSandrea.merello 7327f07ec0fSandrea.merello ret = stts751_read_reg16(priv, &priv->event_min, 7337f07ec0fSandrea.merello STTS751_REG_LLIM_H, STTS751_REG_LLIM_L); 7347f07ec0fSandrea.merello if (ret) 7357f07ec0fSandrea.merello return ret; 7367f07ec0fSandrea.merello 7377f07ec0fSandrea.merello ret = stts751_read_reg8(priv, &priv->therm, STTS751_REG_TLIM); 7387f07ec0fSandrea.merello if (ret) 7397f07ec0fSandrea.merello return ret; 7407f07ec0fSandrea.merello 7417f07ec0fSandrea.merello ret = stts751_read_reg8(priv, &tmp, STTS751_REG_HYST); 7427f07ec0fSandrea.merello if (ret) 7437f07ec0fSandrea.merello return ret; 7447f07ec0fSandrea.merello priv->hyst = priv->therm - tmp; 7457f07ec0fSandrea.merello 7467f07ec0fSandrea.merello return 0; 7477f07ec0fSandrea.merello } 7487f07ec0fSandrea.merello 7497f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_input, NULL, 0); 7507f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_min, 0644, show_min, set_min, 0); 7517f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_max, 0644, show_max, set_max, 0); 7527f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_min_alarm, 0444, show_min_alarm, NULL, 0); 7537f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_max_alarm, 0444, show_max_alarm, NULL, 0); 7547f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_crit, 0644, show_therm, set_therm, 0); 7557f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_crit_hyst, 0644, show_hyst, set_hyst, 0); 7567f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(temp1_crit_alarm, 0444, show_therm_trip, NULL, 0); 7577f07ec0fSandrea.merello static SENSOR_DEVICE_ATTR(update_interval, 0644, 7587f07ec0fSandrea.merello show_interval, set_interval, 0); 7597f07ec0fSandrea.merello 7607f07ec0fSandrea.merello static struct attribute *stts751_attrs[] = { 7617f07ec0fSandrea.merello &sensor_dev_attr_temp1_input.dev_attr.attr, 7627f07ec0fSandrea.merello &sensor_dev_attr_temp1_min.dev_attr.attr, 7637f07ec0fSandrea.merello &sensor_dev_attr_temp1_max.dev_attr.attr, 7647f07ec0fSandrea.merello &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 7657f07ec0fSandrea.merello &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 7667f07ec0fSandrea.merello &sensor_dev_attr_temp1_crit.dev_attr.attr, 7677f07ec0fSandrea.merello &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 7687f07ec0fSandrea.merello &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 7697f07ec0fSandrea.merello &sensor_dev_attr_update_interval.dev_attr.attr, 7707f07ec0fSandrea.merello NULL 7717f07ec0fSandrea.merello }; 7727f07ec0fSandrea.merello ATTRIBUTE_GROUPS(stts751); 7737f07ec0fSandrea.merello 7747f07ec0fSandrea.merello static int stts751_probe(struct i2c_client *client, 7757f07ec0fSandrea.merello const struct i2c_device_id *id) 7767f07ec0fSandrea.merello { 7777f07ec0fSandrea.merello struct stts751_priv *priv; 7787f07ec0fSandrea.merello int ret; 7797f07ec0fSandrea.merello bool smbus_nto; 7807f07ec0fSandrea.merello int rev_id; 7817f07ec0fSandrea.merello 7827f07ec0fSandrea.merello priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 7837f07ec0fSandrea.merello if (!priv) 7847f07ec0fSandrea.merello return -ENOMEM; 7857f07ec0fSandrea.merello 7867f07ec0fSandrea.merello priv->client = client; 7877f07ec0fSandrea.merello priv->notify_max = true; 7887f07ec0fSandrea.merello priv->notify_min = true; 7897f07ec0fSandrea.merello i2c_set_clientdata(client, priv); 7907f07ec0fSandrea.merello mutex_init(&priv->access_lock); 7917f07ec0fSandrea.merello 7927f07ec0fSandrea.merello if (device_property_present(&client->dev, 7937f07ec0fSandrea.merello "smbus-timeout-disable")) { 7947f07ec0fSandrea.merello smbus_nto = device_property_read_bool(&client->dev, 7957f07ec0fSandrea.merello "smbus-timeout-disable"); 7967f07ec0fSandrea.merello 7977f07ec0fSandrea.merello ret = i2c_smbus_write_byte_data(client, STTS751_REG_SMBUS_TO, 7987f07ec0fSandrea.merello smbus_nto ? 0 : 0x80); 7997f07ec0fSandrea.merello if (ret) 8007f07ec0fSandrea.merello return ret; 8017f07ec0fSandrea.merello } 8027f07ec0fSandrea.merello 8037f07ec0fSandrea.merello rev_id = i2c_smbus_read_byte_data(client, STTS751_REG_REV_ID); 8047f07ec0fSandrea.merello if (rev_id < 0) 8057f07ec0fSandrea.merello return -ENODEV; 8067f07ec0fSandrea.merello if (rev_id != 0x1) { 8077f07ec0fSandrea.merello dev_dbg(&client->dev, "Chip revision 0x%x is untested\n", 8087f07ec0fSandrea.merello rev_id); 8097f07ec0fSandrea.merello } 8107f07ec0fSandrea.merello 8117f07ec0fSandrea.merello ret = stts751_read_chip_config(priv); 8127f07ec0fSandrea.merello if (ret) 8137f07ec0fSandrea.merello return ret; 8147f07ec0fSandrea.merello 8157f07ec0fSandrea.merello priv->config &= ~(STTS751_CONF_STOP | STTS751_CONF_EVENT_DIS); 8167f07ec0fSandrea.merello ret = i2c_smbus_write_byte_data(client, STTS751_REG_CONF, priv->config); 8177f07ec0fSandrea.merello if (ret) 8187f07ec0fSandrea.merello return ret; 8197f07ec0fSandrea.merello 8207f07ec0fSandrea.merello priv->dev = devm_hwmon_device_register_with_groups(&client->dev, 8217f07ec0fSandrea.merello client->name, priv, 8227f07ec0fSandrea.merello stts751_groups); 8237f07ec0fSandrea.merello return PTR_ERR_OR_ZERO(priv->dev); 8247f07ec0fSandrea.merello } 8257f07ec0fSandrea.merello 8267f07ec0fSandrea.merello MODULE_DEVICE_TABLE(i2c, stts751_id); 8277f07ec0fSandrea.merello 8287f07ec0fSandrea.merello static struct i2c_driver stts751_driver = { 8297f07ec0fSandrea.merello .class = I2C_CLASS_HWMON, 8307f07ec0fSandrea.merello .driver = { 8317f07ec0fSandrea.merello .name = DEVNAME, 8321c1a7b75SJavier Martinez Canillas .of_match_table = of_match_ptr(stts751_of_match), 8337f07ec0fSandrea.merello }, 8347f07ec0fSandrea.merello .probe = stts751_probe, 8357f07ec0fSandrea.merello .id_table = stts751_id, 8367f07ec0fSandrea.merello .detect = stts751_detect, 8377f07ec0fSandrea.merello .alert = stts751_alert, 8387f07ec0fSandrea.merello .address_list = normal_i2c, 8397f07ec0fSandrea.merello }; 8407f07ec0fSandrea.merello 8417f07ec0fSandrea.merello module_i2c_driver(stts751_driver); 8427f07ec0fSandrea.merello 8437f07ec0fSandrea.merello MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>"); 8447f07ec0fSandrea.merello MODULE_DESCRIPTION("STTS751 sensor driver"); 8457f07ec0fSandrea.merello MODULE_LICENSE("GPL"); 846