|
@@ -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",
|