summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/w83627ehf.c106
2 files changed, 72 insertions, 38 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index b4eea0292c1..0eb4170cc4a 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -827,7 +827,7 @@ config SENSORS_W83627HF
will be called w83627hf.
config SENSORS_W83627EHF
- tristate "Winbond W83627EHF/DHG"
+ tristate "Winbond W83627EHF/EHG/DHG, W83667HG"
select HWMON_VID
help
If you say yes here you get support for the hardware
@@ -838,6 +838,8 @@ config SENSORS_W83627EHF
chip suited for specific Intel processors that use PECI such as
the Core 2 Duo.
+ This driver also supports the W83667HG chip.
+
This driver can also be built as a module. If so, the module
will be called w83627ehf.
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 18432e34dc7..20a9332959b 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -36,6 +36,7 @@
w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3
0x8860 0xa1
w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3
+ w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3
*/
#include <linux/module.h>
@@ -52,12 +53,13 @@
#include <asm/io.h>
#include "lm75.h"
-enum kinds { w83627ehf, w83627dhg };
+enum kinds { w83627ehf, w83627dhg, w83667hg };
/* used to set data->name = w83627ehf_device_names[data->sio_kind] */
static const char * w83627ehf_device_names[] = {
"w83627ehf",
"w83627dhg",
+ "w83667hg",
};
static unsigned short force_id;
@@ -71,6 +73,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
*/
#define W83627EHF_LD_HWM 0x0b
+#define W83667HG_LD_VID 0x0d
#define SIO_REG_LDSEL 0x07 /* Logical device select */
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
@@ -83,6 +86,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
#define SIO_W83627EHF_ID 0x8850
#define SIO_W83627EHG_ID 0x8860
#define SIO_W83627DHG_ID 0xa020
+#define SIO_W83667HG_ID 0xa510
#define SIO_ID_MASK 0xFFF0
static inline void
@@ -289,6 +293,7 @@ struct w83627ehf_data {
u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
u8 pwm_enable[4]; /* 1->manual
2->thermal cruise (also called SmartFan I) */
+ u8 pwm_num; /* number of pwm */
u8 pwm[4];
u8 target_temp[4];
u8 tolerance[4];
@@ -1192,7 +1197,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
device_remove_file(dev, &sda_fan_div[i].dev_attr);
device_remove_file(dev, &sda_fan_min[i].dev_attr);
}
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < data->pwm_num; i++) {
device_remove_file(dev, &sda_pwm[i].dev_attr);
device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
@@ -1272,8 +1277,10 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
data->name = w83627ehf_device_names[sio_data->kind];
platform_set_drvdata(pdev, data);
- /* 627EHG and 627EHF have 10 voltage inputs; DHG has 9 */
- data->in_num = (sio_data->kind == w83627dhg) ? 9 : 10;
+ /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
+ data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
+ /* 667HG has 3 pwms */
+ data->pwm_num = (sio_data->kind == w83667hg) ? 3 : 4;
/* Initialize the chip */
w83627ehf_init_device(data);
@@ -1281,44 +1288,64 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
data->vrm = vid_which_vrm();
superio_enter(sio_data->sioreg);
/* Read VID value */
- superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
- if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
- /* Set VID input sensibility if needed. In theory the BIOS
- should have set it, but in practice it's not always the
- case. We only do it for the W83627EHF/EHG because the
- W83627DHG is more complex in this respect. */
- if (sio_data->kind == w83627ehf) {
- en_vrm10 = superio_inb(sio_data->sioreg,
- SIO_REG_EN_VRM10);
- if ((en_vrm10 & 0x08) && data->vrm == 90) {
- dev_warn(dev, "Setting VID input voltage to "
- "TTL\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 & ~0x08);
- } else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
- dev_warn(dev, "Setting VID input voltage to "
- "VRM10\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 | 0x08);
- }
- }
-
- data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA);
- if (sio_data->kind == w83627ehf) /* 6 VID pins only */
- data->vid &= 0x3f;
-
+ if (sio_data->kind == w83667hg) {
+ /* W83667HG has different pins for VID input and output, so
+ we can get the VID input values directly at logical device D
+ 0xe3. */
+ superio_select(sio_data->sioreg, W83667HG_LD_VID);
+ data->vid = superio_inb(sio_data->sioreg, 0xe3);
err = device_create_file(dev, &dev_attr_cpu0_vid);
if (err)
goto exit_release;
} else {
- dev_info(dev, "VID pins in output mode, CPU VID not "
- "available\n");
+ superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+ if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
+ /* Set VID input sensibility if needed. In theory the
+ BIOS should have set it, but in practice it's not
+ always the case. We only do it for the W83627EHF/EHG
+ because the W83627DHG is more complex in this
+ respect. */
+ if (sio_data->kind == w83627ehf) {
+ en_vrm10 = superio_inb(sio_data->sioreg,
+ SIO_REG_EN_VRM10);
+ if ((en_vrm10 & 0x08) && data->vrm == 90) {
+ dev_warn(dev, "Setting VID input "
+ "voltage to TTL\n");
+ superio_outb(sio_data->sioreg,
+ SIO_REG_EN_VRM10,
+ en_vrm10 & ~0x08);
+ } else if (!(en_vrm10 & 0x08)
+ && data->vrm == 100) {
+ dev_warn(dev, "Setting VID input "
+ "voltage to VRM10\n");
+ superio_outb(sio_data->sioreg,
+ SIO_REG_EN_VRM10,
+ en_vrm10 | 0x08);
+ }
+ }
+
+ data->vid = superio_inb(sio_data->sioreg,
+ SIO_REG_VID_DATA);
+ if (sio_data->kind == w83627ehf) /* 6 VID pins only */
+ data->vid &= 0x3f;
+
+ err = device_create_file(dev, &dev_attr_cpu0_vid);
+ if (err)
+ goto exit_release;
+ } else {
+ dev_info(dev, "VID pins in output mode, CPU VID not "
+ "available\n");
+ }
}
/* fan4 and fan5 share some pins with the GPIO and serial flash */
-
- fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x2);
- fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x6);
+ if (sio_data->kind == w83667hg) {
+ fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+ fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
+ } else {
+ fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+ fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+ }
superio_exit(sio_data->sioreg);
/* It looks like fan4 and fan5 pins can be alternatively used
@@ -1344,7 +1371,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
goto exit_remove;
/* if fan4 is enabled create the sf3 files for it */
- if (data->has_fan & (1 << 3))
+ if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
if ((err = device_create_file(dev,
&sda_sf3_arrays_fan4[i].dev_attr)))
@@ -1372,7 +1399,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
|| (err = device_create_file(dev,
&sda_fan_min[i].dev_attr)))
goto exit_remove;
- if (i < 4 && /* w83627ehf only has 4 pwm */
+ if (i < data->pwm_num &&
((err = device_create_file(dev,
&sda_pwm[i].dev_attr))
|| (err = device_create_file(dev,
@@ -1442,6 +1469,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
+ static const char __initdata sio_name_W83667HG[] = "W83667HG";
u16 val;
const char *sio_name;
@@ -1466,6 +1494,10 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
sio_data->kind = w83627dhg;
sio_name = sio_name_W83627DHG;
break;
+ case SIO_W83667HG_ID:
+ sio_data->kind = w83667hg;
+ sio_name = sio_name_W83667HG;
+ break;
default:
if (val != 0xffff)
pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",