[PATCH 2/3] lm90: Support MAX6646, MAX6647 and MAX6649

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ben,

On Thu, 10 Jul 2008 15:59:35 +0100, Ben Hutchings wrote:
> These Maxim chips are similar to MAX6657 but use unsigned temperature
> values to allow for readings up to 145 degrees.
> 
> Signed-off-by: Ben Hutchings <bhutchings at solarflare.com>
> ---
>  drivers/hwmon/Kconfig |    3 +-
>  drivers/hwmon/lm90.c  |   67 ++++++++++++++++++++++++++++++++++++++----------
>  2 files changed, 55 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index b8ab275..cc40c88 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -485,7 +485,8 @@ config SENSORS_LM90
>  	help
>  	  If you say yes here you get support for National Semiconductor LM90,
>  	  LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
> -	  MAX6657, MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
> +	  MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and
> +	  MAX6681 sensor chips.
>  
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called lm90.
> diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
> index 9ee7e3a..dbf0dfe 100644
> --- a/drivers/hwmon/lm90.c
> +++ b/drivers/hwmon/lm90.c
> @@ -25,9 +25,10 @@
>   * that are not handled by this driver. Among others, it has a higher
>   * accuracy than the LM90, much like the LM86 does.
>   *
> - * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
> - * chips made by Maxim. These chips are similar to the LM86.
> - * Note that there is no easy way to differentiate between the three
> + * This driver also supports the MAX6646, MAX6647, MAX6649, MAX6657,
> + * MAX6658 and MAX6659 sensor chips made by Maxim. These chips are
> + * similar to the LM86.

This isn't really correct. While the MAX6657, MAX6658 and MAX6659 are
indeed similar to the LM86, the MAX6646, MAX6647 and MAX6649 use a
different temperature encoding to support a different temperature range.

> + * Note that there is no easy way to differentiate between the MAX665x
>   * variants. The extra address and features of the MAX6659 are not
>   * supported by this driver. These chips lack the remote temperature
>   * offset feature.

This is also not totally correct, you can differentiate between the
MAX6657 and the MAX6646 (different device ID register value).

So, please make a separate paragraph for the MAX6646, MAX6647 and
MAX6649 chips, instead of merging them in the MAX6657 paragraph.

Your patch should also update Documentation/hwmon/lm90 to mention the
newly supported chips.

> @@ -76,9 +77,10 @@
>   * Addresses to scan
>   * Address is fully defined internally and cannot be changed except for
>   * MAX6659, MAX6680 and MAX6681.
> - * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
> - * have address 0x4c.
> - * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
> + * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657
> + * and MAX6658 have address 0x4c.
> + * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
> + * MAX6647 has address 0x4e.
>   * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
>   * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
>   * 0x4c, 0x4d or 0x4e.
> @@ -91,7 +93,8 @@ static const unsigned short normal_i2c[] = {
>   * Insmod parameters
>   */
>  
> -I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
> +I2C_CLIENT_INSMOD_8(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680,
> +		    max6646);
>  
>  /*
>   * The LM90 registers
> @@ -132,7 +135,7 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
>  #define LM90_REG_R_TCRIT_HYST		0x21
>  #define LM90_REG_W_TCRIT_HYST		0x21
>  
> -/* MAX6657-specific registers */
> +/* MAX6646/6647/6649/6657/6658/6659 registers */
>  
>  #define MAX6657_REG_R_LOCAL_TEMPL	0x11
>  
> @@ -185,7 +188,7 @@ struct lm90_data {
>  	s16 temp11[5];	/* 0: remote input
>  			   1: remote low limit
>  			   2: remote high limit
> -			   3: remote offset (except max6657)
> +			   3: remote offset (except max6646 and max6657)
>  			   4: local input */
>  	u8 temp_hyst;
>  	u8 alarms; /* bitvector */
> @@ -197,6 +200,8 @@ struct lm90_data {
>   * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
>   * For remote temperatures and limits, it uses signed 11-bit values with
>   * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
> + * Some Maxim chips use 16-bit signed or unsigned values for local and
> + * both remote temperatures.

That's a bit confusing, makes it sound like the same chip can do both,
and also that these chips have 16 bits of actual resolution. I am also
not aware of any of these chips supporting two external temperature
sensors? What about just:

 * Some Maxim chips use unsigned values instead.

>   */
>  
>  static inline int temp_from_s8(s8 val)
> @@ -204,11 +209,21 @@ static inline int temp_from_s8(s8 val)
>  	return val * 1000;
>  }
>  
> +static inline int temp_from_u8(u8 val)
> +{
> +	return val * 1000;
> +}
> +
>  static inline int temp_from_s16(s16 val)
>  {
>  	return val / 32 * 125;
>  }
>  
> +static inline int temp_from_u16(u16 val)
> +{
> +	return val / 32 * 125;
> +}
> +
>  static s8 temp_to_s8(long val)
>  {
>  	if (val <= -128000)
> @@ -220,6 +235,15 @@ static s8 temp_to_s8(long val)
>  	return (val + 500) / 1000;
>  }
>  
> +static u8 temp_to_u8(long val)
> +{
> +	if (val <= 0)
> +		return 0;
> +	if (val >= 255000)
> +		return 255;
> +	return (val + 500) / 1000;
> +}
> +
>  static s16 temp_to_s16(long val)
>  {
>  	if (val <= -128000)
> @@ -311,6 +335,8 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
>  
>  	if (data->kind == adt7461)
>  		temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
> +	else if (data->kind == max6646)
> +		temp = temp_from_u8(data->temp8[attr->index]);
>  	else
>  		temp = temp_from_s8(data->temp8[attr->index]);
>  
> @@ -336,6 +362,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
>  	mutex_lock(&data->update_lock);
>  	if (data->kind == adt7461)
>  		data->temp8[nr] = temp_to_u8_adt7461(data, val);
> +	else if (data->kind == max6646)
> +		data->temp8[nr] = temp_to_u8(val);
>  	else
>  		data->temp8[nr] = temp_to_s8(val);
>  	i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
> @@ -352,6 +380,8 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
>  
>  	if (data->kind == adt7461)
>  		temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
> +	else if (data->kind == max6646)
> +		temp = temp_from_u16(data->temp11[attr->index]);
>  	else
>  		temp = temp_from_s16(data->temp11[attr->index]);
>  
> @@ -381,12 +411,15 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
>  		data->temp11[nr] = temp_to_u16_adt7461(data, val);
>  	else if (data->kind == max6657 || data->kind == max6680)
>  		data->temp11[nr] = temp_to_s8(val) << 8;
> +	else if (data->kind == max6646)
> +		data->temp11[nr] = temp_to_u8(val) << 8;
>  	else
>  		data->temp11[nr] = temp_to_s16(val);
>  
>  	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
>  				  data->temp11[nr] >> 8);
> -	if (data->kind != max6657 && data->kind != max6680)
> +	if (data->kind != max6657 && data->kind != max6680
> +	    && data->kind != max6646)
>  		i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
>  					  data->temp11[nr] & 0xff);
>  	mutex_unlock(&data->update_lock);
> @@ -696,6 +729,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
>  			 && (reg_config1 & 0x03) == 0x00
>  			 && reg_convrate <= 0x07) {
>  			 	kind = max6680;
> +			} else if (chip_id == 0x59) {
> +				kind = max6646;

I see no reason why you wouldn't check the config and conversion rate
registers as we do for all other chips, to make detection a bit more
reliable.

>  			}
>  		}
>  
> @@ -725,6 +760,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
>  		name = "max6680";
>  	} else if (kind == adt7461) {
>  		name = "adt7461";
> +	} else if (kind == max6646) {
> +		name = "max6646";
>  	}
>  
>  	/* We can fill in the remaining client fields */
> @@ -748,7 +785,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
>  					      &dev_attr_pec)))
>  			goto exit_remove_files;
>  	}
> -	if (data->kind != max6657) {
> +	if (data->kind != max6657 && data->kind != max6646) {
>  		if ((err = device_create_file(&new_client->dev,
>  				&sensor_dev_attr_temp2_offset.dev_attr)))
>  			goto exit_remove_files;
> @@ -811,7 +848,7 @@ static int lm90_detach_client(struct i2c_client *client)
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm90_group);
>  	device_remove_file(&client->dev, &dev_attr_pec);
> -	if (data->kind != max6657)
> +	if (data->kind != max6657 && data->kind != max6646)
>  		device_remove_file(&client->dev,
>  				   &sensor_dev_attr_temp2_offset.dev_attr);
>  
> @@ -871,7 +908,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
>  		lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
>  		lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
>  
> -		if (data->kind == max6657) {
> +		if (data->kind == max6657 || data->kind == max6646) {
>  			lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
>  				    MAX6657_REG_R_LOCAL_TEMPL,
>  				    &data->temp11[4]);
> @@ -886,6 +923,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
>  		if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
>  			data->temp11[1] = h << 8;
>  			if (data->kind != max6657 && data->kind != max6680
> +			 && data->kind != max6646
>  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
>  					  &l) == 0)
>  				data->temp11[1] |= l;
> @@ -893,12 +931,13 @@ static struct lm90_data *lm90_update_device(struct device *dev)
>  		if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
>  			data->temp11[2] = h << 8;
>  			if (data->kind != max6657 && data->kind != max6680
> +			 && data->kind != max6646
>  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
>  					  &l) == 0)
>  				data->temp11[2] |= l;
>  		}
>  
> -		if (data->kind != max6657) {
> +		if (data->kind != max6657 && data->kind != max6646) {
>  			if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
>  					  &h) == 0
>  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,

All the rest looks good.

-- 
Jean Delvare




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux