aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-02-07 18:08:54 -0500
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-03-15 01:39:14 -0400
commitd36cf32c9a6c4ffea8f2108a05defb55800f9215 (patch)
tree7d663ef2b91947314d6b39d1af83ec6c4c5d823c
parent83cc8985b82dff2ef85987a8481a92aab1b33323 (diff)
hwmon: (w83627ehf) Improve support for W83667HG-B
Add support for 4th temperature sensor on W83677HG-B. Display temperature labels on W83677HG-B to report temperature sources. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Acked-by: Ian Dobson <i.dobson@planet-ian.com>
-rw-r--r--Documentation/hwmon/w83627ehf19
-rw-r--r--drivers/hwmon/w83627ehf.c155
2 files changed, 136 insertions, 38 deletions
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index 13d556112fc0..064301944d49 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -39,16 +39,21 @@ This driver implements support for the Winbond W83627EHF, W83627EHG,
39W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips. 39W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips.
40We will refer to them collectively as Winbond chips. 40We will refer to them collectively as Winbond chips.
41 41
42The chips implement three temperature sensors, five fan rotation 42The chips implement three temperature sensors (up to four for 667HG-B),
43speed sensors, ten analog voltage sensors (only nine for the 627DHG), one 43five fan rotation speed sensors, ten analog voltage sensors (only nine for the
44VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG), alarms 44627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG),
45with beep warnings (control unimplemented), and some automatic fan 45alarms with beep warnings (control unimplemented), and some automatic fan
46regulation strategies (plus manual fan control mode). 46regulation strategies (plus manual fan control mode).
47 47
48The temperature sensor sources on W82677HG-B are configurable. temp4 is only
49reported if its temperature source differs from the temperature sources of the
50other three temperature sensors. The configured source for each of the
51temperature sensors is reported in tempX_label.
52
48Temperatures are measured in degrees Celsius and measurement resolution is 1 53Temperatures are measured in degrees Celsius and measurement resolution is 1
49degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when 54degC for temp1 and temp4, and 0.5 degC for temp2 and temp3. An alarm is
50the temperature gets higher than high limit; it stays on until the temperature 55triggered when the temperature gets higher than high limit; it stays on until
51falls below the hysteresis value. 56the temperature falls below the hysteresis value.
52 57
53Fan rotation speeds are reported in RPM (rotations per minute). An alarm is 58Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
54triggered if the rotation speed has dropped below a programmable limit. Fan 59triggered if the rotation speed has dropped below a programmable limit. Fan
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 5a627b9db3e8..d10fe706c856 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -39,7 +39,7 @@
39 w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 39 w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3
40 w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 40 w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3
41 w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 41 w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3
42 w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3 42 w83667hg-b 9 5 3 4 0xb350 0xc1 0x5ca3
43*/ 43*/
44 44
45#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 45#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -164,10 +164,10 @@ static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
164#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ 164#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
165 (0x550 + (nr) - 7)) 165 (0x550 + (nr) - 7))
166 166
167static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250 }; 167static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e };
168static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253 }; 168static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 };
169static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255 }; 169static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 };
170static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252 }; 170static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };
171 171
172/* Fan clock dividers are spread over the following five registers */ 172/* Fan clock dividers are spread over the following five registers */
173#define W83627EHF_REG_FANDIV1 0x47 173#define W83627EHF_REG_FANDIV1 0x47
@@ -213,6 +213,19 @@ static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
213static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b }; 213static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
214static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c }; 214static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c };
215 215
216static const char *const w83667hg_b_temp_label[] = {
217 "SYSTIN",
218 "CPUTIN",
219 "AUXTIN",
220 "AMDTSI",
221 "PECI Agent 1",
222 "PECI Agent 2",
223 "PECI Agent 3",
224 "PECI Agent 4"
225};
226
227#define NUM_REG_TEMP 4
228
216static inline int is_word_sized(u16 reg) 229static inline int is_word_sized(u16 reg)
217{ 230{
218 return (((reg & 0xff00) == 0x100 231 return (((reg & 0xff00) == 0x100
@@ -294,6 +307,9 @@ struct w83627ehf_data {
294 struct device *hwmon_dev; 307 struct device *hwmon_dev;
295 struct mutex lock; 308 struct mutex lock;
296 309
310 u8 temp_src[NUM_REG_TEMP];
311 const char * const *temp_label;
312
297 const u8 *REG_FAN_START_OUTPUT; 313 const u8 *REG_FAN_START_OUTPUT;
298 const u8 *REG_FAN_STOP_OUTPUT; 314 const u8 *REG_FAN_STOP_OUTPUT;
299 const u8 *REG_FAN_MAX_OUTPUT; 315 const u8 *REG_FAN_MAX_OUTPUT;
@@ -314,9 +330,9 @@ struct w83627ehf_data {
314 u8 fan_div[5]; 330 u8 fan_div[5];
315 u8 has_fan; /* some fan inputs can be disabled */ 331 u8 has_fan; /* some fan inputs can be disabled */
316 u8 temp_type[3]; 332 u8 temp_type[3];
317 s16 temp[3]; 333 s16 temp[4];
318 s16 temp_max[3]; 334 s16 temp_max[4];
319 s16 temp_max_hyst[3]; 335 s16 temp_max_hyst[4];
320 u32 alarms; 336 u32 alarms;
321 337
322 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ 338 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
@@ -339,7 +355,7 @@ struct w83627ehf_data {
339 u8 vid; 355 u8 vid;
340 u8 vrm; 356 u8 vrm;
341 357
342 u8 temp3_disable; 358 u8 have_temp;
343 u8 in6_skip; 359 u8 in6_skip;
344}; 360};
345 361
@@ -577,12 +593,18 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
577 } 593 }
578 594
579 /* Measured temperatures and limits */ 595 /* Measured temperatures and limits */
580 for (i = 0; i < 3; i++) { 596 for (i = 0; i < NUM_REG_TEMP; i++) {
581 data->temp[i] = w83627ehf_read_value(data, 597 if (!(data->have_temp & (1 << i)))
582 W83627EHF_REG_TEMP[i]); 598 continue;
583 data->temp_max[i] = w83627ehf_read_value(data, 599 data->temp[i]
584 W83627EHF_REG_TEMP_OVER[i]); 600 = w83627ehf_read_value(data, W83627EHF_REG_TEMP[i]);
585 data->temp_max_hyst[i] = w83627ehf_read_value(data, 601 if (i > 2)
602 break;
603 data->temp_max[i]
604 = w83627ehf_read_value(data,
605 W83627EHF_REG_TEMP_OVER[i]);
606 data->temp_max_hyst[i]
607 = w83627ehf_read_value(data,
586 W83627EHF_REG_TEMP_HYST[i]); 608 W83627EHF_REG_TEMP_HYST[i]);
587 } 609 }
588 610
@@ -844,6 +866,15 @@ static struct sensor_device_attribute sda_fan_div[] = {
844 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), 866 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
845}; 867};
846 868
869static ssize_t
870show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
871{
872 struct w83627ehf_data *data = w83627ehf_update_device(dev);
873 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
874 int nr = sensor_attr->index;
875 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
876}
877
847#define show_temp_reg(REG, reg) \ 878#define show_temp_reg(REG, reg) \
848static ssize_t \ 879static ssize_t \
849show_##reg(struct device *dev, struct device_attribute *attr, \ 880show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -897,6 +928,14 @@ static struct sensor_device_attribute sda_temp_input[] = {
897 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), 928 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
898 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), 929 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
899 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), 930 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
931 SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3),
932};
933
934static struct sensor_device_attribute sda_temp_label[] = {
935 SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
936 SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
937 SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
938 SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
900}; 939};
901 940
902static struct sensor_device_attribute sda_temp_max[] = { 941static struct sensor_device_attribute sda_temp_max[] = {
@@ -1328,10 +1367,13 @@ static void w83627ehf_device_remove_files(struct device *dev)
1328 device_remove_file(dev, &sda_target_temp[i].dev_attr); 1367 device_remove_file(dev, &sda_target_temp[i].dev_attr);
1329 device_remove_file(dev, &sda_tolerance[i].dev_attr); 1368 device_remove_file(dev, &sda_tolerance[i].dev_attr);
1330 } 1369 }
1331 for (i = 0; i < 3; i++) { 1370 for (i = 0; i < NUM_REG_TEMP; i++) {
1332 if ((i == 2) && data->temp3_disable) 1371 if (!(data->have_temp & (1 << i)))
1333 continue; 1372 continue;
1334 device_remove_file(dev, &sda_temp_input[i].dev_attr); 1373 device_remove_file(dev, &sda_temp_input[i].dev_attr);
1374 device_remove_file(dev, &sda_temp_label[i].dev_attr);
1375 if (i > 2)
1376 break;
1335 device_remove_file(dev, &sda_temp_max[i].dev_attr); 1377 device_remove_file(dev, &sda_temp_max[i].dev_attr);
1336 device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); 1378 device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
1337 device_remove_file(dev, &sda_temp_alarm[i].dev_attr); 1379 device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
@@ -1354,12 +1396,14 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
1354 w83627ehf_write_value(data, W83627EHF_REG_CONFIG, 1396 w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
1355 tmp | 0x01); 1397 tmp | 0x01);
1356 1398
1357 /* Enable temp2 and temp3 if needed */ 1399 /* Enable temperature sensors if needed */
1358 for (i = 1; i < 3; i++) { 1400 for (i = 0; i < NUM_REG_TEMP; i++) {
1401 if (!(data->have_temp & (1 << i)))
1402 continue;
1403 if (!W83627EHF_REG_TEMP_CONFIG[i])
1404 continue;
1359 tmp = w83627ehf_read_value(data, 1405 tmp = w83627ehf_read_value(data,
1360 W83627EHF_REG_TEMP_CONFIG[i]); 1406 W83627EHF_REG_TEMP_CONFIG[i]);
1361 if ((i == 2) && data->temp3_disable)
1362 continue;
1363 if (tmp & 0x01) 1407 if (tmp & 0x01)
1364 w83627ehf_write_value(data, 1408 w83627ehf_write_value(data,
1365 W83627EHF_REG_TEMP_CONFIG[i], 1409 W83627EHF_REG_TEMP_CONFIG[i],
@@ -1417,11 +1461,52 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
1417 data->pwm_num = (sio_data->kind == w83667hg 1461 data->pwm_num = (sio_data->kind == w83667hg
1418 || sio_data->kind == w83667hg_b) ? 3 : 4; 1462 || sio_data->kind == w83667hg_b) ? 3 : 4;
1419 1463
1464 data->have_temp = 0x07;
1420 /* Check temp3 configuration bit for 667HG */ 1465 /* Check temp3 configuration bit for 667HG */
1421 if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { 1466 if (sio_data->kind == w83667hg) {
1422 data->temp3_disable = w83627ehf_read_value(data, 1467 u8 reg;
1423 W83627EHF_REG_TEMP_CONFIG[2]) & 0x01; 1468
1424 data->in6_skip = !data->temp3_disable; 1469 reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
1470 if (reg & 0x01)
1471 data->have_temp &= ~(1 << 2);
1472 else
1473 data->in6_skip = 1; /* Either temp3 or in6 */
1474 } else if (sio_data->kind == w83667hg_b) {
1475 u8 reg;
1476
1477 reg = w83627ehf_read_value(data, 0x4a);
1478 data->temp_src[0] = reg >> 5;
1479 reg = w83627ehf_read_value(data, 0x49);
1480 data->temp_src[1] = reg & 0x07;
1481 data->temp_src[2] = (reg >> 4) & 0x07;
1482
1483 /*
1484 * W83667HG-B has another temperature register at 0x7e.
1485 * The temperature source is selected with register 0x7d.
1486 * Support it if the source differs from already reported
1487 * sources.
1488 */
1489 reg = w83627ehf_read_value(data, 0x7d);
1490 reg &= 0x07;
1491 if (reg != data->temp_src[0] && reg != data->temp_src[1]
1492 && reg != data->temp_src[2]) {
1493 data->temp_src[3] = reg;
1494 data->have_temp |= 1 << 3;
1495 }
1496
1497 /*
1498 * Chip supports either AUXTIN or VIN3. Try to find out which
1499 * one.
1500 */
1501 reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
1502 if (data->temp_src[2] == 2 && (reg & 0x01))
1503 data->have_temp &= ~(1 << 2);
1504
1505 if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2)))
1506 || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3))))
1507 data->in6_skip = 1;
1508
1509 data->temp_label = w83667hg_b_temp_label;
1425 } 1510 }
1426 1511
1427 data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; 1512 data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
@@ -1584,13 +1669,21 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
1584 } 1669 }
1585 } 1670 }
1586 1671
1587 for (i = 0; i < 3; i++) { 1672 for (i = 0; i < NUM_REG_TEMP; i++) {
1588 if ((i == 2) && data->temp3_disable) 1673 if (!(data->have_temp & (1 << i)))
1589 continue; 1674 continue;
1590 if ((err = device_create_file(dev, 1675 err = device_create_file(dev, &sda_temp_input[i].dev_attr);
1591 &sda_temp_input[i].dev_attr)) 1676 if (err)
1592 || (err = device_create_file(dev, 1677 goto exit_remove;
1593 &sda_temp_max[i].dev_attr)) 1678 if (data->temp_label) {
1679 err = device_create_file(dev,
1680 &sda_temp_label[i].dev_attr);
1681 if (err)
1682 goto exit_remove;
1683 }
1684 if (i > 2)
1685 break;
1686 if ((err = device_create_file(dev, &sda_temp_max[i].dev_attr))
1594 || (err = device_create_file(dev, 1687 || (err = device_create_file(dev,
1595 &sda_temp_max_hyst[i].dev_attr)) 1688 &sda_temp_max_hyst[i].dev_attr))
1596 || (err = device_create_file(dev, 1689 || (err = device_create_file(dev,