1cff37c9eSJean Delvare /* Texas Instruments TMP102 SMBus temperature sensor driver 2beb1b6bbSSteven King * 3cff37c9eSJean Delvare * Copyright (C) 2010 Steven King <sfking@fdwdc.com> 4beb1b6bbSSteven King * 5beb1b6bbSSteven King * This program is free software; you can redistribute it and/or modify 6beb1b6bbSSteven King * it under the terms of the GNU General Public License as published by 7beb1b6bbSSteven King * the Free Software Foundation; either version 2 of the License, or 8beb1b6bbSSteven King * (at your option) any later version. 9beb1b6bbSSteven King * 10beb1b6bbSSteven King * This program is distributed in the hope that it will be useful, 11beb1b6bbSSteven King * but WITHOUT ANY WARRANTY; without even the implied warranty of 12beb1b6bbSSteven King * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13beb1b6bbSSteven King * GNU General Public License for more details. 14beb1b6bbSSteven King */ 15beb1b6bbSSteven King 16*3d8f7a89SGuenter Roeck #include <linux/delay.h> 17beb1b6bbSSteven King #include <linux/module.h> 18beb1b6bbSSteven King #include <linux/init.h> 19beb1b6bbSSteven King #include <linux/slab.h> 20beb1b6bbSSteven King #include <linux/i2c.h> 21beb1b6bbSSteven King #include <linux/hwmon.h> 22beb1b6bbSSteven King #include <linux/hwmon-sysfs.h> 23beb1b6bbSSteven King #include <linux/err.h> 24beb1b6bbSSteven King #include <linux/mutex.h> 25cff37c9eSJean Delvare #include <linux/device.h> 26dcd8f392SJean Delvare #include <linux/jiffies.h> 276a027523SEduardo Valentin #include <linux/thermal.h> 286a027523SEduardo Valentin #include <linux/of.h> 29beb1b6bbSSteven King 30beb1b6bbSSteven King #define DRIVER_NAME "tmp102" 31beb1b6bbSSteven King 32beb1b6bbSSteven King #define TMP102_TEMP_REG 0x00 33beb1b6bbSSteven King #define TMP102_CONF_REG 0x01 34beb1b6bbSSteven King /* note: these bit definitions are byte swapped */ 35beb1b6bbSSteven King #define TMP102_CONF_SD 0x0100 36beb1b6bbSSteven King #define TMP102_CONF_TM 0x0200 37beb1b6bbSSteven King #define TMP102_CONF_POL 0x0400 38beb1b6bbSSteven King #define TMP102_CONF_F0 0x0800 39beb1b6bbSSteven King #define TMP102_CONF_F1 0x1000 40beb1b6bbSSteven King #define TMP102_CONF_R0 0x2000 41beb1b6bbSSteven King #define TMP102_CONF_R1 0x4000 42beb1b6bbSSteven King #define TMP102_CONF_OS 0x8000 43beb1b6bbSSteven King #define TMP102_CONF_EM 0x0010 44beb1b6bbSSteven King #define TMP102_CONF_AL 0x0020 45beb1b6bbSSteven King #define TMP102_CONF_CR0 0x0040 46beb1b6bbSSteven King #define TMP102_CONF_CR1 0x0080 47beb1b6bbSSteven King #define TMP102_TLOW_REG 0x02 48beb1b6bbSSteven King #define TMP102_THIGH_REG 0x03 49beb1b6bbSSteven King 50*3d8f7a89SGuenter Roeck #define CONVERSION_TIME_MS 35 /* in milli-seconds */ 51*3d8f7a89SGuenter Roeck 52beb1b6bbSSteven King struct tmp102 { 53ad9beea4SGuenter Roeck struct i2c_client *client; 54beb1b6bbSSteven King struct mutex lock; 5538806bdaSJean Delvare u16 config_orig; 56beb1b6bbSSteven King unsigned long last_update; 57*3d8f7a89SGuenter Roeck unsigned long ready_time; 58*3d8f7a89SGuenter Roeck bool valid; 59beb1b6bbSSteven King int temp[3]; 60beb1b6bbSSteven King }; 61beb1b6bbSSteven King 62cff37c9eSJean Delvare /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ 63cff37c9eSJean Delvare static inline int tmp102_reg_to_mC(s16 val) 64beb1b6bbSSteven King { 65cff37c9eSJean Delvare return ((val & ~0x01) * 1000) / 128; 66beb1b6bbSSteven King } 67beb1b6bbSSteven King 68cff37c9eSJean Delvare /* convert milliCelsius to left adjusted 13-bit TMP102 register value */ 69cff37c9eSJean Delvare static inline u16 tmp102_mC_to_reg(int val) 70beb1b6bbSSteven King { 71beb1b6bbSSteven King return (val * 128) / 1000; 72beb1b6bbSSteven King } 73beb1b6bbSSteven King 74beb1b6bbSSteven King static const u8 tmp102_reg[] = { 75beb1b6bbSSteven King TMP102_TEMP_REG, 76beb1b6bbSSteven King TMP102_TLOW_REG, 77beb1b6bbSSteven King TMP102_THIGH_REG, 78beb1b6bbSSteven King }; 79beb1b6bbSSteven King 80*3d8f7a89SGuenter Roeck static void tmp102_update_device(struct device *dev) 81beb1b6bbSSteven King { 82ad9beea4SGuenter Roeck struct tmp102 *tmp102 = dev_get_drvdata(dev); 83ad9beea4SGuenter Roeck struct i2c_client *client = tmp102->client; 84beb1b6bbSSteven King 85beb1b6bbSSteven King mutex_lock(&tmp102->lock); 86*3d8f7a89SGuenter Roeck if (!tmp102->valid || 87*3d8f7a89SGuenter Roeck time_after(jiffies, tmp102->last_update + HZ / 3)) { 88beb1b6bbSSteven King int i; 89beb1b6bbSSteven King for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { 9090f4102cSJean Delvare int status = i2c_smbus_read_word_swapped(client, 9190f4102cSJean Delvare tmp102_reg[i]); 92beb1b6bbSSteven King if (status > -1) 93beb1b6bbSSteven King tmp102->temp[i] = tmp102_reg_to_mC(status); 94beb1b6bbSSteven King } 95beb1b6bbSSteven King tmp102->last_update = jiffies; 96*3d8f7a89SGuenter Roeck tmp102->valid = true; 97beb1b6bbSSteven King } 98beb1b6bbSSteven King mutex_unlock(&tmp102->lock); 99beb1b6bbSSteven King } 100beb1b6bbSSteven King 10117e8351aSSascha Hauer static int tmp102_read_temp(void *dev, int *temp) 1026a027523SEduardo Valentin { 103*3d8f7a89SGuenter Roeck struct tmp102 *tmp102 = dev_get_drvdata(dev); 1046a027523SEduardo Valentin 105*3d8f7a89SGuenter Roeck if (time_before(jiffies, tmp102->ready_time)) { 10600917b5cSNishanth Menon dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); 10700917b5cSNishanth Menon return -EAGAIN; 10800917b5cSNishanth Menon } 10900917b5cSNishanth Menon 110*3d8f7a89SGuenter Roeck tmp102_update_device(dev); 111*3d8f7a89SGuenter Roeck 1126a027523SEduardo Valentin *temp = tmp102->temp[0]; 1136a027523SEduardo Valentin 1146a027523SEduardo Valentin return 0; 1156a027523SEduardo Valentin } 1166a027523SEduardo Valentin 117beb1b6bbSSteven King static ssize_t tmp102_show_temp(struct device *dev, 118beb1b6bbSSteven King struct device_attribute *attr, 119beb1b6bbSSteven King char *buf) 120beb1b6bbSSteven King { 121beb1b6bbSSteven King struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 122*3d8f7a89SGuenter Roeck struct tmp102 *tmp102 = dev_get_drvdata(dev); 123beb1b6bbSSteven King 124*3d8f7a89SGuenter Roeck if (time_before(jiffies, tmp102->ready_time)) 12500917b5cSNishanth Menon return -EAGAIN; 12600917b5cSNishanth Menon 127*3d8f7a89SGuenter Roeck tmp102_update_device(dev); 128*3d8f7a89SGuenter Roeck 129beb1b6bbSSteven King return sprintf(buf, "%d\n", tmp102->temp[sda->index]); 130beb1b6bbSSteven King } 131beb1b6bbSSteven King 132beb1b6bbSSteven King static ssize_t tmp102_set_temp(struct device *dev, 133beb1b6bbSSteven King struct device_attribute *attr, 134beb1b6bbSSteven King const char *buf, size_t count) 135beb1b6bbSSteven King { 136beb1b6bbSSteven King struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 137ad9beea4SGuenter Roeck struct tmp102 *tmp102 = dev_get_drvdata(dev); 138ad9beea4SGuenter Roeck struct i2c_client *client = tmp102->client; 139beb1b6bbSSteven King long val; 140cff37c9eSJean Delvare int status; 141beb1b6bbSSteven King 142179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &val) < 0) 143beb1b6bbSSteven King return -EINVAL; 1442a844c14SGuenter Roeck val = clamp_val(val, -256000, 255000); 145cff37c9eSJean Delvare 146beb1b6bbSSteven King mutex_lock(&tmp102->lock); 147beb1b6bbSSteven King tmp102->temp[sda->index] = val; 14890f4102cSJean Delvare status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index], 149beb1b6bbSSteven King tmp102_mC_to_reg(val)); 150beb1b6bbSSteven King mutex_unlock(&tmp102->lock); 151beb1b6bbSSteven King return status ? : count; 152beb1b6bbSSteven King } 153beb1b6bbSSteven King 154beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); 155beb1b6bbSSteven King 156beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, 157beb1b6bbSSteven King tmp102_set_temp, 1); 158beb1b6bbSSteven King 159beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, 160beb1b6bbSSteven King tmp102_set_temp, 2); 161beb1b6bbSSteven King 162ad9beea4SGuenter Roeck static struct attribute *tmp102_attrs[] = { 163beb1b6bbSSteven King &sensor_dev_attr_temp1_input.dev_attr.attr, 164beb1b6bbSSteven King &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 165beb1b6bbSSteven King &sensor_dev_attr_temp1_max.dev_attr.attr, 166beb1b6bbSSteven King NULL 167beb1b6bbSSteven King }; 168ad9beea4SGuenter Roeck ATTRIBUTE_GROUPS(tmp102); 169beb1b6bbSSteven King 170beb1b6bbSSteven King #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) 171beb1b6bbSSteven King #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) 172beb1b6bbSSteven King 1732251aef6SEduardo Valentin static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = { 1742251aef6SEduardo Valentin .get_temp = tmp102_read_temp, 1752251aef6SEduardo Valentin }; 1762251aef6SEduardo Valentin 177b17ea1caSGuenter Roeck static void tmp102_restore_config(void *data) 178b17ea1caSGuenter Roeck { 179b17ea1caSGuenter Roeck struct tmp102 *tmp102 = data; 180b17ea1caSGuenter Roeck struct i2c_client *client = tmp102->client; 181b17ea1caSGuenter Roeck 182b17ea1caSGuenter Roeck i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, 183b17ea1caSGuenter Roeck tmp102->config_orig); 184b17ea1caSGuenter Roeck } 185b17ea1caSGuenter Roeck 1866c931ae1SBill Pemberton static int tmp102_probe(struct i2c_client *client, 187beb1b6bbSSteven King const struct i2c_device_id *id) 188beb1b6bbSSteven King { 189fbd9af16SGuenter Roeck struct device *dev = &client->dev; 190ad9beea4SGuenter Roeck struct device *hwmon_dev; 191beb1b6bbSSteven King struct tmp102 *tmp102; 192beb1b6bbSSteven King int status; 193beb1b6bbSSteven King 194cff37c9eSJean Delvare if (!i2c_check_functionality(client->adapter, 195beb1b6bbSSteven King I2C_FUNC_SMBUS_WORD_DATA)) { 196fbd9af16SGuenter Roeck dev_err(dev, 197b55f3757SGuenter Roeck "adapter doesn't support SMBus word transactions\n"); 198beb1b6bbSSteven King return -ENODEV; 199beb1b6bbSSteven King } 200beb1b6bbSSteven King 201fbd9af16SGuenter Roeck tmp102 = devm_kzalloc(dev, sizeof(*tmp102), GFP_KERNEL); 202f511a21fSGuenter Roeck if (!tmp102) 203beb1b6bbSSteven King return -ENOMEM; 204f511a21fSGuenter Roeck 205beb1b6bbSSteven King i2c_set_clientdata(client, tmp102); 206ad9beea4SGuenter Roeck tmp102->client = client; 207beb1b6bbSSteven King 20890f4102cSJean Delvare status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 20938806bdaSJean Delvare if (status < 0) { 210fbd9af16SGuenter Roeck dev_err(dev, "error reading config register\n"); 211f511a21fSGuenter Roeck return status; 21238806bdaSJean Delvare } 21338806bdaSJean Delvare tmp102->config_orig = status; 214b17ea1caSGuenter Roeck 215b17ea1caSGuenter Roeck devm_add_action(dev, tmp102_restore_config, tmp102); 216b17ea1caSGuenter Roeck 21790f4102cSJean Delvare status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, 21890f4102cSJean Delvare TMP102_CONFIG); 219cff37c9eSJean Delvare if (status < 0) { 220fbd9af16SGuenter Roeck dev_err(dev, "error writing config register\n"); 221b17ea1caSGuenter Roeck return status; 222cff37c9eSJean Delvare } 22390f4102cSJean Delvare status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 224beb1b6bbSSteven King if (status < 0) { 225fbd9af16SGuenter Roeck dev_err(dev, "error reading config register\n"); 226b17ea1caSGuenter Roeck return status; 227beb1b6bbSSteven King } 228beb1b6bbSSteven King status &= ~TMP102_CONFIG_RD_ONLY; 229beb1b6bbSSteven King if (status != TMP102_CONFIG) { 230fbd9af16SGuenter Roeck dev_err(dev, "config settings did not stick\n"); 231b17ea1caSGuenter Roeck return -ENODEV; 232beb1b6bbSSteven King } 233*3d8f7a89SGuenter Roeck 234beb1b6bbSSteven King mutex_init(&tmp102->lock); 235beb1b6bbSSteven King 236*3d8f7a89SGuenter Roeck tmp102->ready_time = jiffies; 237*3d8f7a89SGuenter Roeck if (tmp102->config_orig & TMP102_CONF_SD) { 238*3d8f7a89SGuenter Roeck /* 239*3d8f7a89SGuenter Roeck * Mark that we are not ready with data until the first 240*3d8f7a89SGuenter Roeck * conversion is complete 241*3d8f7a89SGuenter Roeck */ 242*3d8f7a89SGuenter Roeck tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS); 243*3d8f7a89SGuenter Roeck } 244*3d8f7a89SGuenter Roeck 245b17ea1caSGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 246b17ea1caSGuenter Roeck tmp102, 247b17ea1caSGuenter Roeck tmp102_groups); 248ad9beea4SGuenter Roeck if (IS_ERR(hwmon_dev)) { 249ad9beea4SGuenter Roeck dev_dbg(dev, "unable to register hwmon device\n"); 250b17ea1caSGuenter Roeck return PTR_ERR(hwmon_dev); 251beb1b6bbSSteven King } 25251b77fd7SEduardo Valentin devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, 2532251aef6SEduardo Valentin &tmp102_of_thermal_ops); 2546a027523SEduardo Valentin 255fbd9af16SGuenter Roeck dev_info(dev, "initialized\n"); 256beb1b6bbSSteven King 257beb1b6bbSSteven King return 0; 258beb1b6bbSSteven King } 259beb1b6bbSSteven King 260dd378b1bSGrygorii Strashko #ifdef CONFIG_PM_SLEEP 261beb1b6bbSSteven King static int tmp102_suspend(struct device *dev) 262beb1b6bbSSteven King { 263beb1b6bbSSteven King struct i2c_client *client = to_i2c_client(dev); 2648d4dee98SJean Delvare int config; 265beb1b6bbSSteven King 26690f4102cSJean Delvare config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 2678d4dee98SJean Delvare if (config < 0) 2688d4dee98SJean Delvare return config; 269beb1b6bbSSteven King 2708d4dee98SJean Delvare config |= TMP102_CONF_SD; 27190f4102cSJean Delvare return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); 272beb1b6bbSSteven King } 273beb1b6bbSSteven King 274beb1b6bbSSteven King static int tmp102_resume(struct device *dev) 275beb1b6bbSSteven King { 276beb1b6bbSSteven King struct i2c_client *client = to_i2c_client(dev); 277*3d8f7a89SGuenter Roeck struct tmp102 *tmp102 = i2c_get_clientdata(client); 2788d4dee98SJean Delvare int config; 279beb1b6bbSSteven King 28090f4102cSJean Delvare config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 2818d4dee98SJean Delvare if (config < 0) 2828d4dee98SJean Delvare return config; 283beb1b6bbSSteven King 284*3d8f7a89SGuenter Roeck tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS); 285*3d8f7a89SGuenter Roeck 2868d4dee98SJean Delvare config &= ~TMP102_CONF_SD; 28790f4102cSJean Delvare return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); 288beb1b6bbSSteven King } 289beb1b6bbSSteven King #endif /* CONFIG_PM */ 290beb1b6bbSSteven King 291dd378b1bSGrygorii Strashko static SIMPLE_DEV_PM_OPS(tmp102_dev_pm_ops, tmp102_suspend, tmp102_resume); 292dd378b1bSGrygorii Strashko 293beb1b6bbSSteven King static const struct i2c_device_id tmp102_id[] = { 294cff37c9eSJean Delvare { "tmp102", 0 }, 295beb1b6bbSSteven King { } 296beb1b6bbSSteven King }; 297cff37c9eSJean Delvare MODULE_DEVICE_TABLE(i2c, tmp102_id); 298beb1b6bbSSteven King 299beb1b6bbSSteven King static struct i2c_driver tmp102_driver = { 300beb1b6bbSSteven King .driver.name = DRIVER_NAME, 301dd378b1bSGrygorii Strashko .driver.pm = &tmp102_dev_pm_ops, 302beb1b6bbSSteven King .probe = tmp102_probe, 303beb1b6bbSSteven King .id_table = tmp102_id, 304beb1b6bbSSteven King }; 305beb1b6bbSSteven King 306f0967eeaSAxel Lin module_i2c_driver(tmp102_driver); 307beb1b6bbSSteven King 308beb1b6bbSSteven King MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); 309beb1b6bbSSteven King MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); 310beb1b6bbSSteven King MODULE_LICENSE("GPL"); 311