瀏覽代碼

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>
Jean Delvare 15 年之前
父節點
當前提交
cff37c9e82
共有 3 個文件被更改,包括 39 次插入42 次删除
  1. 4 5
      Documentation/hwmon/tmp102
  2. 1 1
      drivers/hwmon/Kconfig
  3. 34 36
      drivers/hwmon/tmp102.c

+ 4 - 5
Documentation/hwmon/tmp102

@@ -4,7 +4,7 @@ Kernel driver tmp102
 Supported chips:
 Supported chips:
   * Texas Instruments TMP102
   * Texas Instruments TMP102
     Prefix: 'tmp102'
     Prefix: 'tmp102'
-    Addresses scanned: I2C 0x48 0x49 0x4a 0x4b
+    Addresses scanned: none
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp102.html
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp102.html
 
 
 Author:
 Author:
@@ -15,13 +15,12 @@ Description
 
 
 The Texas Instruments TMP102 implements one temperature sensor.  Limits can be
 The Texas Instruments TMP102 implements one temperature sensor.  Limits can be
 set through the Overtemperature Shutdown register and Hysteresis register.  The
 set through the Overtemperature Shutdown register and Hysteresis register.  The
-sensor is accurate to 0.5 degrees over the range of -25 to +85 C, and to 1.0
-degrees from -40 to +125 C. Resolution of the sensor is 0.0625 degree.  The
+sensor is accurate to 0.5 degree over the range of -25 to +85 C, and to 1.0
+degree from -40 to +125 C. Resolution of the sensor is 0.0625 degree.  The
 operating temperature has a minimum of -55 C and a maximum of +150 C.
 operating temperature has a minimum of -55 C and a maximum of +150 C.
 
 
 The TMP102 has a programmable update rate that can select between 8, 4, 1, and
 The TMP102 has a programmable update rate that can select between 8, 4, 1, and
 0.5 Hz. (Currently the driver only supports the default of 4 Hz).
 0.5 Hz. (Currently the driver only supports the default of 4 Hz).
 
 
 The driver provides the common sysfs-interface for temperatures (see
 The driver provides the common sysfs-interface for temperatures (see
-/Documentation/hwmon/sysfs-interface under Temperatures).
-
+Documentation/hwmon/sysfs-interface under Temperatures).

+ 1 - 1
drivers/hwmon/Kconfig

@@ -843,7 +843,7 @@ config SENSORS_THMC50
 	  will be called thmc50.
 	  will be called thmc50.
 
 
 config SENSORS_TMP102
 config SENSORS_TMP102
-	tristate "Texas Instruments TMP102 and compatibles"
+	tristate "Texas Instruments TMP102"
 	depends on I2C && EXPERIMENTAL
 	depends on I2C && EXPERIMENTAL
 	help
 	help
 	  If you say yes here you get support for Texas Instruments TMP102
 	  If you say yes here you get support for Texas Instruments TMP102

+ 34 - 36
drivers/hwmon/tmp102.c

@@ -1,6 +1,6 @@
-/* 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -17,8 +17,6 @@
  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  */
  */
 
 
-
-
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -27,7 +25,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
+#include <linux/device.h>
 
 
 #define	DRIVER_NAME "tmp102"
 #define	DRIVER_NAME "tmp102"
 
 
@@ -56,26 +54,27 @@ struct tmp102 {
 	int temp[3];
 	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);
 	int result = i2c_smbus_read_word_data(client, reg);
 	return result < 0 ? result : swab16(result);
 	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));
 	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;
 	return (val * 128) / 1000;
 }
 }
@@ -91,7 +90,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
 
 	mutex_lock(&tmp102->lock);
 	mutex_lock(&tmp102->lock);
-	if (time_after(jiffies, tmp102->last_update + HZ / 4)) {
+	if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
 		int i;
 		int i;
 		for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
 		for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
 			int status = tmp102_read_reg(client, tmp102_reg[i]);
 			int status = tmp102_read_reg(client, tmp102_reg[i]);
@@ -122,16 +121,16 @@ static ssize_t tmp102_set_temp(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 	long val;
 	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;
 		return -EINVAL;
+	val = SENSORS_LIMIT(val, -256000, 255000);
+
 	mutex_lock(&tmp102->lock);
 	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);
 	mutex_unlock(&tmp102->lock);
 	return status ? : count;
 	return status ? : count;
 }
 }
@@ -164,9 +163,10 @@ static int __devinit tmp102_probe(struct i2c_client *client,
 	struct tmp102 *tmp102;
 	struct tmp102 *tmp102;
 	int status;
 	int status;
 
 
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA)) {
 				     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;
 		return -ENODEV;
 	}
 	}
 
 
@@ -177,16 +177,20 @@ static int __devinit tmp102_probe(struct i2c_client *client,
 	}
 	}
 	i2c_set_clientdata(client, tmp102);
 	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);
 	status = tmp102_read_reg(client, TMP102_CONF_REG);
 	if (status < 0) {
 	if (status < 0) {
-		dev_dbg(&client->dev, "error reading config register\n");
+		dev_err(&client->dev, "error reading config register\n");
 		goto fail0;
 		goto fail0;
 	}
 	}
 	status &= ~TMP102_CONFIG_RD_ONLY;
 	status &= ~TMP102_CONFIG_RD_ONLY;
 	if (status != TMP102_CONFIG) {
 	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;
 		goto fail0;
 	}
 	}
 	tmp102->last_update = jiffies - HZ;
 	tmp102->last_update = jiffies - HZ;
@@ -213,7 +217,7 @@ fail0:
 	i2c_set_clientdata(client, NULL);
 	i2c_set_clientdata(client, NULL);
 	kfree(tmp102);
 	kfree(tmp102);
 
 
-	return 0;
+	return status;
 }
 }
 
 
 static int __devexit tmp102_remove(struct i2c_client *client)
 static int __devexit tmp102_remove(struct i2c_client *client)
@@ -260,23 +264,18 @@ static const struct dev_pm_ops tmp102_dev_pm_ops = {
 #define	TMP102_DEV_PM_OPS NULL
 #define	TMP102_DEV_PM_OPS NULL
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */
 
 
-static const unsigned short normal_i2c[] = {
-	0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END
-};
-
 static const struct i2c_device_id tmp102_id[] = {
 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 = {
 static struct i2c_driver tmp102_driver = {
 	.driver.name	= DRIVER_NAME,
 	.driver.name	= DRIVER_NAME,
 	.driver.pm	= TMP102_DEV_PM_OPS,
 	.driver.pm	= TMP102_DEV_PM_OPS,
-	.class		= I2C_CLASS_HWMON,
 	.probe		= tmp102_probe,
 	.probe		= tmp102_probe,
 	.remove		= __devexit_p(tmp102_remove),
 	.remove		= __devexit_p(tmp102_remove),
 	.id_table	= tmp102_id,
 	.id_table	= tmp102_id,
-	.address_list	= normal_i2c,
 };
 };
 
 
 static int __init tmp102_init(void)
 static int __init tmp102_init(void)
@@ -291,7 +290,6 @@ static void __exit tmp102_exit(void)
 }
 }
 module_exit(tmp102_exit);
 module_exit(tmp102_exit);
 
 
-
 MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
 MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
 MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
 MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");