[lm-sensors] [patch 2.6.25-rc9 3/5] lm75: support 12-bit resolution
Laurent Pinchart
laurentp at cse-semaphore.com
Tue Apr 22 14:38:06 CEST 2008
Hi David,
On Wednesday 16 April 2008 19:30, David Brownell wrote:
> Make the lm75 driver so that use the best resolution available on
> each chip it finds ... usually this is 12 bits (0.0625 degrees C).
>
> Note that this preserves the quirky "round away from zero" behavior
> for converting temperatures to sensor values. (I'd think no rounding
> at all would be better.)
>
> Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>
> ---
> drivers/hwmon/Kconfig | 4 +++-
> drivers/hwmon/lm75.c | 44 ++++++++++++++++++++++++++++++++++++--------
> 2 files changed, 39 insertions(+), 9 deletions(-)
>
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -391,7 +391,9 @@ config SENSORS_LM75
> - Texas Instruments TMP100, TMP101, TMP75, TMP175, TMP275
>
> This driver supports driver model based binding through board
> - specific I2C device tables.
> + specific I2C device tables. When those tables report a chip
> + type that's recognized as supporting it, this driver uses 12-bit
> + sample resolution (to 1/16 degree C).
>
> It also supports the "legacy" style of driver binding. To use
> that with some chips which don't replicate LM75 quirks exactly,
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,7 +27,6 @@
> #include <linux/hwmon-sysfs.h>
> #include <linux/err.h>
> #include <linux/mutex.h>
> -#include "lm75.h"
>
>
> /*
> @@ -65,6 +64,8 @@ struct lm75_data {
> 0 = input
> 1 = max
> 2 = hyst */
> + u16 round; /* f(resolution) */
> + u16 mask;
> };
>
> static int lm75_read_value(struct i2c_client *client, u8 reg);
> @@ -74,7 +75,7 @@ static struct lm75_data *lm75_update_dev
>
> /*-----------------------------------------------------------------------*/
>
> -/* sysfs attributes for hwmon */
> +/* sysfs attributes for hwmon, handling any sample resolution */
>
> static inline s16 temp_to_reg(struct lm75_data *lm75, long temp)
> {
> @@ -83,12 +84,19 @@ static inline s16 temp_to_reg(struct lm7
> else if (temp > lm75->max)
> temp = lm75->max;
>
> - return LM75_TEMP_TO_REG(temp);
> + /* "Round away from zero" -- unusual but backwards-compatible.
> + * Rounding should really be done *after* conversion.
> + */
> + temp += (temp < 0) ? -lm75->round : lm75->round;
> + return ((temp * 256) / 1000) & lm75->mask;
> }
>
> static inline int reg_to_temp(s16 reg)
> {
> - return LM75_TEMP_FROM_REG(reg);
> + /* Use integer division instead of logical right shift to
> + * preserve sign (compiler uses arithmetic right shift).
> + */
> + return (reg * 1000) / 256;
> }
>
> static ssize_t show_temp(struct device *dev, struct device_attribute *da,
> @@ -97,7 +105,8 @@ static ssize_t show_temp(struct device *
> struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
> struct lm75_data *data = lm75_update_device(dev);
>
> - return sprintf(buf, "%d\n", reg_to_temp(data->temp[attr->index]));
> + return sprintf(buf, "%d\n",
> + reg_to_temp(data->temp[attr->index]) & data->mask);
This should be
return sprintf(buf, "%d\n",
reg_to_temp(data->temp[attr->index] & data->mask));
> }
>
> static ssize_t set_temp(struct device *dev, struct device_attribute *da,
> @@ -144,6 +153,7 @@ static int lm75_probe(struct i2c_client
> int status;
> u8 set_mask, clr_mask;
> int new;
> + int resolution;
>
> if (!i2c_check_functionality(client->adapter,
> I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
> @@ -163,13 +173,27 @@ static int lm75_probe(struct i2c_client
> set_mask = 0;
> clr_mask = (1 << 0) /* continuous conversions */
> | (1 << 6) | (1 << 5); /* 9-bit mode */
> + resolution = 9;
>
> data->min = -55 * 1000;
> data->max = 125 * 1000;
>
> /* for tmp175 or tmp275, use name "tmp75" */
> - if (strcmp(client->name, "tmp75") == 0)
> + if (strcmp(client->name, "tmp75") == 0) {
> data->min = -40 * 1000;
> + set_mask |= (1 << 6) | (1 << 5);
> + resolution = 12;
> +
> + /* for ds1775, use name "ds75" */
> + } else if (strcmp(client->name, "ds75") == 0
> + || strcmp(client->name, "mcp980x") == 0
> + || strcmp(client->name, "tmp100") == 0
> + || strcmp(client->name, "tmp101") == 0) {
> + set_mask |= (1 << 6) | (1 << 5);
> + resolution = 12;
> +
> + } else if (strcmp(client->name, "max6626") == 0)
> + resolution = 12;
>
> /* NOTE: also need to ensure that the chip is in interrupt mode
> * in various cases, and maybe handle SMBALERT#.
> @@ -188,6 +212,9 @@ static int lm75_probe(struct i2c_client
> lm75_write_value(client, LM75_REG_CONF, new);
> dev_dbg(&client->dev, "Config %02x\n", new);
>
> + data->round = 500 / (1 << (resolution - 8));
> + data->mask = ~((1 << (16 - resolution)) - 1);
> +
> /* Register sysfs hooks */
> if ((status = sysfs_create_group(&client->dev.kobj, &lm75_group)))
> goto exit_free;
> @@ -198,8 +225,9 @@ static int lm75_probe(struct i2c_client
> goto exit_remove;
> }
>
> - dev_info(&client->dev, "%s: sensor '%s'\n",
> - data->hwmon_dev->bus_id, client->name);
> + dev_info(&client->dev,
> + "%s: sensor '%s', resolution %d millidegrees C\n",
> + data->hwmon_dev->bus_id, client->name, data->round * 2);
>
> return 0;
>
>
>
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20080422/6625e321/attachment.bin
More information about the lm-sensors
mailing list