aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pc87360.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pc87360.c')
-rw-r--r--drivers/hwmon/pc87360.c230
1 files changed, 163 insertions, 67 deletions
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 236f9f29c624..3b8b81984ad4 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -328,6 +328,12 @@ static struct sensor_device_attribute fan_min[] = {
328 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), 328 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
329}; 329};
330 330
331#define FAN_UNIT_ATTRS(X) \
332 &fan_input[X].dev_attr.attr, \
333 &fan_status[X].dev_attr.attr, \
334 &fan_div[X].dev_attr.attr, \
335 &fan_min[X].dev_attr.attr
336
331static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) 337static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
332{ 338{
333 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 339 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -360,6 +366,19 @@ static struct sensor_device_attribute pwm[] = {
360 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), 366 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
361}; 367};
362 368
369static struct attribute * pc8736x_fan_attr_array[] = {
370 FAN_UNIT_ATTRS(0),
371 FAN_UNIT_ATTRS(1),
372 FAN_UNIT_ATTRS(2),
373 &pwm[0].dev_attr.attr,
374 &pwm[1].dev_attr.attr,
375 &pwm[2].dev_attr.attr,
376 NULL
377};
378static const struct attribute_group pc8736x_fan_group = {
379 .attrs = pc8736x_fan_attr_array,
380};
381
363static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) 382static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
364{ 383{
365 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 384 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -472,6 +491,61 @@ static struct sensor_device_attribute in_max[] = {
472 SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), 491 SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
473}; 492};
474 493
494#define VIN_UNIT_ATTRS(X) \
495 &in_input[X].dev_attr.attr, \
496 &in_status[X].dev_attr.attr, \
497 &in_min[X].dev_attr.attr, \
498 &in_max[X].dev_attr.attr
499
500static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
501{
502 struct pc87360_data *data = pc87360_update_device(dev);
503 return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
504}
505static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
506
507static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
508{
509 struct pc87360_data *data = pc87360_update_device(dev);
510 return sprintf(buf, "%u\n", data->vrm);
511}
512static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
513{
514 struct i2c_client *client = to_i2c_client(dev);
515 struct pc87360_data *data = i2c_get_clientdata(client);
516 data->vrm = simple_strtoul(buf, NULL, 10);
517 return count;
518}
519static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
520
521static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
522{
523 struct pc87360_data *data = pc87360_update_device(dev);
524 return sprintf(buf, "%u\n", data->in_alarms);
525}
526static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
527
528static struct attribute *pc8736x_vin_attr_array[] = {
529 VIN_UNIT_ATTRS(0),
530 VIN_UNIT_ATTRS(1),
531 VIN_UNIT_ATTRS(2),
532 VIN_UNIT_ATTRS(3),
533 VIN_UNIT_ATTRS(4),
534 VIN_UNIT_ATTRS(5),
535 VIN_UNIT_ATTRS(6),
536 VIN_UNIT_ATTRS(7),
537 VIN_UNIT_ATTRS(8),
538 VIN_UNIT_ATTRS(9),
539 VIN_UNIT_ATTRS(10),
540 &dev_attr_cpu0_vid.attr,
541 &dev_attr_vrm.attr,
542 &dev_attr_alarms_in.attr,
543 NULL
544};
545static const struct attribute_group pc8736x_vin_group = {
546 .attrs = pc8736x_vin_attr_array,
547};
548
475static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) 549static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
476{ 550{
477 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 551 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -590,33 +664,22 @@ static struct sensor_device_attribute therm_crit[] = {
590 show_therm_crit, set_therm_crit, 2+11), 664 show_therm_crit, set_therm_crit, 2+11),
591}; 665};
592 666
593static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) 667#define THERM_UNIT_ATTRS(X) \
594{ 668 &therm_input[X].dev_attr.attr, \
595 struct pc87360_data *data = pc87360_update_device(dev); 669 &therm_status[X].dev_attr.attr, \
596 return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); 670 &therm_min[X].dev_attr.attr, \
597} 671 &therm_max[X].dev_attr.attr, \
598static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); 672 &therm_crit[X].dev_attr.attr
599 673
600static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) 674static struct attribute * pc8736x_therm_attr_array[] = {
601{ 675 THERM_UNIT_ATTRS(0),
602 struct pc87360_data *data = pc87360_update_device(dev); 676 THERM_UNIT_ATTRS(1),
603 return sprintf(buf, "%u\n", data->vrm); 677 THERM_UNIT_ATTRS(2),
604} 678 NULL
605static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 679};
606{ 680static const struct attribute_group pc8736x_therm_group = {
607 struct i2c_client *client = to_i2c_client(dev); 681 .attrs = pc8736x_therm_attr_array,
608 struct pc87360_data *data = i2c_get_clientdata(client); 682};
609 data->vrm = simple_strtoul(buf, NULL, 10);
610 return count;
611}
612static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
613
614static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
615{
616 struct pc87360_data *data = pc87360_update_device(dev);
617 return sprintf(buf, "%u\n", data->in_alarms);
618}
619static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
620 683
621static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf) 684static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
622{ 685{
@@ -736,6 +799,25 @@ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *att
736} 799}
737static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); 800static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
738 801
802#define TEMP_UNIT_ATTRS(X) \
803 &temp_input[X].dev_attr.attr, \
804 &temp_status[X].dev_attr.attr, \
805 &temp_min[X].dev_attr.attr, \
806 &temp_max[X].dev_attr.attr, \
807 &temp_crit[X].dev_attr.attr
808
809static struct attribute * pc8736x_temp_attr_array[] = {
810 TEMP_UNIT_ATTRS(0),
811 TEMP_UNIT_ATTRS(1),
812 TEMP_UNIT_ATTRS(2),
813 /* include the few miscellaneous atts here */
814 &dev_attr_alarms_temp.attr,
815 NULL
816};
817static const struct attribute_group pc8736x_temp_group = {
818 .attrs = pc8736x_temp_attr_array,
819};
820
739/* 821/*
740 * Device detection, registration and update 822 * Device detection, registration and update
741 */ 823 */
@@ -936,60 +1018,69 @@ static int pc87360_detect(struct i2c_adapter *adapter)
936 pc87360_init_client(client, use_thermistors); 1018 pc87360_init_client(client, use_thermistors);
937 } 1019 }
938 1020
939 /* Register sysfs hooks */ 1021 /* Register all-or-nothing sysfs groups */
940 data->class_dev = hwmon_device_register(&client->dev); 1022
941 if (IS_ERR(data->class_dev)) { 1023 if (data->innr &&
942 err = PTR_ERR(data->class_dev); 1024 (err = sysfs_create_group(&client->dev.kobj,
1025 &pc8736x_vin_group)))
943 goto ERROR3; 1026 goto ERROR3;
944 }
945 1027
946 if (data->innr) { 1028 if (data->innr == 14 &&
947 for (i = 0; i < 11; i++) { 1029 (err = sysfs_create_group(&client->dev.kobj,
948 device_create_file(dev, &in_input[i].dev_attr); 1030 &pc8736x_therm_group)))
949 device_create_file(dev, &in_min[i].dev_attr); 1031 goto ERROR3;
950 device_create_file(dev, &in_max[i].dev_attr); 1032
951 device_create_file(dev, &in_status[i].dev_attr); 1033 /* create device attr-files for varying sysfs groups */
952 }
953 device_create_file(dev, &dev_attr_cpu0_vid);
954 device_create_file(dev, &dev_attr_vrm);
955 device_create_file(dev, &dev_attr_alarms_in);
956 }
957 1034
958 if (data->tempnr) { 1035 if (data->tempnr) {
959 for (i = 0; i < data->tempnr; i++) { 1036 for (i = 0; i < data->tempnr; i++) {
960 device_create_file(dev, &temp_input[i].dev_attr); 1037 if ((err = device_create_file(dev,
961 device_create_file(dev, &temp_min[i].dev_attr); 1038 &temp_input[i].dev_attr))
962 device_create_file(dev, &temp_max[i].dev_attr); 1039 || (err = device_create_file(dev,
963 device_create_file(dev, &temp_crit[i].dev_attr); 1040 &temp_min[i].dev_attr))
964 device_create_file(dev, &temp_status[i].dev_attr); 1041 || (err = device_create_file(dev,
965 } 1042 &temp_max[i].dev_attr))
966 device_create_file(dev, &dev_attr_alarms_temp); 1043 || (err = device_create_file(dev,
967 } 1044 &temp_crit[i].dev_attr))
968 1045 || (err = device_create_file(dev,
969 if (data->innr == 14) { 1046 &temp_status[i].dev_attr)))
970 for (i = 0; i < 3; i++) { 1047 goto ERROR3;
971 device_create_file(dev, &therm_input[i].dev_attr);
972 device_create_file(dev, &therm_min[i].dev_attr);
973 device_create_file(dev, &therm_max[i].dev_attr);
974 device_create_file(dev, &therm_crit[i].dev_attr);
975 device_create_file(dev, &therm_status[i].dev_attr);
976 } 1048 }
1049 if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
1050 goto ERROR3;
977 } 1051 }
978 1052
979 for (i = 0; i < data->fannr; i++) { 1053 for (i = 0; i < data->fannr; i++) {
980 if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { 1054 if (FAN_CONFIG_MONITOR(data->fan_conf, i)
981 device_create_file(dev, &fan_input[i].dev_attr); 1055 && ((err = device_create_file(dev,
982 device_create_file(dev, &fan_min[i].dev_attr); 1056 &fan_input[i].dev_attr))
983 device_create_file(dev, &fan_div[i].dev_attr); 1057 || (err = device_create_file(dev,
984 device_create_file(dev, &fan_status[i].dev_attr); 1058 &fan_min[i].dev_attr))
985 } 1059 || (err = device_create_file(dev,
986 if (FAN_CONFIG_CONTROL(data->fan_conf, i)) 1060 &fan_div[i].dev_attr))
987 device_create_file(dev, &pwm[i].dev_attr); 1061 || (err = device_create_file(dev,
1062 &fan_status[i].dev_attr))))
1063 goto ERROR3;
1064
1065 if (FAN_CONFIG_CONTROL(data->fan_conf, i)
1066 && (err = device_create_file(dev, &pwm[i].dev_attr)))
1067 goto ERROR3;
988 } 1068 }
989 1069
1070 data->class_dev = hwmon_device_register(&client->dev);
1071 if (IS_ERR(data->class_dev)) {
1072 err = PTR_ERR(data->class_dev);
1073 goto ERROR3;
1074 }
990 return 0; 1075 return 0;
991 1076
992ERROR3: 1077ERROR3:
1078 /* can still remove groups whose members were added individually */
1079 sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
1080 sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
1081 sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
1082 sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
1083
993 i2c_detach_client(client); 1084 i2c_detach_client(client);
994ERROR2: 1085ERROR2:
995 for (i = 0; i < 3; i++) { 1086 for (i = 0; i < 3; i++) {
@@ -1009,6 +1100,11 @@ static int pc87360_detach_client(struct i2c_client *client)
1009 1100
1010 hwmon_device_unregister(data->class_dev); 1101 hwmon_device_unregister(data->class_dev);
1011 1102
1103 sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
1104 sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
1105 sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
1106 sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
1107
1012 if ((i = i2c_detach_client(client))) 1108 if ((i = i2c_detach_client(client)))
1013 return i; 1109 return i;
1014 1110