[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.sig>


More information about the lm-sensors mailing list