diff options
Diffstat (limited to 'drivers/hwmon/lm90.c')
-rw-r--r-- | drivers/hwmon/lm90.c | 1014 |
1 files changed, 723 insertions, 291 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 760ef72eea56..812781c655a7 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -28,9 +28,11 @@ * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor * chips made by Maxim. These chips are similar to the LM86. * Note that there is no easy way to differentiate between the three - * variants. The extra address and features of the MAX6659 are not - * supported by this driver. These chips lack the remote temperature - * offset feature. + * variants. We use the device address to detect MAX6659, which will result + * in a detection as max6657 if it is on address 0x4c. The extra address + * and features of the MAX6659 are only supported if the chip is configured + * explicitly as max6659, or if its address is not 0x4c. + * These chips lack the remote temperature offset feature. * * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and * MAX6692 chips made by Maxim. These are again similar to the LM86, @@ -42,6 +44,11 @@ * chips. The MAX6680 and MAX6681 only differ in the pinout so they can * be treated identically. * + * This driver also supports the MAX6695 and MAX6696, two other sensor + * chips made by Maxim. These are also quite similar to other Maxim + * chips, but support three temperature sensors instead of two. MAX6695 + * and MAX6696 only differ in the pinout so they can be treated identically. + * * This driver also supports the ADT7461 chip from Analog Devices. * It's supported in both compatibility and extended mode. It is mostly * compatible with LM90 except for a data format difference for the @@ -81,11 +88,11 @@ * 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, MAX6649, MAX6657 - * and MAX6658 have address 0x4c. + * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657, + * MAX6658 and W83L771 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). + * MAX6659 can have address 0x4c, 0x4d or 0x4e. * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, * 0x4c, 0x4d or 0x4e. */ @@ -93,8 +100,8 @@ static const unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; -enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646, - w83l771 }; +enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, + max6646, w83l771, max6696 }; /* * The LM90 registers @@ -135,26 +142,30 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646, #define LM90_REG_R_TCRIT_HYST 0x21 #define LM90_REG_W_TCRIT_HYST 0x21 -/* MAX6646/6647/6649/6657/6658/6659 registers */ +/* MAX6646/6647/6649/6657/6658/6659/6695/6696 registers */ #define MAX6657_REG_R_LOCAL_TEMPL 0x11 +#define MAX6696_REG_R_STATUS2 0x12 +#define MAX6659_REG_R_REMOTE_EMERG 0x16 +#define MAX6659_REG_W_REMOTE_EMERG 0x16 +#define MAX6659_REG_R_LOCAL_EMERG 0x17 +#define MAX6659_REG_W_LOCAL_EMERG 0x17 -/* - * Device flags - */ -#define LM90_FLAG_ADT7461_EXT 0x01 /* ADT7461 extended mode */ +#define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ +#define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ /* - * Functions declaration + * Device flags */ - -static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info); -static int lm90_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static void lm90_init_client(struct i2c_client *client); -static void lm90_alert(struct i2c_client *client, unsigned int flag); -static int lm90_remove(struct i2c_client *client); -static struct lm90_data *lm90_update_device(struct device *dev); +#define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ +/* Device features */ +#define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ +#define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ +#define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ +#define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ +#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ +#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ +#define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ /* * Driver data (common to all clients) @@ -172,25 +183,85 @@ static const struct i2c_device_id lm90_id[] = { { "max6649", max6646 }, { "max6657", max6657 }, { "max6658", max6657 }, - { "max6659", max6657 }, + { "max6659", max6659 }, { "max6680", max6680 }, { "max6681", max6680 }, + { "max6695", max6696 }, + { "max6696", max6696 }, { "w83l771", w83l771 }, { } }; MODULE_DEVICE_TABLE(i2c, lm90_id); -static struct i2c_driver lm90_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm90", +/* + * chip type specific parameters + */ +struct lm90_params { + u32 flags; /* Capabilities */ + u16 alert_alarms; /* Which alarm bits trigger ALERT# */ + /* Upper 8 bits for max6695/96 */ + u8 max_convrate; /* Maximum conversion rate register value */ +}; + +static const struct lm90_params lm90_params[] = { + [adm1032] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT + | LM90_HAVE_BROKEN_ALERT, + .alert_alarms = 0x7c, + .max_convrate = 10, + }, + [adt7461] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT + | LM90_HAVE_BROKEN_ALERT, + .alert_alarms = 0x7c, + .max_convrate = 10, + }, + [lm86] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [lm90] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [lm99] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [max6646] = { + .flags = LM90_HAVE_LOCAL_EXT, + .alert_alarms = 0x7c, + .max_convrate = 6, + }, + [max6657] = { + .flags = LM90_HAVE_LOCAL_EXT, + .alert_alarms = 0x7c, + .max_convrate = 8, + }, + [max6659] = { + .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY, + .alert_alarms = 0x7c, + .max_convrate = 8, + }, + [max6680] = { + .flags = LM90_HAVE_OFFSET, + .alert_alarms = 0x7c, + .max_convrate = 7, + }, + [max6696] = { + .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY + | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, + .alert_alarms = 0x187c, + .max_convrate = 6, + }, + [w83l771] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, + .alert_alarms = 0x7c, + .max_convrate = 8, }, - .probe = lm90_probe, - .remove = lm90_remove, - .alert = lm90_alert, - .id_table = lm90_id, - .detect = lm90_detect, - .address_list = normal_i2c, }; /* @@ -203,26 +274,268 @@ struct lm90_data { char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ int kind; - int flags; + u32 flags; + + int update_interval; /* in milliseconds */ u8 config_orig; /* Original configuration register value */ - u8 alert_alarms; /* Which alarm bits trigger ALERT# */ + u8 convrate_orig; /* Original conversion rate register value */ + u16 alert_alarms; /* Which alarm bits trigger ALERT# */ + /* Upper 8 bits for max6695/96 */ + u8 max_convrate; /* Maximum conversion rate */ /* registers values */ - s8 temp8[4]; /* 0: local low limit + s8 temp8[8]; /* 0: local low limit 1: local high limit 2: local critical limit - 3: remote critical limit */ - s16 temp11[5]; /* 0: remote input + 3: remote critical limit + 4: local emergency limit (max6659 and max6695/96) + 5: remote emergency limit (max6659 and max6695/96) + 6: remote 2 critical limit (max6695/96 only) + 7: remote 2 emergency limit (max6695/96 only) */ + s16 temp11[8]; /* 0: remote input 1: remote low limit 2: remote high limit - 3: remote offset (except max6646 and max6657) - 4: local input */ + 3: remote offset (except max6646, max6657/58/59, + and max6695/96) + 4: local input + 5: remote 2 input (max6695/96 only) + 6: remote 2 low limit (max6695/96 only) + 7: remote 2 high limit (ma6695/96 only) */ u8 temp_hyst; - u8 alarms; /* bitvector */ + u16 alarms; /* bitvector (upper 8 bits for max6695/96) */ }; /* + * Support functions + */ + +/* + * The ADM1032 supports PEC but not on write byte transactions, so we need + * to explicitly ask for a transaction without PEC. + */ +static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) +{ + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags & ~I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); +} + +/* + * It is assumed that client->update_lock is held (unless we are in + * detection or initialization steps). This matters when PEC is enabled, + * because we don't want the address pointer to change between the write + * byte and the read byte transactions. + */ +static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) +{ + int err; + + if (client->flags & I2C_CLIENT_PEC) { + err = adm1032_write_byte(client, reg); + if (err >= 0) + err = i2c_smbus_read_byte(client); + } else + err = i2c_smbus_read_byte_data(client, reg); + + if (err < 0) { + dev_warn(&client->dev, "Register %#02x read failed (%d)\n", + reg, err); + return err; + } + *value = err; + + return 0; +} + +static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) +{ + int err; + u8 oldh, newh, l; + + /* + * There is a trick here. We have to read two registers to have the + * sensor temperature, but we have to beware a conversion could occur + * inbetween the readings. The datasheet says we should either use + * the one-shot conversion register, which we don't want to do + * (disables hardware monitoring) or monitor the busy bit, which is + * impossible (we can't read the values and monitor that bit at the + * exact same time). So the solution used here is to read the high + * byte once, then the low byte, then the high byte again. If the new + * high byte matches the old one, then we have a valid reading. Else + * we have to read the low byte again, and now we believe we have a + * correct reading. + */ + if ((err = lm90_read_reg(client, regh, &oldh)) + || (err = lm90_read_reg(client, regl, &l)) + || (err = lm90_read_reg(client, regh, &newh))) + return err; + if (oldh != newh) { + err = lm90_read_reg(client, regl, &l); + if (err) + return err; + } + *value = (newh << 8) | l; + + return 0; +} + +/* + * client->update_lock must be held when calling this function (unless we are + * in detection or initialization steps), and while a remote channel other + * than channel 0 is selected. Also, calling code must make sure to re-select + * external channel 0 before releasing the lock. This is necessary because + * various registers have different meanings as a result of selecting a + * non-default remote channel. + */ +static inline void lm90_select_remote_channel(struct i2c_client *client, + struct lm90_data *data, + int channel) +{ + u8 config; + + if (data->kind == max6696) { + lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); + config &= ~0x08; + if (channel) + config |= 0x08; + i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, + config); + } +} + +/* + * Set conversion rate. + * client->update_lock must be held when calling this function (unless we are + * in detection or initialization steps). + */ +static void lm90_set_convrate(struct i2c_client *client, struct lm90_data *data, + unsigned int interval) +{ + int i; + unsigned int update_interval; + + /* Shift calculations to avoid rounding errors */ + interval <<= 6; + + /* find the nearest update rate */ + for (i = 0, update_interval = LM90_MAX_CONVRATE_MS << 6; + i < data->max_convrate; i++, update_interval >>= 1) + if (interval >= update_interval * 3 / 4) + break; + + i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, i); + data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64); +} + +static struct lm90_data *lm90_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm90_data *data = i2c_get_clientdata(client); + unsigned long next_update; + + mutex_lock(&data->update_lock); + + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval) + 1; + if (time_after(jiffies, next_update) || !data->valid) { + u8 h, l; + u8 alarms; + + dev_dbg(&client->dev, "Updating lm90 data.\n"); + lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]); + lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]); + lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]); + 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->flags & LM90_HAVE_LOCAL_EXT) { + lm90_read16(client, LM90_REG_R_LOCAL_TEMP, + MAX6657_REG_R_LOCAL_TEMPL, + &data->temp11[4]); + } else { + if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, + &h) == 0) + data->temp11[4] = h << 8; + } + lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, + LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]); + + if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { + data->temp11[1] = h << 8; + if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) + && 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->flags & LM90_HAVE_REM_LIMIT_EXT) + && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, + &l) == 0) + data->temp11[2] |= l; + } + + if (data->flags & LM90_HAVE_OFFSET) { + if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, + &h) == 0 + && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, + &l) == 0) + data->temp11[3] = (h << 8) | l; + } + if (data->flags & LM90_HAVE_EMERGENCY) { + lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, + &data->temp8[4]); + lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, + &data->temp8[5]); + } + lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); + data->alarms = alarms; /* save as 16 bit value */ + + if (data->kind == max6696) { + lm90_select_remote_channel(client, data, 1); + lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, + &data->temp8[6]); + lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, + &data->temp8[7]); + lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, + LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]); + if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h)) + data->temp11[6] = h << 8; + if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) + data->temp11[7] = h << 8; + lm90_select_remote_channel(client, data, 0); + + if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, + &alarms)) + data->alarms |= alarms << 8; + } + + /* Re-enable ALERT# output if it was originally enabled and + * relevant alarms are all clear */ + if ((data->config_orig & 0x80) == 0 + && (data->alarms & data->alert_alarms) == 0) { + u8 config; + + lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); + if (config & 0x80) { + dev_dbg(&client->dev, "Re-enabling ALERT#\n"); + i2c_smbus_write_byte_data(client, + LM90_REG_W_CONFIG1, + config & ~0x80); + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* * Conversions * For local temperatures and limits, critical limits and the hysteresis * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius. @@ -377,18 +690,27 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - static const u8 reg[4] = { + static const u8 reg[8] = { LM90_REG_W_LOCAL_LOW, LM90_REG_W_LOCAL_HIGH, LM90_REG_W_LOCAL_CRIT, LM90_REG_W_REMOTE_CRIT, + MAX6659_REG_W_LOCAL_EMERG, + MAX6659_REG_W_REMOTE_EMERG, + LM90_REG_W_REMOTE_CRIT, + MAX6659_REG_W_REMOTE_EMERG, }; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct lm90_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); int nr = attr->index; + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; /* +16 degrees offset for temp2 for the LM99 */ if (data->kind == lm99 && attr->index == 3) @@ -401,7 +723,11 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, data->temp8[nr] = temp_to_u8(val); else data->temp8[nr] = temp_to_s8(val); + + lm90_select_remote_channel(client, data, nr >= 6); i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]); + lm90_select_remote_channel(client, data, 0); + mutex_unlock(&data->update_lock); return count; } @@ -409,7 +735,7 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); struct lm90_data *data = lm90_update_device(dev); int temp; @@ -430,46 +756,58 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - static const u8 reg[6] = { - LM90_REG_W_REMOTE_LOWH, - LM90_REG_W_REMOTE_LOWL, - LM90_REG_W_REMOTE_HIGHH, - LM90_REG_W_REMOTE_HIGHL, - LM90_REG_W_REMOTE_OFFSH, - LM90_REG_W_REMOTE_OFFSL, + struct { + u8 high; + u8 low; + int channel; + } reg[5] = { + { LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 0 }, + { LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 0 }, + { LM90_REG_W_REMOTE_OFFSH, LM90_REG_W_REMOTE_OFFSL, 0 }, + { LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 1 }, + { LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 1 } }; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); struct i2c_client *client = to_i2c_client(dev); struct lm90_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - int nr = attr->index; + int nr = attr->nr; + int index = attr->index; + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && attr->index <= 2) + if (data->kind == lm99 && index <= 2) val -= 16000; mutex_lock(&data->update_lock); if (data->kind == adt7461) - 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; + data->temp11[index] = temp_to_u16_adt7461(data, val); else if (data->kind == max6646) - data->temp11[nr] = temp_to_u8(val) << 8; + data->temp11[index] = temp_to_u8(val) << 8; + else if (data->flags & LM90_HAVE_REM_LIMIT_EXT) + data->temp11[index] = temp_to_s16(val); 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 - && data->kind != max6646) - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], - data->temp11[nr] & 0xff); + data->temp11[index] = temp_to_s8(val) << 8; + + lm90_select_remote_channel(client, data, reg[nr].channel); + i2c_smbus_write_byte_data(client, reg[nr].high, + data->temp11[index] >> 8); + if (data->flags & LM90_HAVE_REM_LIMIT_EXT) + i2c_smbus_write_byte_data(client, reg[nr].low, + data->temp11[index] & 0xff); + lm90_select_remote_channel(client, data, 0); + mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temphyst(struct device *dev, struct device_attribute *devattr, +static ssize_t show_temphyst(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -495,9 +833,14 @@ 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 val; + int err; int temp; + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; + mutex_lock(&data->update_lock); if (data->kind == adt7461) temp = temp_from_u8_adt7461(data, data->temp8[2]); @@ -530,16 +873,44 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp11, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); +static ssize_t show_update_interval(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lm90_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", data->update_interval); +} + +static ssize_t set_update_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm90_data *data = i2c_get_clientdata(client); + unsigned long val; + int err; + + err = strict_strtoul(buf, 10, &val); + if (err) + return err; + + mutex_lock(&data->update_lock); + lm90_set_convrate(client, data, val); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp11, NULL, 0, 4); +static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp11, NULL, 0, 0); static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, set_temp8, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 1); +static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 0, 1); static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, set_temp8, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 2); +static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 1, 2); static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, set_temp8, 2); static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, @@ -547,8 +918,8 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, set_temphyst, 2); static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 3); +static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 2, 3); /* Individual alarm files */ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); @@ -561,6 +932,9 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); /* Raw alarm file for compatibility */ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, + set_update_interval); + static struct attribute *lm90_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, @@ -581,6 +955,7 @@ static struct attribute *lm90_attributes[] = { &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, &dev_attr_alarms.attr, + &dev_attr_update_interval.attr, NULL }; @@ -588,6 +963,86 @@ static const struct attribute_group lm90_group = { .attrs = lm90_attributes, }; +/* + * Additional attributes for devices with emergency sensors + */ +static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8, + set_temp8, 4); +static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8, + set_temp8, 5); +static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst, + NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst, + NULL, 5); + +static struct attribute *lm90_emergency_attributes[] = { + &sensor_dev_attr_temp1_emergency.dev_attr.attr, + &sensor_dev_attr_temp2_emergency.dev_attr.attr, + &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_emergency_hyst.dev_attr.attr, + NULL +}; + +static const struct attribute_group lm90_emergency_group = { + .attrs = lm90_emergency_attributes, +}; + +static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 13); + +static struct attribute *lm90_emergency_alarm_attributes[] = { + &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group lm90_emergency_alarm_group = { + .attrs = lm90_emergency_alarm_attributes, +}; + +/* + * Additional attributes for devices with 3 temperature sensors + */ +static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp11, NULL, 0, 5); +static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 3, 6); +static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 4, 7); +static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp8, + set_temp8, 6); +static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temphyst, NULL, 6); +static SENSOR_DEVICE_ATTR(temp3_emergency, S_IWUSR | S_IRUGO, show_temp8, + set_temp8, 7); +static SENSOR_DEVICE_ATTR(temp3_emergency_hyst, S_IRUGO, show_temphyst, + NULL, 7); + +static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(temp3_emergency_alarm, S_IRUGO, show_alarm, NULL, 14); + +static struct attribute *lm90_temp3_attributes[] = { + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_emergency.dev_attr.attr, + &sensor_dev_attr_temp3_emergency_hyst.dev_attr.attr, + + &sensor_dev_attr_temp3_fault.dev_attr.attr, + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_emergency_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group lm90_temp3_group = { + .attrs = lm90_temp3_attributes, +}; + /* pec used for ADM1032 only */ static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, char *buf) @@ -600,7 +1055,12 @@ static ssize_t set_pec(struct device *dev, struct device_attribute *dummy, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); - long val = simple_strtol(buf, NULL, 10); + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; switch (val) { case 0: @@ -622,40 +1082,6 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec); * Real code */ -/* The ADM1032 supports PEC but not on write byte transactions, so we need - to explicitly ask for a transaction without PEC. */ -static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) -{ - return i2c_smbus_xfer(client->adapter, client->addr, - client->flags & ~I2C_CLIENT_PEC, - I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); -} - -/* It is assumed that client->update_lock is held (unless we are in - detection or initialization steps). This matters when PEC is enabled, - because we don't want the address pointer to change between the write - byte and the read byte transactions. */ -static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) -{ - int err; - - if (client->flags & I2C_CLIENT_PEC) { - err = adm1032_write_byte(client, reg); - if (err >= 0) - err = i2c_smbus_read_byte(client); - } else - err = i2c_smbus_read_byte_data(client, reg); - - if (err < 0) { - dev_warn(&client->dev, "Register %#02x read failed (%d)\n", - reg, err); - return err; - } - *value = err; - - return 0; -} - /* Return 0 if detection is successful, -ENODEV otherwise */ static int lm90_detect(struct i2c_client *new_client, struct i2c_board_info *info) @@ -730,6 +1156,23 @@ static int lm90_detect(struct i2c_client *new_client, } } else if (man_id == 0x4D) { /* Maxim */ + int reg_emerg, reg_emerg2, reg_status2; + + /* + * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read + * LM90_REG_R_MAN_ID in between. If MAX6659_REG_R_REMOTE_EMERG + * exists, both readings will reflect the same value. Otherwise, + * the readings will be different. + */ + if ((reg_emerg = i2c_smbus_read_byte_data(new_client, + MAX6659_REG_R_REMOTE_EMERG)) < 0 + || i2c_smbus_read_byte_data(new_client, LM90_REG_R_MAN_ID) < 0 + || (reg_emerg2 = i2c_smbus_read_byte_data(new_client, + MAX6659_REG_R_REMOTE_EMERG)) < 0 + || (reg_status2 = i2c_smbus_read_byte_data(new_client, + MAX6696_REG_R_STATUS2)) < 0) + return -ENODEV; + /* * The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id * register. Reading from that address will return the last @@ -737,12 +1180,38 @@ static int lm90_detect(struct i2c_client *new_client, * register. Likewise, the config1 register seems to lack a * low nibble, so the value will be those of the previous * read, so in our case those of the man_id register. + * MAX6659 has a third set of upper temperature limit registers. + * Those registers also return values on MAX6657 and MAX6658, + * thus the only way to detect MAX6659 is by its address. + * For this reason it will be mis-detected as MAX6657 if its + * address is 0x4C. */ if (chip_id == man_id - && (address == 0x4C || address == 0x4D) + && (address == 0x4C || address == 0x4D || address == 0x4E) && (reg_config1 & 0x1F) == (man_id & 0x0F) && reg_convrate <= 0x09) { - name = "max6657"; + if (address == 0x4C) + name = "max6657"; + else + name = "max6659"; + } else + /* + * Even though MAX6695 and MAX6696 do not have a chip ID + * register, reading it returns 0x01. Bit 4 of the config1 + * register is unused and should return zero when read. Bit 0 of + * the status2 register is unused and should return zero when + * read. + * + * MAX6695 and MAX6696 have an additional set of temperature + * limit registers. We can detect those chips by checking if + * one of those registers exists. + */ + if (chip_id == 0x01 + && (reg_config1 & 0x10) == 0x00 + && (reg_status2 & 0x01) == 0x00 + && reg_emerg == reg_emerg2 + && reg_convrate <= 0x07) { + name = "max6696"; } else /* * The chip_id register of the MAX6680 and MAX6681 holds the @@ -768,10 +1237,23 @@ static int lm90_detect(struct i2c_client *new_client, } else if (address == 0x4C && man_id == 0x5C) { /* Winbond/Nuvoton */ - if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */ - && (reg_config1 & 0x2A) == 0x00 - && reg_convrate <= 0x08) { - name = "w83l771"; + int reg_config2; + + reg_config2 = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CONFIG2); + if (reg_config2 < 0) + return -ENODEV; + + if ((reg_config1 & 0x2A) == 0x00 + && (reg_config2 & 0xF8) == 0x00) { + if (chip_id == 0x01 /* W83L771W/G */ + && reg_convrate <= 0x09) { + name = "w83l771"; + } else + if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */ + && reg_convrate <= 0x08) { + name = "w83l771"; + } } } @@ -787,6 +1269,69 @@ static int lm90_detect(struct i2c_client *new_client, return 0; } +static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data) +{ + if (data->flags & LM90_HAVE_TEMP3) + sysfs_remove_group(&client->dev.kobj, &lm90_temp3_group); + if (data->flags & LM90_HAVE_EMERGENCY_ALARM) + sysfs_remove_group(&client->dev.kobj, + &lm90_emergency_alarm_group); + if (data->flags & LM90_HAVE_EMERGENCY) + sysfs_remove_group(&client->dev.kobj, + &lm90_emergency_group); + if (data->flags & LM90_HAVE_OFFSET) + device_remove_file(&client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); + device_remove_file(&client->dev, &dev_attr_pec); + sysfs_remove_group(&client->dev.kobj, &lm90_group); +} + +static void lm90_init_client(struct i2c_client *client) +{ + u8 config, convrate; + struct lm90_data *data = i2c_get_clientdata(client); + + if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) { + dev_warn(&client->dev, "Failed to read convrate register!\n"); + convrate = LM90_DEF_CONVRATE_RVAL; + } + data->convrate_orig = convrate; + + /* + * Start the conversions. + */ + lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ + if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) { + dev_warn(&client->dev, "Initialization failed!\n"); + return; + } + data->config_orig = config; + + /* Check Temperature Range Select */ + if (data->kind == adt7461) { + if (config & 0x04) + data->flags |= LM90_FLAG_ADT7461_EXT; + } + + /* + * Put MAX6680/MAX8881 into extended resolution (bit 0x10, + * 0.125 degree resolution) and range (0x08, extend range + * to -64 degree) mode for the remote temperature sensor. + */ + if (data->kind == max6680) + config |= 0x18; + + /* + * Select external channel 0 for max6695/96 + */ + if (data->kind == max6696) + config &= ~0x08; + + config &= 0xBF; /* run */ + if (config != data->config_orig) /* Only write if changed */ + i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); +} + static int lm90_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { @@ -811,31 +1356,48 @@ static int lm90_probe(struct i2c_client *new_client, /* Different devices have different alarm bits triggering the * ALERT# output */ - switch (data->kind) { - case lm90: - case lm99: - case lm86: - data->alert_alarms = 0x7b; - break; - default: - data->alert_alarms = 0x7c; - break; - } + data->alert_alarms = lm90_params[data->kind].alert_alarms; + + /* Set chip capabilities */ + data->flags = lm90_params[data->kind].flags; + + /* Set maximum conversion rate */ + data->max_convrate = lm90_params[data->kind].max_convrate; /* Initialize the LM90 chip */ lm90_init_client(new_client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) + err = sysfs_create_group(&new_client->dev.kobj, &lm90_group); + if (err) goto exit_free; if (new_client->flags & I2C_CLIENT_PEC) { - if ((err = device_create_file(&new_client->dev, - &dev_attr_pec))) + err = device_create_file(&new_client->dev, &dev_attr_pec); + if (err) + goto exit_remove_files; + } + if (data->flags & LM90_HAVE_OFFSET) { + err = device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); + if (err) goto exit_remove_files; } - if (data->kind != max6657 && data->kind != max6646) { - if ((err = device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_offset.dev_attr))) + if (data->flags & LM90_HAVE_EMERGENCY) { + err = sysfs_create_group(&new_client->dev.kobj, + &lm90_emergency_group); + if (err) + goto exit_remove_files; + } + if (data->flags & LM90_HAVE_EMERGENCY_ALARM) { + err = sysfs_create_group(&new_client->dev.kobj, + &lm90_emergency_alarm_group); + if (err) + goto exit_remove_files; + } + if (data->flags & LM90_HAVE_TEMP3) { + err = sysfs_create_group(&new_client->dev.kobj, + &lm90_temp3_group); + if (err) goto exit_remove_files; } @@ -848,62 +1410,23 @@ static int lm90_probe(struct i2c_client *new_client, return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &lm90_group); - device_remove_file(&new_client->dev, &dev_attr_pec); + lm90_remove_files(new_client, data); exit_free: kfree(data); exit: return err; } -static void lm90_init_client(struct i2c_client *client) -{ - u8 config; - struct lm90_data *data = i2c_get_clientdata(client); - - /* - * Start the conversions. - */ - i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, - 5); /* 2 Hz */ - if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) { - dev_warn(&client->dev, "Initialization failed!\n"); - return; - } - data->config_orig = config; - - /* Check Temperature Range Select */ - if (data->kind == adt7461) { - if (config & 0x04) - data->flags |= LM90_FLAG_ADT7461_EXT; - } - - /* - * Put MAX6680/MAX8881 into extended resolution (bit 0x10, - * 0.125 degree resolution) and range (0x08, extend range - * to -64 degree) mode for the remote temperature sensor. - */ - if (data->kind == max6680) { - config |= 0x18; - } - - config &= 0xBF; /* run */ - if (config != data->config_orig) /* Only write if changed */ - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); -} - static int lm90_remove(struct i2c_client *client) { struct lm90_data *data = i2c_get_clientdata(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 && data->kind != max6646) - device_remove_file(&client->dev, - &sensor_dev_attr_temp2_offset.dev_attr); + lm90_remove_files(client, data); /* Restore initial configuration */ + i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, + data->convrate_orig); i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, data->config_orig); @@ -914,10 +1437,14 @@ static int lm90_remove(struct i2c_client *client) static void lm90_alert(struct i2c_client *client, unsigned int flag) { struct lm90_data *data = i2c_get_clientdata(client); - u8 config, alarms; + u8 config, alarms, alarms2 = 0; lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); - if ((alarms & 0x7f) == 0) { + + if (data->kind == max6696) + lm90_read_reg(client, MAX6696_REG_R_STATUS2, &alarms2); + + if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) { dev_info(&client->dev, "Everything OK\n"); } else { if (alarms & 0x61) @@ -930,10 +1457,14 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) dev_warn(&client->dev, "temp%d diode open, please check!\n", 2); + if (alarms2 & 0x18) + dev_warn(&client->dev, + "temp%d out of range, please check!\n", 3); + /* Disable ALERT# output, because these chips don't implement SMBus alert correctly; they should only hold the alert line low briefly. */ - if ((data->kind == adm1032 || data->kind == adt7461) + if ((data->flags & LM90_HAVE_BROKEN_ALERT) && (alarms & data->alert_alarms)) { dev_dbg(&client->dev, "Disabling ALERT#\n"); lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); @@ -943,117 +1474,18 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) } } -static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) -{ - int err; - u8 oldh, newh, l; - - /* - * There is a trick here. We have to read two registers to have the - * sensor temperature, but we have to beware a conversion could occur - * inbetween the readings. The datasheet says we should either use - * the one-shot conversion register, which we don't want to do - * (disables hardware monitoring) or monitor the busy bit, which is - * impossible (we can't read the values and monitor that bit at the - * exact same time). So the solution used here is to read the high - * byte once, then the low byte, then the high byte again. If the new - * high byte matches the old one, then we have a valid reading. Else - * we have to read the low byte again, and now we believe we have a - * correct reading. - */ - if ((err = lm90_read_reg(client, regh, &oldh)) - || (err = lm90_read_reg(client, regl, &l)) - || (err = lm90_read_reg(client, regh, &newh))) - return err; - if (oldh != newh) { - err = lm90_read_reg(client, regl, &l); - if (err) - return err; - } - *value = (newh << 8) | l; - - return 0; -} - -static struct lm90_data *lm90_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10) - || !data->valid) { - u8 h, l; - - dev_dbg(&client->dev, "Updating lm90 data.\n"); - lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]); - lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]); - lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]); - 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 || data->kind == max6646) { - lm90_read16(client, LM90_REG_R_LOCAL_TEMP, - MAX6657_REG_R_LOCAL_TEMPL, - &data->temp11[4]); - } else { - if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, - &h) == 0) - data->temp11[4] = h << 8; - } - lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, - LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]); - - 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 && data->kind != max6646) { - if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, - &h) == 0 - && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, - &l) == 0) - data->temp11[3] = (h << 8) | l; - } - lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); - - /* Re-enable ALERT# output if it was originally enabled and - * relevant alarms are all clear */ - if ((data->config_orig & 0x80) == 0 - && (data->alarms & data->alert_alarms) == 0) { - u8 config; - - lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); - if (config & 0x80) { - dev_dbg(&client->dev, "Re-enabling ALERT#\n"); - i2c_smbus_write_byte_data(client, - LM90_REG_W_CONFIG1, - config & ~0x80); - } - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} +static struct i2c_driver lm90_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "lm90", + }, + .probe = lm90_probe, + .remove = lm90_remove, + .alert = lm90_alert, + .id_table = lm90_id, + .detect = lm90_detect, + .address_list = normal_i2c, +}; static int __init sensors_lm90_init(void) { |