aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/w83627ehf.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index ec595c606ed4..a25350cf9554 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -240,6 +240,8 @@ static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
240static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] 240static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[]
241 = { 0x68, 0x6a, 0x6c }; 241 = { 0x68, 0x6a, 0x6c };
242 242
243static const u16 W83627EHF_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
244
243static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 }; 245static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 };
244static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 }; 246static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 };
245static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 }; 247static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 };
@@ -465,6 +467,7 @@ struct w83627ehf_data {
465 u8 has_fan_min; /* some fans don't have min register */ 467 u8 has_fan_min; /* some fans don't have min register */
466 bool has_fan_div; 468 bool has_fan_div;
467 u8 temp_type[3]; 469 u8 temp_type[3];
470 s8 temp_offset[3];
468 s16 temp[9]; 471 s16 temp[9];
469 s16 temp_max[9]; 472 s16 temp_max[9];
470 s16 temp_max_hyst[9]; 473 s16 temp_max_hyst[9];
@@ -496,6 +499,7 @@ struct w83627ehf_data {
496 u8 vrm; 499 u8 vrm;
497 500
498 u16 have_temp; 501 u16 have_temp;
502 u16 have_temp_offset;
499 u8 in6_skip:1; 503 u8 in6_skip:1;
500 u8 temp3_val_only:1; 504 u8 temp3_val_only:1;
501}; 505};
@@ -893,6 +897,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
893 data->temp_max_hyst[i] 897 data->temp_max_hyst[i]
894 = w83627ehf_read_temp(data, 898 = w83627ehf_read_temp(data,
895 data->reg_temp_hyst[i]); 899 data->reg_temp_hyst[i]);
900 if (data->have_temp_offset & (1 << i))
901 data->temp_offset[i]
902 = w83627ehf_read_value(data,
903 W83627EHF_REG_TEMP_OFFSET[i]);
896 } 904 }
897 905
898 data->alarms = w83627ehf_read_value(data, 906 data->alarms = w83627ehf_read_value(data,
@@ -1226,6 +1234,39 @@ store_temp_reg(reg_temp_over, temp_max);
1226store_temp_reg(reg_temp_hyst, temp_max_hyst); 1234store_temp_reg(reg_temp_hyst, temp_max_hyst);
1227 1235
1228static ssize_t 1236static ssize_t
1237show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1238{
1239 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1240 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1241
1242 return sprintf(buf, "%d\n",
1243 data->temp_offset[sensor_attr->index] * 1000);
1244}
1245
1246static ssize_t
1247store_temp_offset(struct device *dev, struct device_attribute *attr,
1248 const char *buf, size_t count)
1249{
1250 struct w83627ehf_data *data = dev_get_drvdata(dev);
1251 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1252 int nr = sensor_attr->index;
1253 long val;
1254 int err;
1255
1256 err = kstrtol(buf, 10, &val);
1257 if (err < 0)
1258 return err;
1259
1260 val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1261
1262 mutex_lock(&data->update_lock);
1263 data->temp_offset[nr] = val;
1264 w83627ehf_write_value(data, W83627EHF_REG_TEMP_OFFSET[nr], val);
1265 mutex_unlock(&data->update_lock);
1266 return count;
1267}
1268
1269static ssize_t
1229show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) 1270show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1230{ 1271{
1231 struct w83627ehf_data *data = w83627ehf_update_device(dev); 1272 struct w83627ehf_data *data = w83627ehf_update_device(dev);
@@ -1312,6 +1353,15 @@ static struct sensor_device_attribute sda_temp_type[] = {
1312 SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), 1353 SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
1313}; 1354};
1314 1355
1356static struct sensor_device_attribute sda_temp_offset[] = {
1357 SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1358 store_temp_offset, 0),
1359 SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1360 store_temp_offset, 1),
1361 SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1362 store_temp_offset, 2),
1363};
1364
1315#define show_pwm_reg(reg) \ 1365#define show_pwm_reg(reg) \
1316static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ 1366static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1317 char *buf) \ 1367 char *buf) \
@@ -1804,6 +1854,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
1804 continue; 1854 continue;
1805 device_remove_file(dev, &sda_temp_alarm[i].dev_attr); 1855 device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
1806 device_remove_file(dev, &sda_temp_type[i].dev_attr); 1856 device_remove_file(dev, &sda_temp_type[i].dev_attr);
1857 device_remove_file(dev, &sda_temp_offset[i].dev_attr);
1807 } 1858 }
1808 1859
1809 device_remove_file(dev, &sda_caseopen[0].dev_attr); 1860 device_remove_file(dev, &sda_caseopen[0].dev_attr);
@@ -2126,6 +2177,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2126 } else { 2177 } else {
2127 data->temp_label = nct6775_temp_label; 2178 data->temp_label = nct6775_temp_label;
2128 } 2179 }
2180 data->have_temp_offset = data->have_temp & 0x07;
2181 for (i = 0; i < 3; i++) {
2182 if (data->temp_src[i] > 3)
2183 data->have_temp_offset &= ~(1 << i);
2184 }
2129 } else if (sio_data->kind == w83667hg_b) { 2185 } else if (sio_data->kind == w83667hg_b) {
2130 u8 reg; 2186 u8 reg;
2131 2187
@@ -2168,6 +2224,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2168 data->in6_skip = 1; 2224 data->in6_skip = 1;
2169 2225
2170 data->temp_label = w83667hg_b_temp_label; 2226 data->temp_label = w83667hg_b_temp_label;
2227 data->have_temp_offset = data->have_temp & 0x07;
2228 for (i = 0; i < 3; i++) {
2229 if (data->temp_src[i] > 2)
2230 data->have_temp_offset &= ~(1 << i);
2231 }
2171 } else if (sio_data->kind == w83627uhg) { 2232 } else if (sio_data->kind == w83627uhg) {
2172 u8 reg; 2233 u8 reg;
2173 2234
@@ -2204,6 +2265,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2204 data->in6_skip = 1; /* No VIN3 */ 2265 data->in6_skip = 1; /* No VIN3 */
2205 2266
2206 data->temp_label = w83667hg_b_temp_label; 2267 data->temp_label = w83667hg_b_temp_label;
2268 data->have_temp_offset = data->have_temp & 0x03;
2269 for (i = 0; i < 3; i++) {
2270 if (data->temp_src[i] > 1)
2271 data->have_temp_offset &= ~(1 << i);
2272 }
2207 } else { 2273 } else {
2208 w83627ehf_set_temp_reg_ehf(data, 3); 2274 w83627ehf_set_temp_reg_ehf(data, 3);
2209 2275
@@ -2223,6 +2289,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2223 else 2289 else
2224 data->in6_skip = 1; 2290 data->in6_skip = 1;
2225 } 2291 }
2292 data->have_temp_offset = data->have_temp & 0x07;
2226 } 2293 }
2227 2294
2228 if (sio_data->kind == nct6775) { 2295 if (sio_data->kind == nct6775) {
@@ -2488,6 +2555,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2488 || (err = device_create_file(dev, 2555 || (err = device_create_file(dev,
2489 &sda_temp_type[i].dev_attr))) 2556 &sda_temp_type[i].dev_attr)))
2490 goto exit_remove; 2557 goto exit_remove;
2558 if (data->have_temp_offset & (1 << i)) {
2559 err = device_create_file(dev,
2560 &sda_temp_offset[i].dev_attr);
2561 if (err)
2562 goto exit_remove;
2563 }
2491 } 2564 }
2492 2565
2493 err = device_create_file(dev, &sda_caseopen[0].dev_attr); 2566 err = device_create_file(dev, &sda_caseopen[0].dev_attr);