diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/lm85.c | 513 |
1 files changed, 250 insertions, 263 deletions
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index ef627ea71cc8..9fdf1c021007 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -121,7 +121,6 @@ enum chips { #define EMC6D102_REG_EXTEND_ADC3 0x87 #define EMC6D102_REG_EXTEND_ADC4 0x88 - /* * Conversions. Rounding and limit checking is only done on the TO_REG * variants. Note that you should be a bit careful with which arguments @@ -334,44 +333,235 @@ struct lm85_data { struct lm85_zone zone[3]; }; -static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info); -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm85_remove(struct i2c_client *client); +static int lm85_read_value(struct i2c_client *client, u8 reg) +{ + int res; -static int lm85_read_value(struct i2c_client *client, u8 reg); -static void lm85_write_value(struct i2c_client *client, u8 reg, int value); -static struct lm85_data *lm85_update_device(struct device *dev); + /* What size location is it? */ + switch (reg) { + case LM85_REG_FAN(0): /* Read WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + case LM85_REG_ALARM1: /* Read both bytes at once */ + res = i2c_smbus_read_byte_data(client, reg) & 0xff; + res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; + break; + default: /* Read BYTE data */ + res = i2c_smbus_read_byte_data(client, reg); + break; + } + return res; +} -static const struct i2c_device_id lm85_id[] = { - { "adm1027", adm1027 }, - { "adt7463", adt7463 }, - { "adt7468", adt7468 }, - { "lm85", lm85 }, - { "lm85b", lm85 }, - { "lm85c", lm85 }, - { "emc6d100", emc6d100 }, - { "emc6d101", emc6d100 }, - { "emc6d102", emc6d102 }, - { "emc6d103", emc6d103 }, - { "emc6d103s", emc6d103s }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm85_id); +static void lm85_write_value(struct i2c_client *client, u8 reg, int value) +{ + switch (reg) { + case LM85_REG_FAN(0): /* Write WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + /* NOTE: ALARM is read only, so not included here */ + i2c_smbus_write_byte_data(client, reg, value & 0xff); + i2c_smbus_write_byte_data(client, reg + 1, value >> 8); + break; + default: /* Write BYTE data */ + i2c_smbus_write_byte_data(client, reg, value); + break; + } +} -static struct i2c_driver lm85_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm85", - }, - .probe = lm85_probe, - .remove = lm85_remove, - .id_table = lm85_id, - .detect = lm85_detect, - .address_list = normal_i2c, -}; +static struct lm85_data *lm85_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->update_lock); + + if (!data->valid || + time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { + /* Things that change quickly */ + dev_dbg(&client->dev, "Reading sensor values\n"); + + /* + * Have to read extended bits first to "freeze" the + * more significant bits that are read later. + * There are 2 additional resolution bits per channel and we + * have room for 4, so we shift them to the left. + */ + if (data->type == adm1027 || data->type == adt7463 || + data->type == adt7468) { + int ext1 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC2); + int val = (ext1 << 8) + ext2; + + for (i = 0; i <= 4; i++) + data->in_ext[i] = + ((val >> (i * 2)) & 0x03) << 2; + + for (i = 0; i <= 2; i++) + data->temp_ext[i] = + (val >> ((i + 4) * 2)) & 0x0c; + } + + data->vid = lm85_read_value(client, LM85_REG_VID); + + for (i = 0; i <= 3; ++i) { + data->in[i] = + lm85_read_value(client, LM85_REG_IN(i)); + data->fan[i] = + lm85_read_value(client, LM85_REG_FAN(i)); + } + + if (!data->has_vid5) + data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); + + if (data->type == adt7468) + data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); + + for (i = 0; i <= 2; ++i) { + data->temp[i] = + lm85_read_value(client, LM85_REG_TEMP(i)); + data->pwm[i] = + lm85_read_value(client, LM85_REG_PWM(i)); + if (IS_ADT7468_OFF64(data)) + data->temp[i] -= 64; + } + + data->alarms = lm85_read_value(client, LM85_REG_ALARM1); + + if (data->type == emc6d100) { + /* Three more voltage sensors */ + for (i = 5; i <= 7; ++i) { + data->in[i] = lm85_read_value(client, + EMC6D100_REG_IN(i)); + } + /* More alarm bits */ + data->alarms |= lm85_read_value(client, + EMC6D100_REG_ALARM3) << 16; + } else if (data->type == emc6d102 || data->type == emc6d103 || + data->type == emc6d103s) { + /* + * Have to read LSB bits after the MSB ones because + * the reading of the MSB bits has frozen the + * LSBs (backward from the ADM1027). + */ + int ext1 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC2); + int ext3 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC3); + int ext4 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC4); + data->in_ext[0] = ext3 & 0x0f; + data->in_ext[1] = ext4 & 0x0f; + data->in_ext[2] = ext4 >> 4; + data->in_ext[3] = ext3 >> 4; + data->in_ext[4] = ext2 >> 4; + + data->temp_ext[0] = ext1 & 0x0f; + data->temp_ext[1] = ext2 & 0x0f; + data->temp_ext[2] = ext1 >> 4; + } + + data->last_reading = jiffies; + } /* last_reading */ + + if (!data->valid || + time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { + /* Things that don't change often */ + dev_dbg(&client->dev, "Reading config values\n"); + + for (i = 0; i <= 3; ++i) { + data->in_min[i] = + lm85_read_value(client, LM85_REG_IN_MIN(i)); + data->in_max[i] = + lm85_read_value(client, LM85_REG_IN_MAX(i)); + data->fan_min[i] = + lm85_read_value(client, LM85_REG_FAN_MIN(i)); + } + + if (!data->has_vid5) { + data->in_min[4] = lm85_read_value(client, + LM85_REG_IN_MIN(4)); + data->in_max[4] = lm85_read_value(client, + LM85_REG_IN_MAX(4)); + } + + if (data->type == emc6d100) { + for (i = 5; i <= 7; ++i) { + data->in_min[i] = lm85_read_value(client, + EMC6D100_REG_IN_MIN(i)); + data->in_max[i] = lm85_read_value(client, + EMC6D100_REG_IN_MAX(i)); + } + } + + for (i = 0; i <= 2; ++i) { + int val; + + data->temp_min[i] = + lm85_read_value(client, LM85_REG_TEMP_MIN(i)); + data->temp_max[i] = + lm85_read_value(client, LM85_REG_TEMP_MAX(i)); + + data->autofan[i].config = + lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); + val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); + data->pwm_freq[i] = val & 0x07; + data->zone[i].range = val >> 4; + data->autofan[i].min_pwm = + lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); + data->zone[i].limit = + lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); + data->zone[i].critical = + lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); + + if (IS_ADT7468_OFF64(data)) { + data->temp_min[i] -= 64; + data->temp_max[i] -= 64; + data->zone[i].limit -= 64; + data->zone[i].critical -= 64; + } + } + + if (data->type != emc6d103s) { + i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); + data->autofan[0].min_off = (i & 0x20) != 0; + data->autofan[1].min_off = (i & 0x40) != 0; + data->autofan[2].min_off = (i & 0x80) != 0; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST1); + data->zone[0].hyst = i >> 4; + data->zone[1].hyst = i & 0x0f; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST2); + data->zone[2].hyst = i >> 4; + } + + data->last_config = jiffies; + } /* last_config */ + + data->valid = 1; + + mutex_unlock(&data->update_lock); + + return data; +} /* 4 Fans */ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, @@ -1467,236 +1657,33 @@ static int lm85_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id lm85_id[] = { + { "adm1027", adm1027 }, + { "adt7463", adt7463 }, + { "adt7468", adt7468 }, + { "lm85", lm85 }, + { "lm85b", lm85 }, + { "lm85c", lm85 }, + { "emc6d100", emc6d100 }, + { "emc6d101", emc6d100 }, + { "emc6d102", emc6d102 }, + { "emc6d103", emc6d103 }, + { "emc6d103s", emc6d103s }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm85_id); -static int lm85_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - /* What size location is it? */ - switch (reg) { - case LM85_REG_FAN(0): /* Read WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - case LM85_REG_ALARM1: /* Read both bytes at once */ - res = i2c_smbus_read_byte_data(client, reg) & 0xff; - res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; - break; - default: /* Read BYTE data */ - res = i2c_smbus_read_byte_data(client, reg); - break; - } - - return res; -} - -static void lm85_write_value(struct i2c_client *client, u8 reg, int value) -{ - switch (reg) { - case LM85_REG_FAN(0): /* Write WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - /* NOTE: ALARM is read only, so not included here */ - i2c_smbus_write_byte_data(client, reg, value & 0xff); - i2c_smbus_write_byte_data(client, reg + 1, value >> 8); - break; - default: /* Write BYTE data */ - i2c_smbus_write_byte_data(client, reg, value); - break; - } -} - -static struct lm85_data *lm85_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (!data->valid || - time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { - /* Things that change quickly */ - dev_dbg(&client->dev, "Reading sensor values\n"); - - /* - * Have to read extended bits first to "freeze" the - * more significant bits that are read later. - * There are 2 additional resolution bits per channel and we - * have room for 4, so we shift them to the left. - */ - if (data->type == adm1027 || data->type == adt7463 || - data->type == adt7468) { - int ext1 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC2); - int val = (ext1 << 8) + ext2; - - for (i = 0; i <= 4; i++) - data->in_ext[i] = - ((val >> (i * 2)) & 0x03) << 2; - - for (i = 0; i <= 2; i++) - data->temp_ext[i] = - (val >> ((i + 4) * 2)) & 0x0c; - } - - data->vid = lm85_read_value(client, LM85_REG_VID); - - for (i = 0; i <= 3; ++i) { - data->in[i] = - lm85_read_value(client, LM85_REG_IN(i)); - data->fan[i] = - lm85_read_value(client, LM85_REG_FAN(i)); - } - - if (!data->has_vid5) - data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); - - if (data->type == adt7468) - data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); - - for (i = 0; i <= 2; ++i) { - data->temp[i] = - lm85_read_value(client, LM85_REG_TEMP(i)); - data->pwm[i] = - lm85_read_value(client, LM85_REG_PWM(i)); - - if (IS_ADT7468_OFF64(data)) - data->temp[i] -= 64; - } - - data->alarms = lm85_read_value(client, LM85_REG_ALARM1); - - if (data->type == emc6d100) { - /* Three more voltage sensors */ - for (i = 5; i <= 7; ++i) { - data->in[i] = lm85_read_value(client, - EMC6D100_REG_IN(i)); - } - /* More alarm bits */ - data->alarms |= lm85_read_value(client, - EMC6D100_REG_ALARM3) << 16; - } else if (data->type == emc6d102 || data->type == emc6d103 || - data->type == emc6d103s) { - /* - * Have to read LSB bits after the MSB ones because - * the reading of the MSB bits has frozen the - * LSBs (backward from the ADM1027). - */ - int ext1 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC2); - int ext3 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC3); - int ext4 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC4); - data->in_ext[0] = ext3 & 0x0f; - data->in_ext[1] = ext4 & 0x0f; - data->in_ext[2] = ext4 >> 4; - data->in_ext[3] = ext3 >> 4; - data->in_ext[4] = ext2 >> 4; - - data->temp_ext[0] = ext1 & 0x0f; - data->temp_ext[1] = ext2 & 0x0f; - data->temp_ext[2] = ext1 >> 4; - } - - data->last_reading = jiffies; - } /* last_reading */ - - if (!data->valid || - time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { - /* Things that don't change often */ - dev_dbg(&client->dev, "Reading config values\n"); - - for (i = 0; i <= 3; ++i) { - data->in_min[i] = - lm85_read_value(client, LM85_REG_IN_MIN(i)); - data->in_max[i] = - lm85_read_value(client, LM85_REG_IN_MAX(i)); - data->fan_min[i] = - lm85_read_value(client, LM85_REG_FAN_MIN(i)); - } - - if (!data->has_vid5) { - data->in_min[4] = lm85_read_value(client, - LM85_REG_IN_MIN(4)); - data->in_max[4] = lm85_read_value(client, - LM85_REG_IN_MAX(4)); - } - - if (data->type == emc6d100) { - for (i = 5; i <= 7; ++i) { - data->in_min[i] = lm85_read_value(client, - EMC6D100_REG_IN_MIN(i)); - data->in_max[i] = lm85_read_value(client, - EMC6D100_REG_IN_MAX(i)); - } - } - - for (i = 0; i <= 2; ++i) { - int val; - - data->temp_min[i] = - lm85_read_value(client, LM85_REG_TEMP_MIN(i)); - data->temp_max[i] = - lm85_read_value(client, LM85_REG_TEMP_MAX(i)); - - data->autofan[i].config = - lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); - val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); - data->pwm_freq[i] = val & 0x07; - data->zone[i].range = val >> 4; - data->autofan[i].min_pwm = - lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); - data->zone[i].limit = - lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); - data->zone[i].critical = - lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); - - if (IS_ADT7468_OFF64(data)) { - data->temp_min[i] -= 64; - data->temp_max[i] -= 64; - data->zone[i].limit -= 64; - data->zone[i].critical -= 64; - } - } - - if (data->type != emc6d103s) { - i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); - data->autofan[0].min_off = (i & 0x20) != 0; - data->autofan[1].min_off = (i & 0x40) != 0; - data->autofan[2].min_off = (i & 0x80) != 0; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST1); - data->zone[0].hyst = i >> 4; - data->zone[1].hyst = i & 0x0f; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST2); - data->zone[2].hyst = i >> 4; - } - - data->last_config = jiffies; - } /* last_config */ - - data->valid = 1; - - mutex_unlock(&data->update_lock); - - return data; -} +static struct i2c_driver lm85_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "lm85", + }, + .probe = lm85_probe, + .remove = lm85_remove, + .id_table = lm85_id, + .detect = lm85_detect, + .address_list = normal_i2c, +}; module_i2c_driver(lm85_driver); |