From 271dabf5bbf6ae6e2792cd5cf6f0434230e5c18c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 17 Oct 2008 17:51:11 +0200 Subject: 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 Signed-off-by: Jean Delvare --- drivers/hwmon/lm90.c | 77 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 12 deletions(-) (limited to 'drivers/hwmon/lm90.c') diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 85ba2c4..fe09f82 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -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, -- cgit v1.1