aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/hwmon/tmp1029
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/hwmon/tmp102.c70
3 files changed, 39 insertions, 42 deletions
diff --git a/Documentation/hwmon/tmp102 b/Documentation/hwmon/tmp102
index 239dded8539f..8454a7763122 100644
--- a/Documentation/hwmon/tmp102
+++ b/Documentation/hwmon/tmp102
@@ -4,7 +4,7 @@ Kernel driver tmp102
4Supported chips: 4Supported chips:
5 * Texas Instruments TMP102 5 * Texas Instruments TMP102
6 Prefix: 'tmp102' 6 Prefix: 'tmp102'
7 Addresses scanned: I2C 0x48 0x49 0x4a 0x4b 7 Addresses scanned: none
8 Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp102.html 8 Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp102.html
9 9
10Author: 10Author:
@@ -15,13 +15,12 @@ Description
15 15
16The Texas Instruments TMP102 implements one temperature sensor. Limits can be 16The Texas Instruments TMP102 implements one temperature sensor. Limits can be
17set through the Overtemperature Shutdown register and Hysteresis register. The 17set through the Overtemperature Shutdown register and Hysteresis register. The
18sensor is accurate to 0.5 degrees over the range of -25 to +85 C, and to 1.0 18sensor is accurate to 0.5 degree over the range of -25 to +85 C, and to 1.0
19degrees from -40 to +125 C. Resolution of the sensor is 0.0625 degree. The 19degree from -40 to +125 C. Resolution of the sensor is 0.0625 degree. The
20operating temperature has a minimum of -55 C and a maximum of +150 C. 20operating temperature has a minimum of -55 C and a maximum of +150 C.
21 21
22The TMP102 has a programmable update rate that can select between 8, 4, 1, and 22The TMP102 has a programmable update rate that can select between 8, 4, 1, and
230.5 Hz. (Currently the driver only supports the default of 4 Hz). 230.5 Hz. (Currently the driver only supports the default of 4 Hz).
24 24
25The driver provides the common sysfs-interface for temperatures (see 25The driver provides the common sysfs-interface for temperatures (see
26/Documentation/hwmon/sysfs-interface under Temperatures). 26Documentation/hwmon/sysfs-interface under Temperatures).
27
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");