* 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
* 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.
* 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
#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
{ "lm86", lm86 },
{ "lm89", lm99 },
{ "lm99", lm99 }, /* Missing temperature offset */
+ { "max6646", max6646 },
+ { "max6647", max6646 },
+ { "max6649", max6646 },
{ "max6657", max6657 },
{ "max6658", max6657 },
{ "max6659", max6657 },
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 */
* 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 temp1_from_reg(s8 val)
+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 temp2_from_reg(s16 val)
+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 temp1_to_reg(long val)
+static s8 temp_to_s8(long val)
{
if (val <= -128000)
return -128;
return (val + 500) / 1000;
}
-static s16 temp2_to_reg(long val)
+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)
return 0x8000;
* ADT7461 in "extended mode" operation uses unsigned integers offset by
* 64 (e.g., 0 -> -64 degC). The range is restricted to -64..191 degC.
*/
-static inline int temp1_from_reg_adt7461(struct lm90_data *data, u8 val)
+static inline int temp_from_u8_adt7461(struct lm90_data *data, u8 val)
{
if (data->flags & LM90_FLAG_ADT7461_EXT)
return (val - 64) * 1000;
else
- return temp1_from_reg(val);
+ return temp_from_s8(val);
}
-static inline int temp2_from_reg_adt7461(struct lm90_data *data, u16 val)
+static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val)
{
if (data->flags & LM90_FLAG_ADT7461_EXT)
return (val - 0x4000) / 64 * 250;
else
- return temp2_from_reg(val);
+ return temp_from_s16(val);
}
-static u8 temp1_to_reg_adt7461(struct lm90_data *data, long val)
+static u8 temp_to_u8_adt7461(struct lm90_data *data, long val)
{
if (data->flags & LM90_FLAG_ADT7461_EXT) {
if (val <= -64000)
}
}
-static u16 temp2_to_reg_adt7461(struct lm90_data *data, long val)
+static u16 temp_to_u16_adt7461(struct lm90_data *data, long val)
{
if (data->flags & LM90_FLAG_ADT7461_EXT) {
if (val <= -64000)
int temp;
if (data->kind == adt7461)
- temp = temp1_from_reg_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
- temp = temp1_from_reg(data->temp8[attr->index]);
+ temp = temp_from_s8(data->temp8[attr->index]);
return sprintf(buf, "%d\n", temp);
}
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
- data->temp8[nr] = temp1_to_reg_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
- data->temp8[nr] = temp1_to_reg(val);
+ data->temp8[nr] = temp_to_s8(val);
i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
mutex_unlock(&data->update_lock);
return count;
int temp;
if (data->kind == adt7461)
- temp = temp2_from_reg_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
- temp = temp2_from_reg(data->temp11[attr->index]);
+ temp = temp_from_s16(data->temp11[attr->index]);
return sprintf(buf, "%d\n", temp);
}
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
- data->temp11[nr] = temp2_to_reg_adt7461(data, val);
+ data->temp11[nr] = temp_to_u16_adt7461(data, val);
else if (data->kind == max6657 || data->kind == max6680)
- data->temp11[nr] = temp1_to_reg(val) << 8;
+ 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] = temp2_to_reg(val);
+ 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);
int temp;
if (data->kind == adt7461)
- temp = temp1_from_reg_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
- temp = temp1_from_reg(data->temp8[attr->index]);
+ temp = temp_from_s8(data->temp8[attr->index]);
- return sprintf(buf, "%d\n", temp - temp1_from_reg(data->temp_hyst));
+ return sprintf(buf, "%d\n", temp - temp_from_s8(data->temp_hyst));
}
static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10);
- long hyst;
+ int temp;
mutex_lock(&data->update_lock);
- hyst = temp1_from_reg(data->temp8[2]) - val;
+ if (data->kind == adt7461)
+ temp = temp_from_u8_adt7461(data, data->temp8[2]);
+ else if (data->kind == max6646)
+ temp = temp_from_u8(data->temp8[2]);
+ else
+ temp = temp_from_s8(data->temp8[2]);
+
+ data->temp_hyst = hyst_to_reg(temp - val);
i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
- hyst_to_reg(hyst));
+ data->temp_hyst);
mutex_unlock(&data->update_lock);
return count;
}
&& (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;
}
}
if (kind <= 0) { /* identification failed */
- dev_info(&adapter->dev,
- "Unsupported chip (man_id=0x%02X, "
- "chip_id=0x%02X).\n", man_id, chip_id);
+ dev_dbg(&adapter->dev,
+ "Unsupported chip at 0x%02x (man_id=0x%02X, "
+ "chip_id=0x%02X)\n", address, man_id, chip_id);
return -ENODEV;
}
}
name = "max6680";
} else if (kind == adt7461) {
name = "adt7461";
+ } else if (kind == max6646) {
+ name = "max6646";
}
strlcpy(info->type, name, I2C_NAME_SIZE);
&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;
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);
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]);
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;
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,