hwmon: (lm90) Support MAX6646, MAX6647 and MAX6649

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@solarflare.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Ben Hutchings 2008-10-17 17:51:11 +02:00 committed by Jean Delvare
parent 9d4d383422
commit 271dabf5bb
3 changed files with 82 additions and 13 deletions

View File

@ -32,6 +32,21 @@ Supported chips:
Addresses scanned: I2C 0x4c and 0x4d
Datasheet: Publicly available at the ON Semiconductor website
http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
* Maxim MAX6646
Prefix: 'max6646'
Addresses scanned: I2C 0x4d
Datasheet: Publicly available at the Maxim website
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
* Maxim MAX6647
Prefix: 'max6646'
Addresses scanned: I2C 0x4e
Datasheet: Publicly available at the Maxim website
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
* Maxim MAX6649
Prefix: 'max6646'
Addresses scanned: I2C 0x4c
Datasheet: Publicly available at the Maxim website
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
* Maxim MAX6657
Prefix: 'max6657'
Addresses scanned: I2C 0x4c

View File

@ -511,7 +511,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.

View File

@ -32,6 +32,11 @@
* supported by this driver. These chips lack the remote temperature
* offset feature.
*
* This driver also supports the MAX6646, MAX6647 and MAX6649 chips
* made by Maxim. These are again similar to the LM86, but they use
* unsigned temperature values and can report temperatures from 0 to
* 145 degrees.
*
* This driver also supports the MAX6680 and MAX6681, two other sensor
* chips made by Maxim. These are quite similar to the other Maxim
* chips. The MAX6680 and MAX6681 only differ in the pinout so they can
@ -76,9 +81,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 +97,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 +139,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
@ -164,6 +171,9 @@ static const struct i2c_device_id lm90_id[] = {
{ "lm86", lm86 },
{ "lm89", lm99 },
{ "lm99", lm99 }, /* Missing temperature offset */
{ "max6646", max6646 },
{ "max6647", max6646 },
{ "max6649", max6646 },
{ "max6657", max6657 },
{ "max6658", max6657 },
{ "max6659", max6657 },
@ -205,7 +215,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 */
@ -216,7 +226,8 @@ struct lm90_data {
* For local temperatures and limits, critical limits and the hysteresis
* 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.
* LSB = 0.125 degree Celsius, left-justified in 16-bit registers. Some
* Maxim chips use unsigned values.
*/
static inline int temp_from_s8(s8 val)
@ -224,11 +235,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)
@ -240,6 +261,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)
@ -331,6 +361,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]);
@ -356,6 +388,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]);
@ -372,6 +406,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]);
@ -401,12 +437,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);
@ -689,6 +728,16 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
&& (reg_config1 & 0x03) == 0x00
&& reg_convrate <= 0x07) {
kind = max6680;
} else
/* The chip_id register of the MAX6646/6647/6649
* holds the revision of the chip.
* The lowest 6 bits of the config1 register are
* unused and should return zero when read.
*/
if (chip_id == 0x59
&& (reg_config1 & 0x3f) == 0x00
&& reg_convrate <= 0x07) {
kind = max6646;
}
}
@ -719,6 +768,8 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
name = "max6680";
} else if (kind == adt7461) {
name = "adt7461";
} else if (kind == max6646) {
name = "max6646";
}
strlcpy(info->type, name, I2C_NAME_SIZE);
@ -758,7 +809,7 @@ static int lm90_probe(struct i2c_client *new_client,
&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;
@ -824,7 +875,7 @@ static int lm90_remove(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);
@ -881,7 +932,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]);
@ -896,6 +947,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;
@ -903,12 +955,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,