diff options
author | Jean Delvare <khali@linux-fr.org> | 2006-01-18 17:22:12 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-23 17:21:52 -0500 |
commit | c2db6ce14a743ac5f8973124272cf425c4f86b90 (patch) | |
tree | ae55d515d46acf40c52b0b62c2ee31ae6c3a0897 /drivers/hwmon | |
parent | f08191849e42e67ab6ad556d9c2e8cbed1ddf303 (diff) |
[PATCH] hwmon: Add support for the Winbond W83687THF
Add support for the Winbond W83687THF chip to the w83627hf hardware
monitoring driver. This new chip is almost similar to the already
supported W83627THF chip, except for VID and a few other minor
changes.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 7 | ||||
-rw-r--r-- | drivers/hwmon/w83627hf.c | 72 |
2 files changed, 62 insertions, 17 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 7230d4e08196..99cdc612d2c6 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -406,13 +406,14 @@ config SENSORS_W83L785TS | |||
406 | will be called w83l785ts. | 406 | will be called w83l785ts. |
407 | 407 | ||
408 | config SENSORS_W83627HF | 408 | config SENSORS_W83627HF |
409 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" | 409 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" |
410 | depends on HWMON && I2C && EXPERIMENTAL | 410 | depends on HWMON && I2C |
411 | select I2C_ISA | 411 | select I2C_ISA |
412 | select HWMON_VID | 412 | select HWMON_VID |
413 | help | 413 | help |
414 | If you say yes here you get support for the Winbond W836X7 series | 414 | If you say yes here you get support for the Winbond W836X7 series |
415 | of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF | 415 | of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and |
416 | W83697HF. | ||
416 | 417 | ||
417 | This driver can also be built as a module. If so, the module | 418 | This driver can also be built as a module. If so, the module |
418 | will be called w83627hf. | 419 | will be called w83627hf. |
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 3d4888c178c9..992e34402705 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -28,6 +28,7 @@ | |||
28 | w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) | 28 | w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) |
29 | w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) | 29 | w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) |
30 | w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) | 30 | w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) |
31 | w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) | ||
31 | w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) | 32 | w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) |
32 | 33 | ||
33 | For other winbond chips, and for i2c support in the above chips, | 34 | For other winbond chips, and for i2c support in the above chips, |
@@ -63,7 +64,7 @@ MODULE_PARM_DESC(force_i2c, | |||
63 | static unsigned short address; | 64 | static unsigned short address; |
64 | 65 | ||
65 | /* Insmod parameters */ | 66 | /* Insmod parameters */ |
66 | enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; | 67 | enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; |
67 | 68 | ||
68 | static int reset; | 69 | static int reset; |
69 | module_param(reset, bool, 0); | 70 | module_param(reset, bool, 0); |
@@ -101,6 +102,10 @@ static int VAL; /* The value to read/write */ | |||
101 | #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ | 102 | #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ |
102 | #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ | 103 | #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ |
103 | 104 | ||
105 | #define W83687THF_VID_EN 0x29 /* w83687thf only */ | ||
106 | #define W83687THF_VID_CFG 0xF0 /* w83687thf only */ | ||
107 | #define W83687THF_VID_DATA 0xF1 /* w83687thf only */ | ||
108 | |||
104 | static inline void | 109 | static inline void |
105 | superio_outb(int reg, int val) | 110 | superio_outb(int reg, int val) |
106 | { | 111 | { |
@@ -139,6 +144,7 @@ superio_exit(void) | |||
139 | #define W627THF_DEVID 0x82 | 144 | #define W627THF_DEVID 0x82 |
140 | #define W697_DEVID 0x60 | 145 | #define W697_DEVID 0x60 |
141 | #define W637_DEVID 0x70 | 146 | #define W637_DEVID 0x70 |
147 | #define W687THF_DEVID 0x85 | ||
142 | #define WINB_ACT_REG 0x30 | 148 | #define WINB_ACT_REG 0x30 |
143 | #define WINB_BASE_REG 0x60 | 149 | #define WINB_BASE_REG 0x60 |
144 | /* Constants specified below */ | 150 | /* Constants specified below */ |
@@ -202,11 +208,11 @@ superio_exit(void) | |||
202 | #define W83627HF_REG_PWM1 0x5A | 208 | #define W83627HF_REG_PWM1 0x5A |
203 | #define W83627HF_REG_PWM2 0x5B | 209 | #define W83627HF_REG_PWM2 0x5B |
204 | 210 | ||
205 | #define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ | 211 | #define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ |
206 | #define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ | 212 | #define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ |
207 | #define W83627THF_REG_PWM3 0x11 /* 637HF too */ | 213 | #define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ |
208 | 214 | ||
209 | #define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ | 215 | #define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ |
210 | 216 | ||
211 | static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; | 217 | static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; |
212 | static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, | 218 | static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, |
@@ -319,7 +325,7 @@ struct w83627hf_data { | |||
319 | Default = 3435. | 325 | Default = 3435. |
320 | Other Betas unimplemented */ | 326 | Other Betas unimplemented */ |
321 | u8 vrm; | 327 | u8 vrm; |
322 | u8 vrm_ovt; /* Register value, 627thf & 637hf only */ | 328 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ |
323 | }; | 329 | }; |
324 | 330 | ||
325 | 331 | ||
@@ -414,7 +420,8 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) | |||
414 | long in0; | 420 | long in0; |
415 | 421 | ||
416 | if ((data->vrm_ovt & 0x01) && | 422 | if ((data->vrm_ovt & 0x01) && |
417 | (w83627thf == data->type || w83637hf == data->type)) | 423 | (w83627thf == data->type || w83637hf == data->type |
424 | || w83687thf == data->type)) | ||
418 | 425 | ||
419 | /* use VRM9 calculation */ | 426 | /* use VRM9 calculation */ |
420 | in0 = (long)((reg * 488 + 70000 + 50) / 100); | 427 | in0 = (long)((reg * 488 + 70000 + 50) / 100); |
@@ -455,7 +462,8 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a | |||
455 | mutex_lock(&data->update_lock); | 462 | mutex_lock(&data->update_lock); |
456 | 463 | ||
457 | if ((data->vrm_ovt & 0x01) && | 464 | if ((data->vrm_ovt & 0x01) && |
458 | (w83627thf == data->type || w83637hf == data->type)) | 465 | (w83627thf == data->type || w83637hf == data->type |
466 | || w83687thf == data->type)) | ||
459 | 467 | ||
460 | /* use VRM9 calculation */ | 468 | /* use VRM9 calculation */ |
461 | data->in_min[0] = | 469 | data->in_min[0] = |
@@ -482,7 +490,8 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a | |||
482 | mutex_lock(&data->update_lock); | 490 | mutex_lock(&data->update_lock); |
483 | 491 | ||
484 | if ((data->vrm_ovt & 0x01) && | 492 | if ((data->vrm_ovt & 0x01) && |
485 | (w83627thf == data->type || w83637hf == data->type)) | 493 | (w83627thf == data->type || w83637hf == data->type |
494 | || w83687thf == data->type)) | ||
486 | 495 | ||
487 | /* use VRM9 calculation */ | 496 | /* use VRM9 calculation */ |
488 | data->in_max[0] = | 497 | data->in_max[0] = |
@@ -981,7 +990,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) | |||
981 | if(val != W627_DEVID && | 990 | if(val != W627_DEVID && |
982 | val != W627THF_DEVID && | 991 | val != W627THF_DEVID && |
983 | val != W697_DEVID && | 992 | val != W697_DEVID && |
984 | val != W637_DEVID) { | 993 | val != W637_DEVID && |
994 | val != W687THF_DEVID) { | ||
985 | superio_exit(); | 995 | superio_exit(); |
986 | return -ENODEV; | 996 | return -ENODEV; |
987 | } | 997 | } |
@@ -1035,6 +1045,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1035 | kind = w83627thf; | 1045 | kind = w83627thf; |
1036 | else if(val == W637_DEVID) | 1046 | else if(val == W637_DEVID) |
1037 | kind = w83637hf; | 1047 | kind = w83637hf; |
1048 | else if (val == W687THF_DEVID) | ||
1049 | kind = w83687thf; | ||
1038 | else { | 1050 | else { |
1039 | dev_info(&adapter->dev, | 1051 | dev_info(&adapter->dev, |
1040 | "Unsupported chip (dev_id=0x%02X).\n", val); | 1052 | "Unsupported chip (dev_id=0x%02X).\n", val); |
@@ -1072,6 +1084,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1072 | client_name = "w83697hf"; | 1084 | client_name = "w83697hf"; |
1073 | } else if (kind == w83637hf) { | 1085 | } else if (kind == w83637hf) { |
1074 | client_name = "w83637hf"; | 1086 | client_name = "w83637hf"; |
1087 | } else if (kind == w83687thf) { | ||
1088 | client_name = "w83687thf"; | ||
1075 | } | 1089 | } |
1076 | 1090 | ||
1077 | /* Fill in the remaining client fields and put into the global list */ | 1091 | /* Fill in the remaining client fields and put into the global list */ |
@@ -1107,7 +1121,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1107 | device_create_file_in(new_client, 2); | 1121 | device_create_file_in(new_client, 2); |
1108 | device_create_file_in(new_client, 3); | 1122 | device_create_file_in(new_client, 3); |
1109 | device_create_file_in(new_client, 4); | 1123 | device_create_file_in(new_client, 4); |
1110 | if (kind != w83627thf && kind != w83637hf) { | 1124 | if (kind == w83627hf || kind == w83697hf) { |
1111 | device_create_file_in(new_client, 5); | 1125 | device_create_file_in(new_client, 5); |
1112 | device_create_file_in(new_client, 6); | 1126 | device_create_file_in(new_client, 6); |
1113 | } | 1127 | } |
@@ -1140,7 +1154,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1140 | 1154 | ||
1141 | device_create_file_pwm(new_client, 1); | 1155 | device_create_file_pwm(new_client, 1); |
1142 | device_create_file_pwm(new_client, 2); | 1156 | device_create_file_pwm(new_client, 2); |
1143 | if (kind == w83627thf || kind == w83637hf) | 1157 | if (kind == w83627thf || kind == w83637hf || kind == w83687thf) |
1144 | device_create_file_pwm(new_client, 3); | 1158 | device_create_file_pwm(new_client, 3); |
1145 | 1159 | ||
1146 | device_create_file_sensor(new_client, 1); | 1160 | device_create_file_sensor(new_client, 1); |
@@ -1248,6 +1262,33 @@ exit: | |||
1248 | return res; | 1262 | return res; |
1249 | } | 1263 | } |
1250 | 1264 | ||
1265 | static int w83687thf_read_vid(struct i2c_client *client) | ||
1266 | { | ||
1267 | int res = 0xff; | ||
1268 | |||
1269 | superio_enter(); | ||
1270 | superio_select(W83627HF_LD_HWM); | ||
1271 | |||
1272 | /* Make sure these GPIO pins are enabled */ | ||
1273 | if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { | ||
1274 | dev_dbg(&client->dev, "VID disabled, no VID function\n"); | ||
1275 | goto exit; | ||
1276 | } | ||
1277 | |||
1278 | /* Make sure the pins are configured for input */ | ||
1279 | if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { | ||
1280 | dev_dbg(&client->dev, "VID configured as output, " | ||
1281 | "no VID function\n"); | ||
1282 | goto exit; | ||
1283 | } | ||
1284 | |||
1285 | res = superio_inb(W83687THF_VID_DATA) & 0x3f; | ||
1286 | |||
1287 | exit: | ||
1288 | superio_exit(); | ||
1289 | return res; | ||
1290 | } | ||
1291 | |||
1251 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) | 1292 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) |
1252 | { | 1293 | { |
1253 | struct w83627hf_data *data = i2c_get_clientdata(client); | 1294 | struct w83627hf_data *data = i2c_get_clientdata(client); |
@@ -1325,10 +1366,13 @@ static void w83627hf_init_client(struct i2c_client *client) | |||
1325 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); | 1366 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); |
1326 | } else if (w83627thf == data->type) { | 1367 | } else if (w83627thf == data->type) { |
1327 | data->vid = w83627thf_read_gpio5(client); | 1368 | data->vid = w83627thf_read_gpio5(client); |
1369 | } else if (w83687thf == data->type) { | ||
1370 | data->vid = w83687thf_read_vid(client); | ||
1328 | } | 1371 | } |
1329 | 1372 | ||
1330 | /* Read VRM & OVT Config only once */ | 1373 | /* Read VRM & OVT Config only once */ |
1331 | if (w83627thf == data->type || w83637hf == data->type) { | 1374 | if (w83627thf == data->type || w83637hf == data->type |
1375 | || w83687thf == data->type) { | ||
1332 | data->vrm_ovt = | 1376 | data->vrm_ovt = |
1333 | w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); | 1377 | w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); |
1334 | } | 1378 | } |
@@ -1395,7 +1439,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1395 | for (i = 0; i <= 8; i++) { | 1439 | for (i = 0; i <= 8; i++) { |
1396 | /* skip missing sensors */ | 1440 | /* skip missing sensors */ |
1397 | if (((data->type == w83697hf) && (i == 1)) || | 1441 | if (((data->type == w83697hf) && (i == 1)) || |
1398 | ((data->type == w83627thf || data->type == w83637hf) | 1442 | ((data->type != w83627hf && data->type != w83697hf) |
1399 | && (i == 5 || i == 6))) | 1443 | && (i == 5 || i == 6))) |
1400 | continue; | 1444 | continue; |
1401 | data->in[i] = | 1445 | data->in[i] = |