mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
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:
parent
9d4d383422
commit
271dabf5bb
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user