diff options
Diffstat (limited to 'drivers/hwmon/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 72 |
1 files changed, 58 insertions, 14 deletions
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] = |