diff options
author | Jean Delvare <khali@linux-fr.org> | 2010-05-27 19:58:57 +0200 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2010-05-27 19:58:57 +0200 |
commit | cff37c9e82e022068840b3d33167e64c6a0ecc06 (patch) | |
tree | 8ebce4d6d8cbc16a661e6548515d02f43d66ad58 /drivers/hwmon | |
parent | beb1b6bbf2b448b97b9611200eb4b5a555336c60 (diff) | |
download | lwn-cff37c9e82e022068840b3d33167e64c6a0ecc06.tar.gz lwn-cff37c9e82e022068840b3d33167e64c6a0ecc06.zip |
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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hwmon/tmp102.c | 70 |
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 will be called thmc50. config SENSORS_TMP102 - tristate "Texas Instruments TMP102 and compatibles" + tristate "Texas Instruments TMP102" depends on I2C && EXPERIMENTAL help 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 @@ -/* 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 @@ -17,8 +17,6 @@ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA */ - - #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -27,7 +25,7 @@ #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" @@ -56,26 +54,27 @@ struct 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; } @@ -91,7 +90,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client) 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]); @@ -122,16 +121,16 @@ static ssize_t tmp102_set_temp(struct device *dev, 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; } @@ -164,9 +163,10 @@ static int __devinit tmp102_probe(struct i2c_client *client, 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; } @@ -177,16 +177,20 @@ static int __devinit tmp102_probe(struct i2c_client *client, } 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; @@ -213,7 +217,7 @@ fail0: i2c_set_clientdata(client, NULL); kfree(tmp102); - return 0; + return status; } 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 #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) @@ -291,7 +290,6 @@ static void __exit tmp102_exit(void) } module_exit(tmp102_exit); - MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); MODULE_LICENSE("GPL"); |