diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-01-31 12:24:00 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-01-31 12:24:00 -0500 |
commit | 30716e07ef511ec7525c07eb1e8060ba8943c2a2 (patch) | |
tree | eb6a47cae63d3587fa773cc5a16781eaa2c7810b /drivers/hwmon/w83793.c | |
parent | 03c79cc56e4497cbd09d74a73c1bd0d1d9a8a16c (diff) | |
parent | f56df2f4db6e4af87fb8e941cff69f4501a111df (diff) |
Merge branch 'linus'
Diffstat (limited to 'drivers/hwmon/w83793.c')
-rw-r--r-- | drivers/hwmon/w83793.c | 127 |
1 files changed, 110 insertions, 17 deletions
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index c12ac5abc2bb..253ffaf1568a 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c | |||
@@ -117,6 +117,7 @@ static const u16 W83793_REG_IN[][3] = { | |||
117 | /* Low Bits of Vcore A/B Vtt Read/High/Low */ | 117 | /* Low Bits of Vcore A/B Vtt Read/High/Low */ |
118 | static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 }; | 118 | static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 }; |
119 | static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 }; | 119 | static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 }; |
120 | static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 }; | ||
120 | 121 | ||
121 | #define W83793_REG_FAN(index) (0x23 + 2 * (index)) /* High byte */ | 122 | #define W83793_REG_FAN(index) (0x23 + 2 * (index)) /* High byte */ |
122 | #define W83793_REG_FAN_MIN(index) (0x90 + 2 * (index)) /* High byte */ | 123 | #define W83793_REG_FAN_MIN(index) (0x90 + 2 * (index)) /* High byte */ |
@@ -203,6 +204,8 @@ struct w83793_data { | |||
203 | u8 temp_fan_map[6]; /* Temp controls which pwm fan, bit field */ | 204 | u8 temp_fan_map[6]; /* Temp controls which pwm fan, bit field */ |
204 | 205 | ||
205 | u8 has_pwm; | 206 | u8 has_pwm; |
207 | u8 has_temp; | ||
208 | u8 has_vid; | ||
206 | u8 pwm_enable; /* Register value, each Temp has 1 bit */ | 209 | u8 pwm_enable; /* Register value, each Temp has 1 bit */ |
207 | u8 pwm_uptime; /* Register value */ | 210 | u8 pwm_uptime; /* Register value */ |
208 | u8 pwm_downtime; /* Register value */ | 211 | u8 pwm_downtime; /* Register value */ |
@@ -500,7 +503,7 @@ store_temp(struct device *dev, struct device_attribute *attr, | |||
500 | each has 4 mode:(2 bits) | 503 | each has 4 mode:(2 bits) |
501 | 0: Stop monitor | 504 | 0: Stop monitor |
502 | 1: Use internal temp sensor(default) | 505 | 1: Use internal temp sensor(default) |
503 | 2: Use sensor in AMD CPU and get result by AMDSI | 506 | 2: Reserved |
504 | 3: Use sensor in Intel CPU and get result by PECI | 507 | 3: Use sensor in Intel CPU and get result by PECI |
505 | 508 | ||
506 | TR1-TR2 | 509 | TR1-TR2 |
@@ -509,8 +512,8 @@ store_temp(struct device *dev, struct device_attribute *attr, | |||
509 | 1: To enable temp sensors monitor | 512 | 1: To enable temp sensors monitor |
510 | */ | 513 | */ |
511 | 514 | ||
512 | /* 0 disable, 5 AMDSI, 6 PECI */ | 515 | /* 0 disable, 6 PECI */ |
513 | static u8 TO_TEMP_MODE[] = { 0, 0, 5, 6 }; | 516 | static u8 TO_TEMP_MODE[] = { 0, 0, 0, 6 }; |
514 | 517 | ||
515 | static ssize_t | 518 | static ssize_t |
516 | show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf) | 519 | show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -550,11 +553,10 @@ store_temp_mode(struct device *dev, struct device_attribute *attr, | |||
550 | u8 val = simple_strtoul(buf, NULL, 10); | 553 | u8 val = simple_strtoul(buf, NULL, 10); |
551 | 554 | ||
552 | /* transform the sysfs interface values into table above */ | 555 | /* transform the sysfs interface values into table above */ |
553 | if ((val == 5 || val == 6) && (index < 4)) { | 556 | if ((val == 6) && (index < 4)) { |
554 | val -= 3; | 557 | val -= 3; |
555 | } else if ((val == 3 && index < 4) | 558 | } else if ((val == 3 && index < 4) |
556 | || (val == 4 && index >= 4) | 559 | || (val == 4 && index >= 4)) { |
557 | || val == 0) { | ||
558 | /* transform diode or thermistor into internal enable */ | 560 | /* transform diode or thermistor into internal enable */ |
559 | val = !!val; | 561 | val = !!val; |
560 | } else { | 562 | } else { |
@@ -839,7 +841,9 @@ show_in(struct device *dev, struct device_attribute *attr, char *buf) | |||
839 | val <<= 2; | 841 | val <<= 2; |
840 | val += (data->in_low_bits[nr] >> (index * 2)) & 0x3; | 842 | val += (data->in_low_bits[nr] >> (index * 2)) & 0x3; |
841 | } | 843 | } |
842 | return sprintf(buf, "%d\n", val * scale_in[index]); | 844 | /* voltage inputs 5VDD and 5VSB needs 150mV offset */ |
845 | val = val * scale_in[index] + scale_in_add[index]; | ||
846 | return sprintf(buf, "%d\n", val); | ||
843 | } | 847 | } |
844 | 848 | ||
845 | static ssize_t | 849 | static ssize_t |
@@ -859,6 +863,10 @@ store_in(struct device *dev, struct device_attribute *attr, | |||
859 | scale_in[index] / 2) / scale_in[index]; | 863 | scale_in[index] / 2) / scale_in[index]; |
860 | mutex_lock(&data->update_lock); | 864 | mutex_lock(&data->update_lock); |
861 | if (index > 2) { | 865 | if (index > 2) { |
866 | /* fix the limit values of 5VDD and 5VSB to ALARM mechanism */ | ||
867 | if (1 == nr || 2 == nr) { | ||
868 | val -= scale_in_add[index] / scale_in[index]; | ||
869 | } | ||
862 | val = SENSORS_LIMIT(val, 0, 255); | 870 | val = SENSORS_LIMIT(val, 0, 255); |
863 | } else { | 871 | } else { |
864 | val = SENSORS_LIMIT(val, 0, 0x3FF); | 872 | val = SENSORS_LIMIT(val, 0, 0x3FF); |
@@ -979,12 +987,6 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = { | |||
979 | SENSOR_ATTR_IN(7), | 987 | SENSOR_ATTR_IN(7), |
980 | SENSOR_ATTR_IN(8), | 988 | SENSOR_ATTR_IN(8), |
981 | SENSOR_ATTR_IN(9), | 989 | SENSOR_ATTR_IN(9), |
982 | SENSOR_ATTR_TEMP(1), | ||
983 | SENSOR_ATTR_TEMP(2), | ||
984 | SENSOR_ATTR_TEMP(3), | ||
985 | SENSOR_ATTR_TEMP(4), | ||
986 | SENSOR_ATTR_TEMP(5), | ||
987 | SENSOR_ATTR_TEMP(6), | ||
988 | SENSOR_ATTR_FAN(1), | 990 | SENSOR_ATTR_FAN(1), |
989 | SENSOR_ATTR_FAN(2), | 991 | SENSOR_ATTR_FAN(2), |
990 | SENSOR_ATTR_FAN(3), | 992 | SENSOR_ATTR_FAN(3), |
@@ -995,6 +997,15 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = { | |||
995 | SENSOR_ATTR_PWM(3), | 997 | SENSOR_ATTR_PWM(3), |
996 | }; | 998 | }; |
997 | 999 | ||
1000 | static struct sensor_device_attribute_2 w83793_temp[] = { | ||
1001 | SENSOR_ATTR_TEMP(1), | ||
1002 | SENSOR_ATTR_TEMP(2), | ||
1003 | SENSOR_ATTR_TEMP(3), | ||
1004 | SENSOR_ATTR_TEMP(4), | ||
1005 | SENSOR_ATTR_TEMP(5), | ||
1006 | SENSOR_ATTR_TEMP(6), | ||
1007 | }; | ||
1008 | |||
998 | /* Fan6-Fan12 */ | 1009 | /* Fan6-Fan12 */ |
999 | static struct sensor_device_attribute_2 w83793_left_fan[] = { | 1010 | static struct sensor_device_attribute_2 w83793_left_fan[] = { |
1000 | SENSOR_ATTR_FAN(6), | 1011 | SENSOR_ATTR_FAN(6), |
@@ -1015,9 +1026,12 @@ static struct sensor_device_attribute_2 w83793_left_pwm[] = { | |||
1015 | SENSOR_ATTR_PWM(8), | 1026 | SENSOR_ATTR_PWM(8), |
1016 | }; | 1027 | }; |
1017 | 1028 | ||
1018 | static struct sensor_device_attribute_2 sda_single_files[] = { | 1029 | static struct sensor_device_attribute_2 w83793_vid[] = { |
1019 | SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0), | 1030 | SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0), |
1020 | SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1), | 1031 | SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1), |
1032 | }; | ||
1033 | |||
1034 | static struct sensor_device_attribute_2 sda_single_files[] = { | ||
1021 | SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm, | 1035 | SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm, |
1022 | NOT_USED, NOT_USED), | 1036 | NOT_USED, NOT_USED), |
1023 | SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, | 1037 | SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, |
@@ -1070,11 +1084,17 @@ static int w83793_detach_client(struct i2c_client *client) | |||
1070 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) | 1084 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) |
1071 | device_remove_file(dev, &sda_single_files[i].dev_attr); | 1085 | device_remove_file(dev, &sda_single_files[i].dev_attr); |
1072 | 1086 | ||
1087 | for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) | ||
1088 | device_remove_file(dev, &w83793_vid[i].dev_attr); | ||
1089 | |||
1073 | for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) | 1090 | for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) |
1074 | device_remove_file(dev, &w83793_left_fan[i].dev_attr); | 1091 | device_remove_file(dev, &w83793_left_fan[i].dev_attr); |
1075 | 1092 | ||
1076 | for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) | 1093 | for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) |
1077 | device_remove_file(dev, &w83793_left_pwm[i].dev_attr); | 1094 | device_remove_file(dev, &w83793_left_pwm[i].dev_attr); |
1095 | |||
1096 | for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) | ||
1097 | device_remove_file(dev, &w83793_temp[i].dev_attr); | ||
1078 | } | 1098 | } |
1079 | 1099 | ||
1080 | if ((err = i2c_detach_client(client))) | 1100 | if ((err = i2c_detach_client(client))) |
@@ -1187,6 +1207,7 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1187 | struct w83793_data *data; | 1207 | struct w83793_data *data; |
1188 | int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; | 1208 | int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; |
1189 | int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; | 1209 | int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; |
1210 | int files_temp = ARRAY_SIZE(w83793_temp) / 6; | ||
1190 | int err = 0; | 1211 | int err = 0; |
1191 | 1212 | ||
1192 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1213 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
@@ -1313,6 +1334,44 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1313 | data->has_pwm |= 0x80; | 1334 | data->has_pwm |= 0x80; |
1314 | } | 1335 | } |
1315 | 1336 | ||
1337 | tmp = w83793_read_value(client, W83793_REG_FANIN_SEL); | ||
1338 | if ((tmp & 0x01) && (val & 0x08)) { /* fan 9, second location */ | ||
1339 | data->has_fan |= 0x100; | ||
1340 | } | ||
1341 | if ((tmp & 0x02) && (val & 0x10)) { /* fan 10, second location */ | ||
1342 | data->has_fan |= 0x200; | ||
1343 | } | ||
1344 | if ((tmp & 0x04) && (val & 0x20)) { /* fan 11, second location */ | ||
1345 | data->has_fan |= 0x400; | ||
1346 | } | ||
1347 | if ((tmp & 0x08) && (val & 0x40)) { /* fan 12, second location */ | ||
1348 | data->has_fan |= 0x800; | ||
1349 | } | ||
1350 | |||
1351 | /* check the temp1-6 mode, ignore former AMDSI selected inputs */ | ||
1352 | tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]); | ||
1353 | if (tmp & 0x01) | ||
1354 | data->has_temp |= 0x01; | ||
1355 | if (tmp & 0x04) | ||
1356 | data->has_temp |= 0x02; | ||
1357 | if (tmp & 0x10) | ||
1358 | data->has_temp |= 0x04; | ||
1359 | if (tmp & 0x40) | ||
1360 | data->has_temp |= 0x08; | ||
1361 | |||
1362 | tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]); | ||
1363 | if (tmp & 0x01) | ||
1364 | data->has_temp |= 0x10; | ||
1365 | if (tmp & 0x02) | ||
1366 | data->has_temp |= 0x20; | ||
1367 | |||
1368 | /* Detect the VID usage and ignore unused input */ | ||
1369 | tmp = w83793_read_value(client, W83793_REG_MFC); | ||
1370 | if (!(tmp & 0x29)) | ||
1371 | data->has_vid |= 0x1; /* has VIDA */ | ||
1372 | if (tmp & 0x80) | ||
1373 | data->has_vid |= 0x2; /* has VIDB */ | ||
1374 | |||
1316 | /* Register sysfs hooks */ | 1375 | /* Register sysfs hooks */ |
1317 | for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) { | 1376 | for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) { |
1318 | err = device_create_file(dev, | 1377 | err = device_create_file(dev, |
@@ -1321,6 +1380,14 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1321 | goto exit_remove; | 1380 | goto exit_remove; |
1322 | } | 1381 | } |
1323 | 1382 | ||
1383 | for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) { | ||
1384 | if (!(data->has_vid & (1 << i))) | ||
1385 | continue; | ||
1386 | err = device_create_file(dev, &w83793_vid[i].dev_attr); | ||
1387 | if (err) | ||
1388 | goto exit_remove; | ||
1389 | } | ||
1390 | |||
1324 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { | 1391 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { |
1325 | err = device_create_file(dev, &sda_single_files[i].dev_attr); | 1392 | err = device_create_file(dev, &sda_single_files[i].dev_attr); |
1326 | if (err) | 1393 | if (err) |
@@ -1328,6 +1395,19 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1328 | 1395 | ||
1329 | } | 1396 | } |
1330 | 1397 | ||
1398 | for (i = 0; i < 6; i++) { | ||
1399 | int j; | ||
1400 | if (!(data->has_temp & (1 << i))) | ||
1401 | continue; | ||
1402 | for (j = 0; j < files_temp; j++) { | ||
1403 | err = device_create_file(dev, | ||
1404 | &w83793_temp[(i) * files_temp | ||
1405 | + j].dev_attr); | ||
1406 | if (err) | ||
1407 | goto exit_remove; | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1331 | for (i = 5; i < 12; i++) { | 1411 | for (i = 5; i < 12; i++) { |
1332 | int j; | 1412 | int j; |
1333 | if (!(data->has_fan & (1 << i))) | 1413 | if (!(data->has_fan & (1 << i))) |
@@ -1371,12 +1451,18 @@ exit_remove: | |||
1371 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) | 1451 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) |
1372 | device_remove_file(dev, &sda_single_files[i].dev_attr); | 1452 | device_remove_file(dev, &sda_single_files[i].dev_attr); |
1373 | 1453 | ||
1454 | for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) | ||
1455 | device_remove_file(dev, &w83793_vid[i].dev_attr); | ||
1456 | |||
1374 | for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) | 1457 | for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) |
1375 | device_remove_file(dev, &w83793_left_fan[i].dev_attr); | 1458 | device_remove_file(dev, &w83793_left_fan[i].dev_attr); |
1376 | 1459 | ||
1377 | for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) | 1460 | for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) |
1378 | device_remove_file(dev, &w83793_left_pwm[i].dev_attr); | 1461 | device_remove_file(dev, &w83793_left_pwm[i].dev_attr); |
1379 | 1462 | ||
1463 | for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) | ||
1464 | device_remove_file(dev, &w83793_temp[i].dev_attr); | ||
1465 | |||
1380 | if (data->lm75[0] != NULL) { | 1466 | if (data->lm75[0] != NULL) { |
1381 | i2c_detach_client(data->lm75[0]); | 1467 | i2c_detach_client(data->lm75[0]); |
1382 | kfree(data->lm75[0]); | 1468 | kfree(data->lm75[0]); |
@@ -1428,6 +1514,8 @@ static void w83793_update_nonvolatile(struct device *dev) | |||
1428 | } | 1514 | } |
1429 | 1515 | ||
1430 | for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) { | 1516 | for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) { |
1517 | if (!(data->has_temp & (1 << i))) | ||
1518 | continue; | ||
1431 | data->temp_fan_map[i] = | 1519 | data->temp_fan_map[i] = |
1432 | w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i)); | 1520 | w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i)); |
1433 | for (j = 1; j < 5; j++) { | 1521 | for (j = 1; j < 5; j++) { |
@@ -1510,9 +1598,12 @@ static struct w83793_data *w83793_update_device(struct device *dev) | |||
1510 | w83793_read_value(client, W83793_REG_FAN(i) + 1); | 1598 | w83793_read_value(client, W83793_REG_FAN(i) + 1); |
1511 | } | 1599 | } |
1512 | 1600 | ||
1513 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) | 1601 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) { |
1602 | if (!(data->has_temp & (1 << i))) | ||
1603 | continue; | ||
1514 | data->temp[i][TEMP_READ] = | 1604 | data->temp[i][TEMP_READ] = |
1515 | w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]); | 1605 | w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]); |
1606 | } | ||
1516 | 1607 | ||
1517 | data->temp_low_bits = | 1608 | data->temp_low_bits = |
1518 | w83793_read_value(client, W83793_REG_TEMP_LOW_BITS); | 1609 | w83793_read_value(client, W83793_REG_TEMP_LOW_BITS); |
@@ -1527,8 +1618,10 @@ static struct w83793_data *w83793_update_device(struct device *dev) | |||
1527 | for (i = 0; i < ARRAY_SIZE(data->alarms); i++) | 1618 | for (i = 0; i < ARRAY_SIZE(data->alarms); i++) |
1528 | data->alarms[i] = | 1619 | data->alarms[i] = |
1529 | w83793_read_value(client, W83793_REG_ALARM(i)); | 1620 | w83793_read_value(client, W83793_REG_ALARM(i)); |
1530 | data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA); | 1621 | if (data->has_vid & 0x01) |
1531 | data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB); | 1622 | data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA); |
1623 | if (data->has_vid & 0x02) | ||
1624 | data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB); | ||
1532 | w83793_update_nonvolatile(dev); | 1625 | w83793_update_nonvolatile(dev); |
1533 | data->last_updated = jiffies; | 1626 | data->last_updated = jiffies; |
1534 | data->valid = 1; | 1627 | data->valid = 1; |