linux/drivers/hwmon/tmp102.c
<<
>>
Prefs
   1/* Texas Instruments TMP102 SMBus temperature sensor driver
   2 *
   3 * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/init.h>
  22#include <linux/slab.h>
  23#include <linux/i2c.h>
  24#include <linux/hwmon.h>
  25#include <linux/hwmon-sysfs.h>
  26#include <linux/err.h>
  27#include <linux/mutex.h>
  28#include <linux/device.h>
  29
  30#define DRIVER_NAME "tmp102"
  31
  32#define TMP102_TEMP_REG                 0x00
  33#define TMP102_CONF_REG                 0x01
  34/* note: these bit definitions are byte swapped */
  35#define         TMP102_CONF_SD          0x0100
  36#define         TMP102_CONF_TM          0x0200
  37#define         TMP102_CONF_POL         0x0400
  38#define         TMP102_CONF_F0          0x0800
  39#define         TMP102_CONF_F1          0x1000
  40#define         TMP102_CONF_R0          0x2000
  41#define         TMP102_CONF_R1          0x4000
  42#define         TMP102_CONF_OS          0x8000
  43#define         TMP102_CONF_EM          0x0010
  44#define         TMP102_CONF_AL          0x0020
  45#define         TMP102_CONF_CR0         0x0040
  46#define         TMP102_CONF_CR1         0x0080
  47#define TMP102_TLOW_REG                 0x02
  48#define TMP102_THIGH_REG                0x03
  49
  50struct tmp102 {
  51        struct device *hwmon_dev;
  52        struct mutex lock;
  53        u16 config_orig;
  54        unsigned long last_update;
  55        int temp[3];
  56};
  57
  58/* SMBus specifies low byte first, but the TMP102 returns high byte first,
  59 * so we have to swab16 the values */
  60static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
  61{
  62        int result = i2c_smbus_read_word_data(client, reg);
  63        return result < 0 ? result : swab16(result);
  64}
  65
  66static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
  67{
  68        return i2c_smbus_write_word_data(client, reg, swab16(val));
  69}
  70
  71/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
  72static inline int tmp102_reg_to_mC(s16 val)
  73{
  74        return ((val & ~0x01) * 1000) / 128;
  75}
  76
  77/* convert milliCelsius to left adjusted 13-bit TMP102 register value */
  78static inline u16 tmp102_mC_to_reg(int val)
  79{
  80        return (val * 128) / 1000;
  81}
  82
  83static const u8 tmp102_reg[] = {
  84        TMP102_TEMP_REG,
  85        TMP102_TLOW_REG,
  86        TMP102_THIGH_REG,
  87};
  88
  89static struct tmp102 *tmp102_update_device(struct i2c_client *client)
  90{
  91        struct tmp102 *tmp102 = i2c_get_clientdata(client);
  92
  93        mutex_lock(&tmp102->lock);
  94        if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
  95                int i;
  96                for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
  97                        int status = tmp102_read_reg(client, tmp102_reg[i]);
  98                        if (status > -1)
  99                                tmp102->temp[i] = tmp102_reg_to_mC(status);
 100                }
 101                tmp102->last_update = jiffies;
 102        }
 103        mutex_unlock(&tmp102->lock);
 104        return tmp102;
 105}
 106
 107static ssize_t tmp102_show_temp(struct device *dev,
 108                                struct device_attribute *attr,
 109                                char *buf)
 110{
 111        struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
 112        struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
 113
 114        return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
 115}
 116
 117static ssize_t tmp102_set_temp(struct device *dev,
 118                               struct device_attribute *attr,
 119                               const char *buf, size_t count)
 120{
 121        struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
 122        struct i2c_client *client = to_i2c_client(dev);
 123        struct tmp102 *tmp102 = i2c_get_clientdata(client);
 124        long val;
 125        int status;
 126
 127        if (strict_strtol(buf, 10, &val) < 0)
 128                return -EINVAL;
 129        val = SENSORS_LIMIT(val, -256000, 255000);
 130
 131        mutex_lock(&tmp102->lock);
 132        tmp102->temp[sda->index] = val;
 133        status = tmp102_write_reg(client, tmp102_reg[sda->index],
 134                                  tmp102_mC_to_reg(val));
 135        mutex_unlock(&tmp102->lock);
 136        return status ? : count;
 137}
 138
 139static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0);
 140
 141static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
 142                          tmp102_set_temp, 1);
 143
 144static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
 145                          tmp102_set_temp, 2);
 146
 147static struct attribute *tmp102_attributes[] = {
 148        &sensor_dev_attr_temp1_input.dev_attr.attr,
 149        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 150        &sensor_dev_attr_temp1_max.dev_attr.attr,
 151        NULL
 152};
 153
 154static const struct attribute_group tmp102_attr_group = {
 155        .attrs = tmp102_attributes,
 156};
 157
 158#define TMP102_CONFIG  (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
 159#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
 160
 161static int __devinit tmp102_probe(struct i2c_client *client,
 162                                  const struct i2c_device_id *id)
 163{
 164        struct tmp102 *tmp102;
 165        int status;
 166
 167        if (!i2c_check_functionality(client->adapter,
 168                                     I2C_FUNC_SMBUS_WORD_DATA)) {
 169                dev_err(&client->dev, "adapter doesn't support SMBus word "
 170                        "transactions\n");
 171                return -ENODEV;
 172        }
 173
 174        tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL);
 175        if (!tmp102) {
 176                dev_dbg(&client->dev, "kzalloc failed\n");
 177                return -ENOMEM;
 178        }
 179        i2c_set_clientdata(client, tmp102);
 180
 181        status = tmp102_read_reg(client, TMP102_CONF_REG);
 182        if (status < 0) {
 183                dev_err(&client->dev, "error reading config register\n");
 184                goto fail_free;
 185        }
 186        tmp102->config_orig = status;
 187        status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
 188        if (status < 0) {
 189                dev_err(&client->dev, "error writing config register\n");
 190                goto fail_restore_config;
 191        }
 192        status = tmp102_read_reg(client, TMP102_CONF_REG);
 193        if (status < 0) {
 194                dev_err(&client->dev, "error reading config register\n");
 195                goto fail_restore_config;
 196        }
 197        status &= ~TMP102_CONFIG_RD_ONLY;
 198        if (status != TMP102_CONFIG) {
 199                dev_err(&client->dev, "config settings did not stick\n");
 200                status = -ENODEV;
 201                goto fail_restore_config;
 202        }
 203        tmp102->last_update = jiffies - HZ;
 204        mutex_init(&tmp102->lock);
 205
 206        status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group);
 207        if (status) {
 208                dev_dbg(&client->dev, "could not create sysfs files\n");
 209                goto fail_restore_config;
 210        }
 211        tmp102->hwmon_dev = hwmon_device_register(&client->dev);
 212        if (IS_ERR(tmp102->hwmon_dev)) {
 213                dev_dbg(&client->dev, "unable to register hwmon device\n");
 214                status = PTR_ERR(tmp102->hwmon_dev);
 215                goto fail_remove_sysfs;
 216        }
 217
 218        dev_info(&client->dev, "initialized\n");
 219
 220        return 0;
 221
 222fail_remove_sysfs:
 223        sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 224fail_restore_config:
 225        tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
 226fail_free:
 227        kfree(tmp102);
 228
 229        return status;
 230}
 231
 232static int __devexit tmp102_remove(struct i2c_client *client)
 233{
 234        struct tmp102 *tmp102 = i2c_get_clientdata(client);
 235
 236        hwmon_device_unregister(tmp102->hwmon_dev);
 237        sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 238
 239        /* Stop monitoring if device was stopped originally */
 240        if (tmp102->config_orig & TMP102_CONF_SD) {
 241                int config;
 242
 243                config = tmp102_read_reg(client, TMP102_CONF_REG);
 244                if (config >= 0)
 245                        tmp102_write_reg(client, TMP102_CONF_REG,
 246                                         config | TMP102_CONF_SD);
 247        }
 248
 249        kfree(tmp102);
 250
 251        return 0;
 252}
 253
 254#ifdef CONFIG_PM
 255static int tmp102_suspend(struct device *dev)
 256{
 257        struct i2c_client *client = to_i2c_client(dev);
 258        int config;
 259
 260        config = tmp102_read_reg(client, TMP102_CONF_REG);
 261        if (config < 0)
 262                return config;
 263
 264        config |= TMP102_CONF_SD;
 265        return tmp102_write_reg(client, TMP102_CONF_REG, config);
 266}
 267
 268static int tmp102_resume(struct device *dev)
 269{
 270        struct i2c_client *client = to_i2c_client(dev);
 271        int config;
 272
 273        config = tmp102_read_reg(client, TMP102_CONF_REG);
 274        if (config < 0)
 275                return config;
 276
 277        config &= ~TMP102_CONF_SD;
 278        return tmp102_write_reg(client, TMP102_CONF_REG, config);
 279}
 280
 281static const struct dev_pm_ops tmp102_dev_pm_ops = {
 282        .suspend        = tmp102_suspend,
 283        .resume         = tmp102_resume,
 284};
 285
 286#define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops)
 287#else
 288#define TMP102_DEV_PM_OPS NULL
 289#endif /* CONFIG_PM */
 290
 291static const struct i2c_device_id tmp102_id[] = {
 292        { "tmp102", 0 },
 293        { }
 294};
 295MODULE_DEVICE_TABLE(i2c, tmp102_id);
 296
 297static struct i2c_driver tmp102_driver = {
 298        .driver.name    = DRIVER_NAME,
 299        .driver.pm      = TMP102_DEV_PM_OPS,
 300        .probe          = tmp102_probe,
 301        .remove         = __devexit_p(tmp102_remove),
 302        .id_table       = tmp102_id,
 303};
 304
 305static int __init tmp102_init(void)
 306{
 307        return i2c_add_driver(&tmp102_driver);
 308}
 309module_init(tmp102_init);
 310
 311static void __exit tmp102_exit(void)
 312{
 313        i2c_del_driver(&tmp102_driver);
 314}
 315module_exit(tmp102_exit);
 316
 317MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
 318MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
 319MODULE_LICENSE("GPL");
 320