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 * You should have received a copy of the GNU General Public License 16beb1b6bbSSteven King * along with this program; if not, write to the Free Software 17beb1b6bbSSteven King * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA 18beb1b6bbSSteven King */ 19beb1b6bbSSteven King 20beb1b6bbSSteven King #include <linux/module.h> 21beb1b6bbSSteven King #include <linux/init.h> 22beb1b6bbSSteven King #include <linux/slab.h> 23beb1b6bbSSteven King #include <linux/i2c.h> 24beb1b6bbSSteven King #include <linux/hwmon.h> 25beb1b6bbSSteven King #include <linux/hwmon-sysfs.h> 26beb1b6bbSSteven King #include <linux/err.h> 27beb1b6bbSSteven King #include <linux/mutex.h> 28cff37c9eSJean Delvare #include <linux/device.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 50beb1b6bbSSteven King struct tmp102 { 51beb1b6bbSSteven King struct device *hwmon_dev; 52beb1b6bbSSteven King struct mutex lock; 53*38806bdaSJean Delvare u16 config_orig; 54beb1b6bbSSteven King unsigned long last_update; 55beb1b6bbSSteven King int temp[3]; 56beb1b6bbSSteven King }; 57beb1b6bbSSteven King 58cff37c9eSJean Delvare /* SMBus specifies low byte first, but the TMP102 returns high byte first, 59cff37c9eSJean Delvare * so we have to swab16 the values */ 60cff37c9eSJean Delvare static inline int tmp102_read_reg(struct i2c_client *client, u8 reg) 61beb1b6bbSSteven King { 62beb1b6bbSSteven King int result = i2c_smbus_read_word_data(client, reg); 63beb1b6bbSSteven King return result < 0 ? result : swab16(result); 64beb1b6bbSSteven King } 65beb1b6bbSSteven King 66cff37c9eSJean Delvare static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val) 67beb1b6bbSSteven King { 68beb1b6bbSSteven King return i2c_smbus_write_word_data(client, reg, swab16(val)); 69beb1b6bbSSteven King } 70beb1b6bbSSteven King 71cff37c9eSJean Delvare /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ 72cff37c9eSJean Delvare static inline int tmp102_reg_to_mC(s16 val) 73beb1b6bbSSteven King { 74cff37c9eSJean Delvare return ((val & ~0x01) * 1000) / 128; 75beb1b6bbSSteven King } 76beb1b6bbSSteven King 77cff37c9eSJean Delvare /* convert milliCelsius to left adjusted 13-bit TMP102 register value */ 78cff37c9eSJean Delvare static inline u16 tmp102_mC_to_reg(int val) 79beb1b6bbSSteven King { 80beb1b6bbSSteven King return (val * 128) / 1000; 81beb1b6bbSSteven King } 82beb1b6bbSSteven King 83beb1b6bbSSteven King static const u8 tmp102_reg[] = { 84beb1b6bbSSteven King TMP102_TEMP_REG, 85beb1b6bbSSteven King TMP102_TLOW_REG, 86beb1b6bbSSteven King TMP102_THIGH_REG, 87beb1b6bbSSteven King }; 88beb1b6bbSSteven King 89beb1b6bbSSteven King static struct tmp102 *tmp102_update_device(struct i2c_client *client) 90beb1b6bbSSteven King { 91beb1b6bbSSteven King struct tmp102 *tmp102 = i2c_get_clientdata(client); 92beb1b6bbSSteven King 93beb1b6bbSSteven King mutex_lock(&tmp102->lock); 94cff37c9eSJean Delvare if (time_after(jiffies, tmp102->last_update + HZ / 3)) { 95beb1b6bbSSteven King int i; 96beb1b6bbSSteven King for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { 97beb1b6bbSSteven King int status = tmp102_read_reg(client, tmp102_reg[i]); 98beb1b6bbSSteven King if (status > -1) 99beb1b6bbSSteven King tmp102->temp[i] = tmp102_reg_to_mC(status); 100beb1b6bbSSteven King } 101beb1b6bbSSteven King tmp102->last_update = jiffies; 102beb1b6bbSSteven King } 103beb1b6bbSSteven King mutex_unlock(&tmp102->lock); 104beb1b6bbSSteven King return tmp102; 105beb1b6bbSSteven King } 106beb1b6bbSSteven King 107beb1b6bbSSteven King static ssize_t tmp102_show_temp(struct device *dev, 108beb1b6bbSSteven King struct device_attribute *attr, 109beb1b6bbSSteven King char *buf) 110beb1b6bbSSteven King { 111beb1b6bbSSteven King struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 112beb1b6bbSSteven King struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); 113beb1b6bbSSteven King 114beb1b6bbSSteven King return sprintf(buf, "%d\n", tmp102->temp[sda->index]); 115beb1b6bbSSteven King } 116beb1b6bbSSteven King 117beb1b6bbSSteven King static ssize_t tmp102_set_temp(struct device *dev, 118beb1b6bbSSteven King struct device_attribute *attr, 119beb1b6bbSSteven King const char *buf, size_t count) 120beb1b6bbSSteven King { 121beb1b6bbSSteven King struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 122beb1b6bbSSteven King struct i2c_client *client = to_i2c_client(dev); 123beb1b6bbSSteven King struct tmp102 *tmp102 = i2c_get_clientdata(client); 124beb1b6bbSSteven King long val; 125cff37c9eSJean Delvare int status; 126beb1b6bbSSteven King 127cff37c9eSJean Delvare if (strict_strtol(buf, 10, &val) < 0) 128beb1b6bbSSteven King return -EINVAL; 129cff37c9eSJean Delvare val = SENSORS_LIMIT(val, -256000, 255000); 130cff37c9eSJean Delvare 131beb1b6bbSSteven King mutex_lock(&tmp102->lock); 132beb1b6bbSSteven King tmp102->temp[sda->index] = val; 133beb1b6bbSSteven King status = tmp102_write_reg(client, tmp102_reg[sda->index], 134beb1b6bbSSteven King tmp102_mC_to_reg(val)); 135beb1b6bbSSteven King mutex_unlock(&tmp102->lock); 136beb1b6bbSSteven King return status ? : count; 137beb1b6bbSSteven King } 138beb1b6bbSSteven King 139beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); 140beb1b6bbSSteven King 141beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, 142beb1b6bbSSteven King tmp102_set_temp, 1); 143beb1b6bbSSteven King 144beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, 145beb1b6bbSSteven King tmp102_set_temp, 2); 146beb1b6bbSSteven King 147beb1b6bbSSteven King static struct attribute *tmp102_attributes[] = { 148beb1b6bbSSteven King &sensor_dev_attr_temp1_input.dev_attr.attr, 149beb1b6bbSSteven King &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 150beb1b6bbSSteven King &sensor_dev_attr_temp1_max.dev_attr.attr, 151beb1b6bbSSteven King NULL 152beb1b6bbSSteven King }; 153beb1b6bbSSteven King 154beb1b6bbSSteven King static const struct attribute_group tmp102_attr_group = { 155beb1b6bbSSteven King .attrs = tmp102_attributes, 156beb1b6bbSSteven King }; 157beb1b6bbSSteven King 158beb1b6bbSSteven King #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) 159beb1b6bbSSteven King #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) 160beb1b6bbSSteven King 161beb1b6bbSSteven King static int __devinit tmp102_probe(struct i2c_client *client, 162beb1b6bbSSteven King const struct i2c_device_id *id) 163beb1b6bbSSteven King { 164beb1b6bbSSteven King struct tmp102 *tmp102; 165beb1b6bbSSteven King int status; 166beb1b6bbSSteven King 167cff37c9eSJean Delvare if (!i2c_check_functionality(client->adapter, 168beb1b6bbSSteven King I2C_FUNC_SMBUS_WORD_DATA)) { 169cff37c9eSJean Delvare dev_err(&client->dev, "adapter doesnt support SMBus word " 170cff37c9eSJean Delvare "transactions\n"); 171beb1b6bbSSteven King return -ENODEV; 172beb1b6bbSSteven King } 173beb1b6bbSSteven King 174beb1b6bbSSteven King tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL); 175beb1b6bbSSteven King if (!tmp102) { 176beb1b6bbSSteven King dev_dbg(&client->dev, "kzalloc failed\n"); 177beb1b6bbSSteven King return -ENOMEM; 178beb1b6bbSSteven King } 179beb1b6bbSSteven King i2c_set_clientdata(client, tmp102); 180beb1b6bbSSteven King 181*38806bdaSJean Delvare status = tmp102_read_reg(client, TMP102_CONF_REG); 182*38806bdaSJean Delvare if (status < 0) { 183*38806bdaSJean Delvare dev_err(&client->dev, "error reading config register\n"); 184*38806bdaSJean Delvare goto fail_free; 185*38806bdaSJean Delvare } 186*38806bdaSJean Delvare tmp102->config_orig = status; 187cff37c9eSJean Delvare status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG); 188cff37c9eSJean Delvare if (status < 0) { 189cff37c9eSJean Delvare dev_err(&client->dev, "error writing config register\n"); 190*38806bdaSJean Delvare goto fail_restore_config; 191cff37c9eSJean Delvare } 192beb1b6bbSSteven King status = tmp102_read_reg(client, TMP102_CONF_REG); 193beb1b6bbSSteven King if (status < 0) { 194cff37c9eSJean Delvare dev_err(&client->dev, "error reading config register\n"); 195*38806bdaSJean Delvare goto fail_restore_config; 196beb1b6bbSSteven King } 197beb1b6bbSSteven King status &= ~TMP102_CONFIG_RD_ONLY; 198beb1b6bbSSteven King if (status != TMP102_CONFIG) { 199cff37c9eSJean Delvare dev_err(&client->dev, "config settings did not stick\n"); 200cff37c9eSJean Delvare status = -ENODEV; 201*38806bdaSJean Delvare goto fail_restore_config; 202beb1b6bbSSteven King } 203beb1b6bbSSteven King tmp102->last_update = jiffies - HZ; 204beb1b6bbSSteven King mutex_init(&tmp102->lock); 205beb1b6bbSSteven King 206beb1b6bbSSteven King status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group); 207beb1b6bbSSteven King if (status) { 208beb1b6bbSSteven King dev_dbg(&client->dev, "could not create sysfs files\n"); 209*38806bdaSJean Delvare goto fail_restore_config; 210beb1b6bbSSteven King } 211beb1b6bbSSteven King tmp102->hwmon_dev = hwmon_device_register(&client->dev); 212beb1b6bbSSteven King if (IS_ERR(tmp102->hwmon_dev)) { 213beb1b6bbSSteven King dev_dbg(&client->dev, "unable to register hwmon device\n"); 214beb1b6bbSSteven King status = PTR_ERR(tmp102->hwmon_dev); 215*38806bdaSJean Delvare goto fail_remove_sysfs; 216beb1b6bbSSteven King } 217beb1b6bbSSteven King 218beb1b6bbSSteven King dev_info(&client->dev, "initialized\n"); 219beb1b6bbSSteven King 220beb1b6bbSSteven King return 0; 221*38806bdaSJean Delvare 222*38806bdaSJean Delvare fail_remove_sysfs: 223beb1b6bbSSteven King sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); 224*38806bdaSJean Delvare fail_restore_config: 225*38806bdaSJean Delvare tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig); 226*38806bdaSJean Delvare fail_free: 227beb1b6bbSSteven King i2c_set_clientdata(client, NULL); 228beb1b6bbSSteven King kfree(tmp102); 229beb1b6bbSSteven King 230cff37c9eSJean Delvare return status; 231beb1b6bbSSteven King } 232beb1b6bbSSteven King 233beb1b6bbSSteven King static int __devexit tmp102_remove(struct i2c_client *client) 234beb1b6bbSSteven King { 235beb1b6bbSSteven King struct tmp102 *tmp102 = i2c_get_clientdata(client); 236beb1b6bbSSteven King 237beb1b6bbSSteven King hwmon_device_unregister(tmp102->hwmon_dev); 238beb1b6bbSSteven King sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); 239*38806bdaSJean Delvare 240*38806bdaSJean Delvare /* Stop monitoring if device was stopped originally */ 241*38806bdaSJean Delvare if (tmp102->config_orig & TMP102_CONF_SD) { 242*38806bdaSJean Delvare int config; 243*38806bdaSJean Delvare 244*38806bdaSJean Delvare config = tmp102_read_reg(client, TMP102_CONF_REG); 245*38806bdaSJean Delvare if (config >= 0) 246*38806bdaSJean Delvare tmp102_write_reg(client, TMP102_CONF_REG, 247*38806bdaSJean Delvare config | TMP102_CONF_SD); 248*38806bdaSJean Delvare } 249*38806bdaSJean Delvare 250beb1b6bbSSteven King i2c_set_clientdata(client, NULL); 251beb1b6bbSSteven King kfree(tmp102); 252beb1b6bbSSteven King 253beb1b6bbSSteven King return 0; 254beb1b6bbSSteven King } 255beb1b6bbSSteven King 256beb1b6bbSSteven King #ifdef CONFIG_PM 257beb1b6bbSSteven King static int tmp102_suspend(struct device *dev) 258beb1b6bbSSteven King { 259beb1b6bbSSteven King struct i2c_client *client = to_i2c_client(dev); 2608d4dee98SJean Delvare int config; 261beb1b6bbSSteven King 2628d4dee98SJean Delvare config = tmp102_read_reg(client, TMP102_CONF_REG); 2638d4dee98SJean Delvare if (config < 0) 2648d4dee98SJean Delvare return config; 265beb1b6bbSSteven King 2668d4dee98SJean Delvare config |= TMP102_CONF_SD; 2678d4dee98SJean Delvare return tmp102_write_reg(client, TMP102_CONF_REG, config); 268beb1b6bbSSteven King } 269beb1b6bbSSteven King 270beb1b6bbSSteven King static int tmp102_resume(struct device *dev) 271beb1b6bbSSteven King { 272beb1b6bbSSteven King struct i2c_client *client = to_i2c_client(dev); 2738d4dee98SJean Delvare int config; 274beb1b6bbSSteven King 2758d4dee98SJean Delvare config = tmp102_read_reg(client, TMP102_CONF_REG); 2768d4dee98SJean Delvare if (config < 0) 2778d4dee98SJean Delvare return config; 278beb1b6bbSSteven King 2798d4dee98SJean Delvare config &= ~TMP102_CONF_SD; 2808d4dee98SJean Delvare return tmp102_write_reg(client, TMP102_CONF_REG, config); 281beb1b6bbSSteven King } 282beb1b6bbSSteven King 283beb1b6bbSSteven King static const struct dev_pm_ops tmp102_dev_pm_ops = { 284beb1b6bbSSteven King .suspend = tmp102_suspend, 285beb1b6bbSSteven King .resume = tmp102_resume, 286beb1b6bbSSteven King }; 287beb1b6bbSSteven King 288beb1b6bbSSteven King #define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops) 289beb1b6bbSSteven King #else 290beb1b6bbSSteven King #define TMP102_DEV_PM_OPS NULL 291beb1b6bbSSteven King #endif /* CONFIG_PM */ 292beb1b6bbSSteven King 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, 301beb1b6bbSSteven King .driver.pm = TMP102_DEV_PM_OPS, 302beb1b6bbSSteven King .probe = tmp102_probe, 303beb1b6bbSSteven King .remove = __devexit_p(tmp102_remove), 304beb1b6bbSSteven King .id_table = tmp102_id, 305beb1b6bbSSteven King }; 306beb1b6bbSSteven King 307beb1b6bbSSteven King static int __init tmp102_init(void) 308beb1b6bbSSteven King { 309beb1b6bbSSteven King return i2c_add_driver(&tmp102_driver); 310beb1b6bbSSteven King } 311beb1b6bbSSteven King module_init(tmp102_init); 312beb1b6bbSSteven King 313beb1b6bbSSteven King static void __exit tmp102_exit(void) 314beb1b6bbSSteven King { 315beb1b6bbSSteven King i2c_del_driver(&tmp102_driver); 316beb1b6bbSSteven King } 317beb1b6bbSSteven King module_exit(tmp102_exit); 318beb1b6bbSSteven King 319beb1b6bbSSteven King MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); 320beb1b6bbSSteven King MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); 321beb1b6bbSSteven King MODULE_LICENSE("GPL"); 322