Commit 271dabf5 authored by Ben Hutchings's avatar Ben Hutchings Committed by Jean Delvare

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 9d4d3834
...@@ -32,6 +32,21 @@ Supported chips: ...@@ -32,6 +32,21 @@ Supported chips:
Addresses scanned: I2C 0x4c and 0x4d Addresses scanned: I2C 0x4c and 0x4d
Datasheet: Publicly available at the ON Semiconductor website Datasheet: Publicly available at the ON Semiconductor website
http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461 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 * Maxim MAX6657
Prefix: 'max6657' Prefix: 'max6657'
Addresses scanned: I2C 0x4c Addresses scanned: I2C 0x4c
......
...@@ -511,7 +511,8 @@ config SENSORS_LM90 ...@@ -511,7 +511,8 @@ config SENSORS_LM90
help help
If you say yes here you get support for National Semiconductor LM90, If you say yes here you get support for National Semiconductor LM90,
LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim 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 This driver can also be built as a module. If so, the module
will be called lm90. will be called lm90.
......
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
* supported by this driver. These chips lack the remote temperature * supported by this driver. These chips lack the remote temperature
* offset feature. * 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 * This driver also supports the MAX6680 and MAX6681, two other sensor
* chips made by Maxim. These are quite similar to the other Maxim * 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 * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
...@@ -76,9 +81,10 @@ ...@@ -76,9 +81,10 @@
* Addresses to scan * Addresses to scan
* Address is fully defined internally and cannot be changed except for * Address is fully defined internally and cannot be changed except for
* MAX6659, MAX6680 and MAX6681. * MAX6659, MAX6680 and MAX6681.
* LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658 * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657
* have address 0x4c. * and MAX6658 have address 0x4c.
* ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d. * 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). * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
* MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
* 0x4c, 0x4d or 0x4e. * 0x4c, 0x4d or 0x4e.
...@@ -91,7 +97,8 @@ static const unsigned short normal_i2c[] = { ...@@ -91,7 +97,8 @@ static const unsigned short normal_i2c[] = {
* Insmod parameters * 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 * The LM90 registers
...@@ -132,7 +139,7 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); ...@@ -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_R_TCRIT_HYST 0x21
#define LM90_REG_W_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 #define MAX6657_REG_R_LOCAL_TEMPL 0x11
...@@ -164,6 +171,9 @@ static const struct i2c_device_id lm90_id[] = { ...@@ -164,6 +171,9 @@ static const struct i2c_device_id lm90_id[] = {
{ "lm86", lm86 }, { "lm86", lm86 },
{ "lm89", lm99 }, { "lm89", lm99 },
{ "lm99", lm99 }, /* Missing temperature offset */ { "lm99", lm99 }, /* Missing temperature offset */
{ "max6646", max6646 },
{ "max6647", max6646 },
{ "max6649", max6646 },
{ "max6657", max6657 }, { "max6657", max6657 },
{ "max6658", max6657 }, { "max6658", max6657 },
{ "max6659", max6657 }, { "max6659", max6657 },
...@@ -205,7 +215,7 @@ struct lm90_data { ...@@ -205,7 +215,7 @@ struct lm90_data {
s16 temp11[5]; /* 0: remote input s16 temp11[5]; /* 0: remote input
1: remote low limit 1: remote low limit
2: remote high limit 2: remote high limit
3: remote offset (except max6657) 3: remote offset (except max6646 and max6657)
4: local input */ 4: local input */
u8 temp_hyst; u8 temp_hyst;
u8 alarms; /* bitvector */ u8 alarms; /* bitvector */
...@@ -216,7 +226,8 @@ struct lm90_data { ...@@ -216,7 +226,8 @@ struct lm90_data {
* For local temperatures and limits, critical limits and the hysteresis * For local temperatures and limits, critical limits and the hysteresis
* value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius. * 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 * 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) static inline int temp_from_s8(s8 val)
...@@ -224,11 +235,21 @@ static inline int temp_from_s8(s8 val) ...@@ -224,11 +235,21 @@ static inline int temp_from_s8(s8 val)
return val * 1000; return val * 1000;
} }
static inline int temp_from_u8(u8 val)
{
return val * 1000;
}
static inline int temp_from_s16(s16 val) static inline int temp_from_s16(s16 val)
{ {
return val / 32 * 125; return val / 32 * 125;
} }
static inline int temp_from_u16(u16 val)
{
return val / 32 * 125;
}
static s8 temp_to_s8(long val) static s8 temp_to_s8(long val)
{ {
if (val <= -128000) if (val <= -128000)
...@@ -240,6 +261,15 @@ static s8 temp_to_s8(long val) ...@@ -240,6 +261,15 @@ static s8 temp_to_s8(long val)
return (val + 500) / 1000; 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) static s16 temp_to_s16(long val)
{ {
if (val <= -128000) if (val <= -128000)
...@@ -331,6 +361,8 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, ...@@ -331,6 +361,8 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
if (data->kind == adt7461) if (data->kind == adt7461)
temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
else if (data->kind == max6646)
temp = temp_from_u8(data->temp8[attr->index]);
else else
temp = temp_from_s8(data->temp8[attr->index]); temp = temp_from_s8(data->temp8[attr->index]);
...@@ -356,6 +388,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, ...@@ -356,6 +388,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
if (data->kind == adt7461) if (data->kind == adt7461)
data->temp8[nr] = temp_to_u8_adt7461(data, val); data->temp8[nr] = temp_to_u8_adt7461(data, val);
else if (data->kind == max6646)
data->temp8[nr] = temp_to_u8(val);
else else
data->temp8[nr] = temp_to_s8(val); data->temp8[nr] = temp_to_s8(val);
i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]); 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, ...@@ -372,6 +406,8 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
if (data->kind == adt7461) if (data->kind == adt7461)
temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
else if (data->kind == max6646)
temp = temp_from_u16(data->temp11[attr->index]);
else else
temp = temp_from_s16(data->temp11[attr->index]); temp = temp_from_s16(data->temp11[attr->index]);
...@@ -401,12 +437,15 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -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); data->temp11[nr] = temp_to_u16_adt7461(data, val);
else if (data->kind == max6657 || data->kind == max6680) else if (data->kind == max6657 || data->kind == max6680)
data->temp11[nr] = temp_to_s8(val) << 8; data->temp11[nr] = temp_to_s8(val) << 8;
else if (data->kind == max6646)
data->temp11[nr] = temp_to_u8(val) << 8;
else else
data->temp11[nr] = temp_to_s16(val); data->temp11[nr] = temp_to_s16(val);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8); 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], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
data->temp11[nr] & 0xff); data->temp11[nr] & 0xff);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -689,6 +728,16 @@ static int lm90_detect(struct i2c_client *new_client, int kind, ...@@ -689,6 +728,16 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
&& (reg_config1 & 0x03) == 0x00 && (reg_config1 & 0x03) == 0x00
&& reg_convrate <= 0x07) { && reg_convrate <= 0x07) {
kind = max6680; 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, ...@@ -719,6 +768,8 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
name = "max6680"; name = "max6680";
} else if (kind == adt7461) { } else if (kind == adt7461) {
name = "adt7461"; name = "adt7461";
} else if (kind == max6646) {
name = "max6646";
} }
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
...@@ -758,7 +809,7 @@ static int lm90_probe(struct i2c_client *new_client, ...@@ -758,7 +809,7 @@ static int lm90_probe(struct i2c_client *new_client,
&dev_attr_pec))) &dev_attr_pec)))
goto exit_remove_files; goto exit_remove_files;
} }
if (data->kind != max6657) { if (data->kind != max6657 && data->kind != max6646) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&new_client->dev,
&sensor_dev_attr_temp2_offset.dev_attr))) &sensor_dev_attr_temp2_offset.dev_attr)))
goto exit_remove_files; goto exit_remove_files;
...@@ -824,7 +875,7 @@ static int lm90_remove(struct i2c_client *client) ...@@ -824,7 +875,7 @@ static int lm90_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm90_group); sysfs_remove_group(&client->dev.kobj, &lm90_group);
device_remove_file(&client->dev, &dev_attr_pec); device_remove_file(&client->dev, &dev_attr_pec);
if (data->kind != max6657) if (data->kind != max6657 && data->kind != max6646)
device_remove_file(&client->dev, device_remove_file(&client->dev,
&sensor_dev_attr_temp2_offset.dev_attr); &sensor_dev_attr_temp2_offset.dev_attr);
...@@ -881,7 +932,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -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_REMOTE_CRIT, &data->temp8[3]);
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); 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, lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
MAX6657_REG_R_LOCAL_TEMPL, MAX6657_REG_R_LOCAL_TEMPL,
&data->temp11[4]); &data->temp11[4]);
...@@ -896,6 +947,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -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) { if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
data->temp11[1] = h << 8; data->temp11[1] = h << 8;
if (data->kind != max6657 && data->kind != max6680 if (data->kind != max6657 && data->kind != max6680
&& data->kind != max6646
&& lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
&l) == 0) &l) == 0)
data->temp11[1] |= l; data->temp11[1] |= l;
...@@ -903,12 +955,13 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -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) { if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
data->temp11[2] = h << 8; data->temp11[2] = h << 8;
if (data->kind != max6657 && data->kind != max6680 if (data->kind != max6657 && data->kind != max6680
&& data->kind != max6646
&& lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
&l) == 0) &l) == 0)
data->temp11[2] |= l; 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, if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
&h) == 0 &h) == 0
&& lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment