aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
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
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')
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/hwmon/tmp102.c70
2 files changed, 35 insertions, 37 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 6d87892a6639..de22ae41f758 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -843,7 +843,7 @@ config SENSORS_THMC50
843 will be called thmc50. 843 will be called thmc50.
844 844
845config SENSORS_TMP102 845config SENSORS_TMP102
846 tristate "Texas Instruments TMP102 and compatibles" 846 tristate "Texas Instruments TMP102"
847 depends on I2C && EXPERIMENTAL 847 depends on I2C && EXPERIMENTAL
848 help 848 help
849 If you say yes here you get support for Texas Instruments TMP102 849 If you say yes here you get support for Texas Instruments TMP102
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");