aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/tmp102.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2010-05-27 13:58:57 -0400
committerJean Delvare <khali@linux-fr.org>2010-05-27 13:58:57 -0400
commitcff37c9e82e022068840b3d33167e64c6a0ecc06 (patch)
tree8ebce4d6d8cbc16a661e6548515d02f43d66ad58 /drivers/hwmon/tmp102.c
parentbeb1b6bbf2b448b97b9611200eb4b5a555336c60 (diff)
hwmon: (tmp102) Various fixes
Fixes from my driver review: http://lists.lm-sensors.org/pipermail/lm-sensors/2010-March/028051.html Only the small changes are in there, more important changes will come later separately as time permits. * Drop the remnants of the now gone detect function * The TMP102 has no known compatible chip * Include the right header files * Clarify why byte swapping of register values is needed * Strip resolution info bit from temperature register value * Set cache lifetime to 1/3 second * Don't arbitrarily reject limit values; clamp as needed * Make limit writing unconditional * Don't check for transaction types the driver doesn't use * Properly check for error when setting configuration * Report error on failed probe * Make the driver load automatically where needed * Various other minor fixes Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Steven King <sfking@fdwdc.com>
Diffstat (limited to 'drivers/hwmon/tmp102.c')
-rw-r--r--drivers/hwmon/tmp102.c70
1 files changed, 34 insertions, 36 deletions
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index e4def62c0ebf..e9de28df0e4d 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -1,6 +1,6 @@
1/* Texas Instruments TMP102 SMBUS temperature sensor driver 1/* Texas Instruments TMP102 SMBus temperature sensor driver
2 * 2 *
3 * Copyright 2010 Steven King <sfking@fdwdc.com> 3 * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License as published by
@@ -17,8 +17,6 @@
17 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA 17 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19 19
20
21
22#include <linux/module.h> 20#include <linux/module.h>
23#include <linux/init.h> 21#include <linux/init.h>
24#include <linux/slab.h> 22#include <linux/slab.h>
@@ -27,7 +25,7 @@
27#include <linux/hwmon-sysfs.h> 25#include <linux/hwmon-sysfs.h>
28#include <linux/err.h> 26#include <linux/err.h>
29#include <linux/mutex.h> 27#include <linux/mutex.h>
30#include <linux/delay.h> 28#include <linux/device.h>
31 29
32#define DRIVER_NAME "tmp102" 30#define DRIVER_NAME "tmp102"
33 31
@@ -56,26 +54,27 @@ struct tmp102 {
56 int temp[3]; 54 int temp[3];
57}; 55};
58 56
59/* the TMP102 registers are big endian so we have to swab16 the values */ 57/* SMBus specifies low byte first, but the TMP102 returns high byte first,
60static int tmp102_read_reg(struct i2c_client *client, u8 reg) 58 * so we have to swab16 the values */
59static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
61{ 60{
62 int result = i2c_smbus_read_word_data(client, reg); 61 int result = i2c_smbus_read_word_data(client, reg);
63 return result < 0 ? result : swab16(result); 62 return result < 0 ? result : swab16(result);
64} 63}
65 64
66static int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val) 65static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
67{ 66{
68 return i2c_smbus_write_word_data(client, reg, swab16(val)); 67 return i2c_smbus_write_word_data(client, reg, swab16(val));
69} 68}
70 69
71/* convert left adjusted 13bit TMP102 register value to miliCelsius */ 70/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
72static int tmp102_reg_to_mC(s16 val) 71static inline int tmp102_reg_to_mC(s16 val)
73{ 72{
74 return (val * 1000) / 128; 73 return ((val & ~0x01) * 1000) / 128;
75} 74}
76 75
77/* convert miliCelsius to left adjusted 13bit TMP102 register value */ 76/* convert milliCelsius to left adjusted 13-bit TMP102 register value */
78static u16 tmp102_mC_to_reg(int val) 77static inline u16 tmp102_mC_to_reg(int val)
79{ 78{
80 return (val * 128) / 1000; 79 return (val * 128) / 1000;
81} 80}
@@ -91,7 +90,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
91 struct tmp102 *tmp102 = i2c_get_clientdata(client); 90 struct tmp102 *tmp102 = i2c_get_clientdata(client);
92 91
93 mutex_lock(&tmp102->lock); 92 mutex_lock(&tmp102->lock);
94 if (time_after(jiffies, tmp102->last_update + HZ / 4)) { 93 if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
95 int i; 94 int i;
96 for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { 95 for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
97 int status = tmp102_read_reg(client, tmp102_reg[i]); 96 int status = tmp102_read_reg(client, tmp102_reg[i]);
@@ -122,16 +121,16 @@ static ssize_t tmp102_set_temp(struct device *dev,
122 struct i2c_client *client = to_i2c_client(dev); 121 struct i2c_client *client = to_i2c_client(dev);
123 struct tmp102 *tmp102 = i2c_get_clientdata(client); 122 struct tmp102 *tmp102 = i2c_get_clientdata(client);
124 long val; 123 long val;
125 int status = 0; 124 int status;
126 125
127 if ((strict_strtol(buf, 10, &val) < 0) || (abs(val) > 150000)) 126 if (strict_strtol(buf, 10, &val) < 0)
128 return -EINVAL; 127 return -EINVAL;
128 val = SENSORS_LIMIT(val, -256000, 255000);
129
129 mutex_lock(&tmp102->lock); 130 mutex_lock(&tmp102->lock);
130 if (tmp102->temp[sda->index] != val) { 131 tmp102->temp[sda->index] = val;
131 tmp102->temp[sda->index] = val; 132 status = tmp102_write_reg(client, tmp102_reg[sda->index],
132 status = tmp102_write_reg(client, tmp102_reg[sda->index], 133 tmp102_mC_to_reg(val));
133 tmp102_mC_to_reg(val));
134 }
135 mutex_unlock(&tmp102->lock); 134 mutex_unlock(&tmp102->lock);
136 return status ? : count; 135 return status ? : count;
137} 136}
@@ -164,9 +163,10 @@ static int __devinit tmp102_probe(struct i2c_client *client,
164 struct tmp102 *tmp102; 163 struct tmp102 *tmp102;
165 int status; 164 int status;
166 165
167 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | 166 if (!i2c_check_functionality(client->adapter,
168 I2C_FUNC_SMBUS_WORD_DATA)) { 167 I2C_FUNC_SMBUS_WORD_DATA)) {
169 dev_dbg(&client->dev, "adapter doesnt support SMBUS\n"); 168 dev_err(&client->dev, "adapter doesnt support SMBus word "
169 "transactions\n");
170 return -ENODEV; 170 return -ENODEV;
171 } 171 }
172 172
@@ -177,16 +177,20 @@ static int __devinit tmp102_probe(struct i2c_client *client,
177 } 177 }
178 i2c_set_clientdata(client, tmp102); 178 i2c_set_clientdata(client, tmp102);
179 179
180 tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG); 180 status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
181 if (status < 0) {
182 dev_err(&client->dev, "error writing config register\n");
183 goto fail0;
184 }
181 status = tmp102_read_reg(client, TMP102_CONF_REG); 185 status = tmp102_read_reg(client, TMP102_CONF_REG);
182 if (status < 0) { 186 if (status < 0) {
183 dev_dbg(&client->dev, "error reading config register\n"); 187 dev_err(&client->dev, "error reading config register\n");
184 goto fail0; 188 goto fail0;
185 } 189 }
186 status &= ~TMP102_CONFIG_RD_ONLY; 190 status &= ~TMP102_CONFIG_RD_ONLY;
187 if (status != TMP102_CONFIG) { 191 if (status != TMP102_CONFIG) {
188 dev_dbg(&client->dev, "could not verify config settings\n"); 192 dev_err(&client->dev, "config settings did not stick\n");
189 status = -EIO; 193 status = -ENODEV;
190 goto fail0; 194 goto fail0;
191 } 195 }
192 tmp102->last_update = jiffies - HZ; 196 tmp102->last_update = jiffies - HZ;
@@ -213,7 +217,7 @@ fail0:
213 i2c_set_clientdata(client, NULL); 217 i2c_set_clientdata(client, NULL);
214 kfree(tmp102); 218 kfree(tmp102);
215 219
216 return 0; 220 return status;
217} 221}
218 222
219static int __devexit tmp102_remove(struct i2c_client *client) 223static int __devexit tmp102_remove(struct i2c_client *client)
@@ -260,23 +264,18 @@ static const struct dev_pm_ops tmp102_dev_pm_ops = {
260#define TMP102_DEV_PM_OPS NULL 264#define TMP102_DEV_PM_OPS NULL
261#endif /* CONFIG_PM */ 265#endif /* CONFIG_PM */
262 266
263static const unsigned short normal_i2c[] = {
264 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END
265};
266
267static const struct i2c_device_id tmp102_id[] = { 267static const struct i2c_device_id tmp102_id[] = {
268 { DRIVER_NAME, 0 }, 268 { "tmp102", 0 },
269 { } 269 { }
270}; 270};
271MODULE_DEVICE_TABLE(i2c, tmp102_id);
271 272
272static struct i2c_driver tmp102_driver = { 273static struct i2c_driver tmp102_driver = {
273 .driver.name = DRIVER_NAME, 274 .driver.name = DRIVER_NAME,
274 .driver.pm = TMP102_DEV_PM_OPS, 275 .driver.pm = TMP102_DEV_PM_OPS,
275 .class = I2C_CLASS_HWMON,
276 .probe = tmp102_probe, 276 .probe = tmp102_probe,
277 .remove = __devexit_p(tmp102_remove), 277 .remove = __devexit_p(tmp102_remove),
278 .id_table = tmp102_id, 278 .id_table = tmp102_id,
279 .address_list = normal_i2c,
280}; 279};
281 280
282static int __init tmp102_init(void) 281static int __init tmp102_init(void)
@@ -291,7 +290,6 @@ static void __exit tmp102_exit(void)
291} 290}
292module_exit(tmp102_exit); 291module_exit(tmp102_exit);
293 292
294
295MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); 293MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
296MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); 294MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
297MODULE_LICENSE("GPL"); 295MODULE_LICENSE("GPL");