-/* 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");