--- linux-2.6.27-rc5-khali/drivers/hwmon/lm85.c 2008-09-10 12:47:24.000000000 +0200 +++ lm85.c 2008-09-14 13:55:13.000000000 +0200 @@ -39,7 +39,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; /* Insmod parameters */ -I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); +I2C_CLIENT_INSMOD_7(lm85b, lm85c, lm96000, adm1027, adt7463, emc6d100, emc6d102); /* The LM85 registers */ @@ -67,6 +67,7 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm102 #define LM85_VERSTEP_GENERIC 0x60 #define LM85_VERSTEP_LM85C 0x60 #define LM85_VERSTEP_LM85B 0x62 +#define LM85_VERSTEP_LM96000 0x69 #define LM85_VERSTEP_ADM1027 0x60 #define LM85_VERSTEP_ADT7463 0x62 #define LM85_VERSTEP_ADT7463C 0x6A @@ -91,6 +92,8 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm102 #define LM85_REG_AFAN_HYST1 0x6d #define LM85_REG_AFAN_HYST2 0x6e +#define LM85_REG_TACHO_MON_MODE 0x74 + #define ADM1027_REG_EXTEND_ADC1 0x76 #define ADM1027_REG_EXTEND_ADC2 0x77 @@ -185,11 +188,16 @@ static int RANGE_TO_REG(int range) #define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] /* These are the PWM frequency encodings */ -static const int lm85_freq_map[8] = { /* 1 Hz */ - 10, 15, 23, 30, 38, 47, 62, 94 +static const int lm85_freq_map[] = { /* 1 Hz */ + 10, 15, 23, 30, 38, 47, 62, 94, 0 +}; +static const int lm96000_freq_map[] = { /* 1 Hz */ + 10, 15, 23, 30, 38, 47, 61, 94, + 22500, 24000, 25700, 25700, + 27700, 27700, 30000, 30000, 0 }; -static const int adm1027_freq_map[8] = { /* 1 Hz */ - 11, 15, 22, 29, 35, 44, 59, 88 +static const int adm1027_freq_map[] = { /* 1 Hz */ + 11, 15, 22, 29, 35, 44, 59, 88, 0 }; static int FREQ_TO_REG(const int *map, int freq) @@ -197,7 +205,7 @@ static int FREQ_TO_REG(const int *map, i int i; /* Find the closest match */ - for (i = 0; i < 7; ++i) + for (i = 0; map[i + 1]; i++) if (freq <= (map[i] + map[i + 1]) / 2) break; return i; @@ -205,7 +213,13 @@ static int FREQ_TO_REG(const int *map, i static int FREQ_FROM_REG(const int *map, u8 reg) { - return map[reg & 0x07]; + int i; + + for (i = 0; map[i]; i++) + if (reg == i) + break; + + return map[i]; } /* Since we can't use strings, I'm abusing these numbers @@ -304,6 +318,7 @@ struct lm85_data { u8 temp_ext[3]; /* Decoded values */ u8 in_ext[8]; /* Decoded values */ u8 vid; /* Register value */ + u8 tmm; /* Register value */ u8 vrm; /* VRM version */ u32 alarms; /* Register encoding, combined */ struct lm85_autofan autofan[3]; @@ -327,6 +342,7 @@ static const struct i2c_device_id lm85_i { "lm85", any_chip }, { "lm85b", lm85b }, { "lm85c", lm85c }, + { "lm96000", lm96000 }, { "emc6d100", emc6d100 }, { "emc6d101", emc6d100 }, { "emc6d102", emc6d102 }, @@ -567,7 +583,31 @@ static ssize_t set_pwm_freq(struct devic data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) - | data->pwm_freq[nr]); + | (data->pwm_freq[nr] & 0x0f)); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_pwm_tmm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf, "%d\n", (data->tmm >> (2*nr)) & 3); +} + +static ssize_t set_pwm_tmm(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int mask = 3 << (2*nr); + + mutex_lock(&data->update_lock); + data->tmm = (data->tmm & ~mask) | ((val & 3) << (2*nr)); + lm85_write_value(client, LM85_REG_TACHO_MON_MODE, data->tmm); mutex_unlock(&data->update_lock); return count; } @@ -578,7 +618,9 @@ static SENSOR_DEVICE_ATTR(pwm##offset, S static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ show_pwm_enable, set_pwm_enable, offset - 1); \ static SENSOR_DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ - show_pwm_freq, set_pwm_freq, offset - 1) + show_pwm_freq, set_pwm_freq, offset - 1); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_tmm, S_IRUGO | S_IWUSR, \ + show_pwm_tmm, set_pwm_tmm, offset - 1) show_pwm_reg(1); show_pwm_reg(2); @@ -885,7 +927,7 @@ static ssize_t set_temp_auto_temp_min(st TEMP_FROM_REG(data->zone[nr].limit)); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | (data->pwm_freq[nr] & 0x0f)); /* Update temp_auto_hyst and temp_auto_off */ data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG( @@ -928,7 +970,7 @@ static ssize_t set_temp_auto_temp_max(st val - min); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | (data->pwm_freq[nr] & 0x0f)); mutex_unlock(&data->update_lock); return count; } @@ -998,6 +1040,9 @@ static struct attribute *lm85_attributes &sensor_dev_attr_pwm1_freq.dev_attr.attr, &sensor_dev_attr_pwm2_freq.dev_attr.attr, &sensor_dev_attr_pwm3_freq.dev_attr.attr, + &sensor_dev_attr_pwm1_tmm.dev_attr.attr, + &sensor_dev_attr_pwm2_tmm.dev_attr.attr, + &sensor_dev_attr_pwm3_tmm.dev_attr.attr, &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -1153,6 +1198,9 @@ static int lm85_detect(struct i2c_client case LM85_VERSTEP_LM85B: kind = lm85b; break; + case LM85_VERSTEP_LM96000: + kind = lm96000; + break; } } else if (company == LM85_COMPANY_ANALOG_DEV) { switch (verstep) { @@ -1189,6 +1237,9 @@ static int lm85_detect(struct i2c_client case lm85c: type_name = "lm85c"; break; + case lm96000: + type_name = "lm96000"; + break; case adm1027: type_name = "adm1027"; break; @@ -1231,6 +1282,9 @@ static int lm85_probe(struct i2c_client case emc6d102: data->freq_map = adm1027_freq_map; break; + case lm96000: + data->freq_map = lm96000_freq_map; + break; default: data->freq_map = lm85_freq_map; } @@ -1394,6 +1448,9 @@ static struct lm85_data *lm85_update_dev lm85_read_value(client, LM85_REG_PWM(i)); } + /* maybe restrict to LM85/LM96000? */ + data->tmm = lm85_read_value(client, LM85_REG_TACHO_MON_MODE); + data->alarms = lm85_read_value(client, LM85_REG_ALARM1); if (data->type == emc6d100) { @@ -1473,7 +1530,7 @@ static struct lm85_data *lm85_update_dev 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->pwm_freq[i] = val & 0x0f; data->zone[i].range = val >> 4; data->autofan[i].min_pwm = lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));