diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/it87.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 7a349e066fdc..d70c6ec31725 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -128,6 +128,7 @@ superio_exit(void) | |||
128 | #define IT87_SIO_GPIO5_REG 0x29 | 128 | #define IT87_SIO_GPIO5_REG 0x29 |
129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | 129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ |
130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ | 130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ |
131 | #define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */ | ||
131 | 132 | ||
132 | /* Update battery voltage after every reading if true */ | 133 | /* Update battery voltage after every reading if true */ |
133 | static int update_vbat; | 134 | static int update_vbat; |
@@ -187,6 +188,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | |||
187 | 188 | ||
188 | #define IT87_REG_VIN_ENABLE 0x50 | 189 | #define IT87_REG_VIN_ENABLE 0x50 |
189 | #define IT87_REG_TEMP_ENABLE 0x51 | 190 | #define IT87_REG_TEMP_ENABLE 0x51 |
191 | #define IT87_REG_BEEP_ENABLE 0x5c | ||
190 | 192 | ||
191 | #define IT87_REG_CHIPID 0x58 | 193 | #define IT87_REG_CHIPID 0x58 |
192 | 194 | ||
@@ -246,6 +248,7 @@ struct it87_sio_data { | |||
246 | /* Values read from Super-I/O config space */ | 248 | /* Values read from Super-I/O config space */ |
247 | u8 revision; | 249 | u8 revision; |
248 | u8 vid_value; | 250 | u8 vid_value; |
251 | u8 beep_pin; | ||
249 | /* Features skipped based on config or DMI */ | 252 | /* Features skipped based on config or DMI */ |
250 | u8 skip_vid; | 253 | u8 skip_vid; |
251 | u8 skip_fan; | 254 | u8 skip_fan; |
@@ -279,6 +282,7 @@ struct it87_data { | |||
279 | u8 vid; /* Register encoding, combined */ | 282 | u8 vid; /* Register encoding, combined */ |
280 | u8 vrm; | 283 | u8 vrm; |
281 | u32 alarms; /* Register encoding, combined */ | 284 | u32 alarms; /* Register encoding, combined */ |
285 | u8 beeps; /* Register encoding */ | ||
282 | u8 fan_main_ctrl; /* Register value */ | 286 | u8 fan_main_ctrl; /* Register value */ |
283 | u8 fan_ctl; /* Register value */ | 287 | u8 fan_ctl; /* Register value */ |
284 | 288 | ||
@@ -919,6 +923,55 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); | |||
919 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); | 923 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); |
920 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); | 924 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); |
921 | 925 | ||
926 | static ssize_t show_beep(struct device *dev, struct device_attribute *attr, | ||
927 | char *buf) | ||
928 | { | ||
929 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
930 | struct it87_data *data = it87_update_device(dev); | ||
931 | return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); | ||
932 | } | ||
933 | static ssize_t set_beep(struct device *dev, struct device_attribute *attr, | ||
934 | const char *buf, size_t count) | ||
935 | { | ||
936 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
937 | struct it87_data *data = dev_get_drvdata(dev); | ||
938 | long val; | ||
939 | |||
940 | if (strict_strtol(buf, 10, &val) < 0 | ||
941 | || (val != 0 && val != 1)) | ||
942 | return -EINVAL; | ||
943 | |||
944 | mutex_lock(&data->update_lock); | ||
945 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
946 | if (val) | ||
947 | data->beeps |= (1 << bitnr); | ||
948 | else | ||
949 | data->beeps &= ~(1 << bitnr); | ||
950 | it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); | ||
951 | mutex_unlock(&data->update_lock); | ||
952 | return count; | ||
953 | } | ||
954 | |||
955 | static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, | ||
956 | show_beep, set_beep, 1); | ||
957 | static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1); | ||
958 | static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1); | ||
959 | static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1); | ||
960 | static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1); | ||
961 | static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1); | ||
962 | static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1); | ||
963 | static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1); | ||
964 | /* fanX_beep writability is set later */ | ||
965 | static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0); | ||
966 | static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0); | ||
967 | static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0); | ||
968 | static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0); | ||
969 | static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0); | ||
970 | static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, | ||
971 | show_beep, set_beep, 2); | ||
972 | static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); | ||
973 | static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); | ||
974 | |||
922 | static ssize_t | 975 | static ssize_t |
923 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 976 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) |
924 | { | 977 | { |
@@ -1014,6 +1067,26 @@ static const struct attribute_group it87_group = { | |||
1014 | .attrs = it87_attributes, | 1067 | .attrs = it87_attributes, |
1015 | }; | 1068 | }; |
1016 | 1069 | ||
1070 | static struct attribute *it87_attributes_beep[] = { | ||
1071 | &sensor_dev_attr_in0_beep.dev_attr.attr, | ||
1072 | &sensor_dev_attr_in1_beep.dev_attr.attr, | ||
1073 | &sensor_dev_attr_in2_beep.dev_attr.attr, | ||
1074 | &sensor_dev_attr_in3_beep.dev_attr.attr, | ||
1075 | &sensor_dev_attr_in4_beep.dev_attr.attr, | ||
1076 | &sensor_dev_attr_in5_beep.dev_attr.attr, | ||
1077 | &sensor_dev_attr_in6_beep.dev_attr.attr, | ||
1078 | &sensor_dev_attr_in7_beep.dev_attr.attr, | ||
1079 | |||
1080 | &sensor_dev_attr_temp1_beep.dev_attr.attr, | ||
1081 | &sensor_dev_attr_temp2_beep.dev_attr.attr, | ||
1082 | &sensor_dev_attr_temp3_beep.dev_attr.attr, | ||
1083 | NULL | ||
1084 | }; | ||
1085 | |||
1086 | static const struct attribute_group it87_group_beep = { | ||
1087 | .attrs = it87_attributes_beep, | ||
1088 | }; | ||
1089 | |||
1017 | static struct attribute *it87_attributes_fan16[5][3+1] = { { | 1090 | static struct attribute *it87_attributes_fan16[5][3+1] = { { |
1018 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | 1091 | &sensor_dev_attr_fan1_input16.dev_attr.attr, |
1019 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | 1092 | &sensor_dev_attr_fan1_min16.dev_attr.attr, |
@@ -1107,6 +1180,14 @@ static const struct attribute_group it87_group_pwm[3] = { | |||
1107 | { .attrs = it87_attributes_pwm[2] }, | 1180 | { .attrs = it87_attributes_pwm[2] }, |
1108 | }; | 1181 | }; |
1109 | 1182 | ||
1183 | static struct attribute *it87_attributes_fan_beep[] = { | ||
1184 | &sensor_dev_attr_fan1_beep.dev_attr.attr, | ||
1185 | &sensor_dev_attr_fan2_beep.dev_attr.attr, | ||
1186 | &sensor_dev_attr_fan3_beep.dev_attr.attr, | ||
1187 | &sensor_dev_attr_fan4_beep.dev_attr.attr, | ||
1188 | &sensor_dev_attr_fan5_beep.dev_attr.attr, | ||
1189 | }; | ||
1190 | |||
1110 | static struct attribute *it87_attributes_vid[] = { | 1191 | static struct attribute *it87_attributes_vid[] = { |
1111 | &dev_attr_vrm.attr, | 1192 | &dev_attr_vrm.attr, |
1112 | &dev_attr_cpu0_vid.attr, | 1193 | &dev_attr_cpu0_vid.attr, |
@@ -1174,6 +1255,10 @@ static int __init it87_find(unsigned short *address, | |||
1174 | if (sio_data->type == it87) { | 1255 | if (sio_data->type == it87) { |
1175 | /* The IT8705F doesn't have VID pins at all */ | 1256 | /* The IT8705F doesn't have VID pins at all */ |
1176 | sio_data->skip_vid = 1; | 1257 | sio_data->skip_vid = 1; |
1258 | |||
1259 | /* The IT8705F has a different LD number for GPIO */ | ||
1260 | superio_select(5); | ||
1261 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1177 | } else { | 1262 | } else { |
1178 | int reg; | 1263 | int reg; |
1179 | 1264 | ||
@@ -1207,7 +1292,11 @@ static int __init it87_find(unsigned short *address, | |||
1207 | pr_info("it87: in3 is VCC (+5V)\n"); | 1292 | pr_info("it87: in3 is VCC (+5V)\n"); |
1208 | if (reg & (1 << 1)) | 1293 | if (reg & (1 << 1)) |
1209 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1294 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); |
1295 | |||
1296 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1210 | } | 1297 | } |
1298 | if (sio_data->beep_pin) | ||
1299 | pr_info("it87: Beeping is supported\n"); | ||
1211 | 1300 | ||
1212 | /* Disable specific features based on DMI strings */ | 1301 | /* Disable specific features based on DMI strings */ |
1213 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1302 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
@@ -1240,10 +1329,15 @@ static void it87_remove_files(struct device *dev) | |||
1240 | int i; | 1329 | int i; |
1241 | 1330 | ||
1242 | sysfs_remove_group(&dev->kobj, &it87_group); | 1331 | sysfs_remove_group(&dev->kobj, &it87_group); |
1332 | if (sio_data->beep_pin) | ||
1333 | sysfs_remove_group(&dev->kobj, &it87_group_beep); | ||
1243 | for (i = 0; i < 5; i++) { | 1334 | for (i = 0; i < 5; i++) { |
1244 | if (!(data->has_fan & (1 << i))) | 1335 | if (!(data->has_fan & (1 << i))) |
1245 | continue; | 1336 | continue; |
1246 | sysfs_remove_group(&dev->kobj, &fan_group[i]); | 1337 | sysfs_remove_group(&dev->kobj, &fan_group[i]); |
1338 | if (sio_data->beep_pin) | ||
1339 | sysfs_remove_file(&dev->kobj, | ||
1340 | it87_attributes_fan_beep[i]); | ||
1247 | } | 1341 | } |
1248 | for (i = 0; i < 3; i++) { | 1342 | for (i = 0; i < 3; i++) { |
1249 | if (sio_data->skip_pwm & (1 << 0)) | 1343 | if (sio_data->skip_pwm & (1 << 0)) |
@@ -1263,6 +1357,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1263 | const struct attribute_group *fan_group; | 1357 | const struct attribute_group *fan_group; |
1264 | int err = 0, i; | 1358 | int err = 0, i; |
1265 | int enable_pwm_interface; | 1359 | int enable_pwm_interface; |
1360 | int fan_beep_need_rw; | ||
1266 | static const char *names[] = { | 1361 | static const char *names[] = { |
1267 | "it87", | 1362 | "it87", |
1268 | "it8712", | 1363 | "it8712", |
@@ -1311,14 +1406,40 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1311 | if ((err = sysfs_create_group(&dev->kobj, &it87_group))) | 1406 | if ((err = sysfs_create_group(&dev->kobj, &it87_group))) |
1312 | goto ERROR2; | 1407 | goto ERROR2; |
1313 | 1408 | ||
1409 | if (sio_data->beep_pin) { | ||
1410 | err = sysfs_create_group(&dev->kobj, &it87_group_beep); | ||
1411 | if (err) | ||
1412 | goto ERROR4; | ||
1413 | } | ||
1414 | |||
1314 | /* Do not create fan files for disabled fans */ | 1415 | /* Do not create fan files for disabled fans */ |
1315 | fan_group = it87_get_fan_group(data); | 1416 | fan_group = it87_get_fan_group(data); |
1417 | fan_beep_need_rw = 1; | ||
1316 | for (i = 0; i < 5; i++) { | 1418 | for (i = 0; i < 5; i++) { |
1317 | if (!(data->has_fan & (1 << i))) | 1419 | if (!(data->has_fan & (1 << i))) |
1318 | continue; | 1420 | continue; |
1319 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); | 1421 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); |
1320 | if (err) | 1422 | if (err) |
1321 | goto ERROR4; | 1423 | goto ERROR4; |
1424 | |||
1425 | if (sio_data->beep_pin) { | ||
1426 | err = sysfs_create_file(&dev->kobj, | ||
1427 | it87_attributes_fan_beep[i]); | ||
1428 | if (err) | ||
1429 | goto ERROR4; | ||
1430 | if (!fan_beep_need_rw) | ||
1431 | continue; | ||
1432 | |||
1433 | /* As we have a single beep enable bit for all fans, | ||
1434 | * only the first enabled fan has a writable attribute | ||
1435 | * for it. */ | ||
1436 | if (sysfs_chmod_file(&dev->kobj, | ||
1437 | it87_attributes_fan_beep[i], | ||
1438 | S_IRUGO | S_IWUSR)) | ||
1439 | dev_dbg(dev, "chmod +w fan%d_beep failed\n", | ||
1440 | i + 1); | ||
1441 | fan_beep_need_rw = 0; | ||
1442 | } | ||
1322 | } | 1443 | } |
1323 | 1444 | ||
1324 | if (enable_pwm_interface) { | 1445 | if (enable_pwm_interface) { |
@@ -1608,6 +1729,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1608 | it87_read_value(data, IT87_REG_ALARM1) | | 1729 | it87_read_value(data, IT87_REG_ALARM1) | |
1609 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | | 1730 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | |
1610 | (it87_read_value(data, IT87_REG_ALARM3) << 16); | 1731 | (it87_read_value(data, IT87_REG_ALARM3) << 16); |
1732 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
1611 | 1733 | ||
1612 | data->fan_main_ctrl = it87_read_value(data, | 1734 | data->fan_main_ctrl = it87_read_value(data, |
1613 | IT87_REG_FAN_MAIN_CTRL); | 1735 | IT87_REG_FAN_MAIN_CTRL); |