-/* Texas Instruments TMP102 SMBUS temperature sensor driver
+/* Texas Instruments TMP102 SMBus temperature sensor driver
  *
- * Copyright 2010 Steven King <sfking@fdwdc.com>
+ * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
+#include <linux/device.h>
 
 #define        DRIVER_NAME "tmp102"
 
        int temp[3];
 };
 
-/* the TMP102 registers are big endian so we have to swab16 the values */
-static int tmp102_read_reg(struct i2c_client *client, u8 reg)
+/* SMBus specifies low byte first, but the TMP102 returns high byte first,
+ * so we have to swab16 the values */
+static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
 {
        int result = i2c_smbus_read_word_data(client, reg);
        return result < 0 ? result : swab16(result);
 }
 
-static int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
+static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
 {
        return i2c_smbus_write_word_data(client, reg, swab16(val));
 }
 
-/* convert left adjusted 13bit TMP102 register value to miliCelsius */
-static int tmp102_reg_to_mC(s16 val)
+/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
+static inline int tmp102_reg_to_mC(s16 val)
 {
-       return (val * 1000) / 128;
+       return ((val & ~0x01) * 1000) / 128;
 }
 
-/* convert miliCelsius to left adjusted 13bit TMP102 register value */
-static u16 tmp102_mC_to_reg(int val)
+/* convert milliCelsius to left adjusted 13-bit TMP102 register value */
+static inline u16 tmp102_mC_to_reg(int val)
 {
        return (val * 128) / 1000;
 }
        struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
        mutex_lock(&tmp102->lock);
-       if (time_after(jiffies, tmp102->last_update + HZ / 4)) {
+       if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
                int i;
                for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
                        int status = tmp102_read_reg(client, tmp102_reg[i]);
        struct i2c_client *client = to_i2c_client(dev);
        struct tmp102 *tmp102 = i2c_get_clientdata(client);
        long val;
-       int status = 0;
+       int status;
 
-       if ((strict_strtol(buf, 10, &val) < 0) || (abs(val) > 150000))
+       if (strict_strtol(buf, 10, &val) < 0)
                return -EINVAL;
+       val = SENSORS_LIMIT(val, -256000, 255000);
+
        mutex_lock(&tmp102->lock);
-       if (tmp102->temp[sda->index] != val) {
-               tmp102->temp[sda->index] = val;
-               status = tmp102_write_reg(client, tmp102_reg[sda->index],
-                                         tmp102_mC_to_reg(val));
-       }
+       tmp102->temp[sda->index] = val;
+       status = tmp102_write_reg(client, tmp102_reg[sda->index],
+                                 tmp102_mC_to_reg(val));
        mutex_unlock(&tmp102->lock);
        return status ? : count;
 }
        struct tmp102 *tmp102;
        int status;
 
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+       if (!i2c_check_functionality(client->adapter,
                                     I2C_FUNC_SMBUS_WORD_DATA)) {
-               dev_dbg(&client->dev, "adapter doesnt support SMBUS\n");
+               dev_err(&client->dev, "adapter doesnt support SMBus word "
+                       "transactions\n");
                return -ENODEV;
        }
 
        }
        i2c_set_clientdata(client, tmp102);
 
-       tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
+       status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
+       if (status < 0) {
+               dev_err(&client->dev, "error writing config register\n");
+               goto fail0;
+       }
        status = tmp102_read_reg(client, TMP102_CONF_REG);
        if (status < 0) {
-               dev_dbg(&client->dev, "error reading config register\n");
+               dev_err(&client->dev, "error reading config register\n");
                goto fail0;
        }
        status &= ~TMP102_CONFIG_RD_ONLY;
        if (status != TMP102_CONFIG) {
-               dev_dbg(&client->dev, "could not verify config settings\n");
-               status = -EIO;
+               dev_err(&client->dev, "config settings did not stick\n");
+               status = -ENODEV;
                goto fail0;
        }
        tmp102->last_update = jiffies - HZ;
        i2c_set_clientdata(client, NULL);
        kfree(tmp102);
 
-       return 0;
+       return status;
 }
 
 static int __devexit tmp102_remove(struct i2c_client *client)
 #define        TMP102_DEV_PM_OPS NULL
 #endif /* CONFIG_PM */
 
-static const unsigned short normal_i2c[] = {
-       0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END
-};
-
 static const struct i2c_device_id tmp102_id[] = {
-       { DRIVER_NAME, 0 },
+       { "tmp102", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c, tmp102_id);
 
 static struct i2c_driver tmp102_driver = {
        .driver.name    = DRIVER_NAME,
        .driver.pm      = TMP102_DEV_PM_OPS,
-       .class          = I2C_CLASS_HWMON,
        .probe          = tmp102_probe,
        .remove         = __devexit_p(tmp102_remove),
        .id_table       = tmp102_id,
-       .address_list   = normal_i2c,
 };
 
 static int __init tmp102_init(void)
 }
 module_exit(tmp102_exit);
 
-
 MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
 MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
 MODULE_LICENSE("GPL");