diff options
Diffstat (limited to 'drivers/hwmon/pmbus/pmbus_core.c')
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 161 |
1 files changed, 74 insertions, 87 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 0f51cd66ecfd..d1792d7195bf 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c | |||
@@ -98,7 +98,11 @@ struct pmbus_sensor { | |||
98 | struct pmbus_boolean { | 98 | struct pmbus_boolean { |
99 | char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ | 99 | char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ |
100 | struct sensor_device_attribute attribute; | 100 | struct sensor_device_attribute attribute; |
101 | struct pmbus_sensor *s1; | ||
102 | struct pmbus_sensor *s2; | ||
101 | }; | 103 | }; |
104 | #define to_pmbus_boolean(_attr) \ | ||
105 | container_of(_attr, struct pmbus_boolean, attribute) | ||
102 | 106 | ||
103 | struct pmbus_label { | 107 | struct pmbus_label { |
104 | char name[PMBUS_NAME_SIZE]; /* sysfs label name */ | 108 | char name[PMBUS_NAME_SIZE]; /* sysfs label name */ |
@@ -673,25 +677,20 @@ static u16 pmbus_data2reg(struct pmbus_data *data, | |||
673 | 677 | ||
674 | /* | 678 | /* |
675 | * Return boolean calculated from converted data. | 679 | * Return boolean calculated from converted data. |
676 | * <index> defines a status register index and mask, and optionally | 680 | * <index> defines a status register index and mask. |
677 | * two sensor indexes. | 681 | * The mask is in the lower 8 bits, the register index is in bits 8..23. |
678 | * The upper half-word references the two sensors, | ||
679 | * two sensor indices. | ||
680 | * The upper half-word references the two optional sensors, | ||
681 | * the lower half word references status register and mask. | ||
682 | * The function returns true if (status[reg] & mask) is true and, | ||
683 | * if specified, if v1 >= v2. | ||
684 | * To determine if an object exceeds upper limits, specify <v, limit>. | ||
685 | * To determine if an object exceeds lower limits, specify <limit, v>. | ||
686 | * | 682 | * |
687 | * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of | 683 | * The associated pmbus_boolean structure contains optional pointers to two |
688 | * index are set. s1 and s2 (the sensor index values) are zero in this case. | 684 | * sensor attributes. If specified, those attributes are compared against each |
689 | * The function returns true if (status[reg] & mask) is true. | 685 | * other to determine if a limit has been exceeded. |
690 | * | 686 | * |
691 | * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against | 687 | * If the sensor attribute pointers are NULL, the function returns true if |
692 | * a specified limit has to be performed to determine the boolean result. | 688 | * (status[reg] & mask) is true. |
689 | * | ||
690 | * If sensor attribute pointers are provided, a comparison against a specified | ||
691 | * limit has to be performed to determine the boolean result. | ||
693 | * In this case, the function returns true if v1 >= v2 (where v1 and v2 are | 692 | * In this case, the function returns true if v1 >= v2 (where v1 and v2 are |
694 | * sensor values referenced by sensor indices s1 and s2). | 693 | * sensor values referenced by sensor attribute pointers s1 and s2). |
695 | * | 694 | * |
696 | * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>. | 695 | * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>. |
697 | * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>. | 696 | * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>. |
@@ -699,11 +698,12 @@ static u16 pmbus_data2reg(struct pmbus_data *data, | |||
699 | * If a negative value is stored in any of the referenced registers, this value | 698 | * If a negative value is stored in any of the referenced registers, this value |
700 | * reflects an error code which will be returned. | 699 | * reflects an error code which will be returned. |
701 | */ | 700 | */ |
702 | static int pmbus_get_boolean(struct pmbus_data *data, int index) | 701 | static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, |
702 | int index) | ||
703 | { | 703 | { |
704 | u8 s1 = (index >> 24) & 0xff; | 704 | struct pmbus_sensor *s1 = b->s1; |
705 | u8 s2 = (index >> 16) & 0xff; | 705 | struct pmbus_sensor *s2 = b->s2; |
706 | u8 reg = (index >> 8) & 0xff; | 706 | u16 reg = (index >> 8) & 0xffff; |
707 | u8 mask = index & 0xff; | 707 | u8 mask = index & 0xff; |
708 | int ret, status; | 708 | int ret, status; |
709 | u8 regval; | 709 | u8 regval; |
@@ -713,21 +713,21 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index) | |||
713 | return status; | 713 | return status; |
714 | 714 | ||
715 | regval = status & mask; | 715 | regval = status & mask; |
716 | if (!s1 && !s2) | 716 | if (!s1 && !s2) { |
717 | ret = !!regval; | 717 | ret = !!regval; |
718 | else { | 718 | } else if (!s1 || !s2) { |
719 | BUG(); | ||
720 | return 0; | ||
721 | } else { | ||
719 | long v1, v2; | 722 | long v1, v2; |
720 | struct pmbus_sensor *sensor1, *sensor2; | ||
721 | 723 | ||
722 | sensor1 = &data->sensors[s1]; | 724 | if (s1->data < 0) |
723 | if (sensor1->data < 0) | 725 | return s1->data; |
724 | return sensor1->data; | 726 | if (s2->data < 0) |
725 | sensor2 = &data->sensors[s2]; | 727 | return s2->data; |
726 | if (sensor2->data < 0) | ||
727 | return sensor2->data; | ||
728 | 728 | ||
729 | v1 = pmbus_reg2data(data, sensor1); | 729 | v1 = pmbus_reg2data(data, s1); |
730 | v2 = pmbus_reg2data(data, sensor2); | 730 | v2 = pmbus_reg2data(data, s2); |
731 | ret = !!(regval && v1 >= v2); | 731 | ret = !!(regval && v1 >= v2); |
732 | } | 732 | } |
733 | return ret; | 733 | return ret; |
@@ -737,10 +737,11 @@ static ssize_t pmbus_show_boolean(struct device *dev, | |||
737 | struct device_attribute *da, char *buf) | 737 | struct device_attribute *da, char *buf) |
738 | { | 738 | { |
739 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 739 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
740 | struct pmbus_boolean *boolean = to_pmbus_boolean(attr); | ||
740 | struct pmbus_data *data = pmbus_update_device(dev); | 741 | struct pmbus_data *data = pmbus_update_device(dev); |
741 | int val; | 742 | int val; |
742 | 743 | ||
743 | val = pmbus_get_boolean(data, attr->index); | 744 | val = pmbus_get_boolean(data, boolean, attr->index); |
744 | if (val < 0) | 745 | if (val < 0) |
745 | return val; | 746 | return val; |
746 | return snprintf(buf, PAGE_SIZE, "%d\n", val); | 747 | return snprintf(buf, PAGE_SIZE, "%d\n", val); |
@@ -829,7 +830,9 @@ static void pmbus_attr_init(struct sensor_device_attribute *a, | |||
829 | 830 | ||
830 | static int pmbus_add_boolean(struct pmbus_data *data, | 831 | static int pmbus_add_boolean(struct pmbus_data *data, |
831 | const char *name, const char *type, int seq, | 832 | const char *name, const char *type, int seq, |
832 | int idx) | 833 | struct pmbus_sensor *s1, |
834 | struct pmbus_sensor *s2, | ||
835 | u16 reg, u8 mask) | ||
833 | { | 836 | { |
834 | struct pmbus_boolean *boolean; | 837 | struct pmbus_boolean *boolean; |
835 | struct sensor_device_attribute *a; | 838 | struct sensor_device_attribute *a; |
@@ -844,32 +847,20 @@ static int pmbus_add_boolean(struct pmbus_data *data, | |||
844 | 847 | ||
845 | snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", | 848 | snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", |
846 | name, seq, type); | 849 | name, seq, type); |
850 | boolean->s1 = s1; | ||
851 | boolean->s2 = s2; | ||
847 | pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, | 852 | pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, |
848 | idx); | 853 | (reg << 8) | mask); |
849 | data->attributes[data->num_attributes++] = &a->dev_attr.attr; | 854 | data->attributes[data->num_attributes++] = &a->dev_attr.attr; |
850 | 855 | ||
851 | return 0; | 856 | return 0; |
852 | } | 857 | } |
853 | 858 | ||
854 | static int pmbus_add_boolean_reg(struct pmbus_data *data, | 859 | static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, |
855 | const char *name, const char *type, | 860 | const char *name, const char *type, |
856 | int seq, int reg, int bit) | 861 | int seq, int page, int reg, |
857 | { | 862 | enum pmbus_sensor_classes class, |
858 | return pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit); | 863 | bool update, bool readonly) |
859 | } | ||
860 | |||
861 | static int pmbus_add_boolean_cmp(struct pmbus_data *data, | ||
862 | const char *name, const char *type, | ||
863 | int seq, int i1, int i2, int reg, int mask) | ||
864 | { | ||
865 | return pmbus_add_boolean(data, name, type, seq, | ||
866 | (i1 << 24) | (i2 << 16) | (reg << 8) | mask); | ||
867 | } | ||
868 | |||
869 | static void pmbus_add_sensor(struct pmbus_data *data, | ||
870 | const char *name, const char *type, int seq, | ||
871 | int page, int reg, enum pmbus_sensor_classes class, | ||
872 | bool update, bool readonly) | ||
873 | { | 864 | { |
874 | struct pmbus_sensor *sensor; | 865 | struct pmbus_sensor *sensor; |
875 | struct sensor_device_attribute *a; | 866 | struct sensor_device_attribute *a; |
@@ -892,6 +883,8 @@ static void pmbus_add_sensor(struct pmbus_data *data, | |||
892 | 883 | ||
893 | data->attributes[data->num_attributes++] = &a->dev_attr.attr; | 884 | data->attributes[data->num_attributes++] = &a->dev_attr.attr; |
894 | data->num_sensors++; | 885 | data->num_sensors++; |
886 | |||
887 | return sensor; | ||
895 | } | 888 | } |
896 | 889 | ||
897 | static int pmbus_add_label(struct pmbus_data *data, | 890 | static int pmbus_add_label(struct pmbus_data *data, |
@@ -1023,38 +1016,31 @@ static int pmbus_add_limit_attrs(struct i2c_client *client, | |||
1023 | struct pmbus_data *data, | 1016 | struct pmbus_data *data, |
1024 | const struct pmbus_driver_info *info, | 1017 | const struct pmbus_driver_info *info, |
1025 | const char *name, int index, int page, | 1018 | const char *name, int index, int page, |
1026 | int cbase, | 1019 | struct pmbus_sensor *base, |
1027 | const struct pmbus_sensor_attr *attr) | 1020 | const struct pmbus_sensor_attr *attr) |
1028 | { | 1021 | { |
1029 | const struct pmbus_limit_attr *l = attr->limit; | 1022 | const struct pmbus_limit_attr *l = attr->limit; |
1030 | int nlimit = attr->nlimit; | 1023 | int nlimit = attr->nlimit; |
1031 | int have_alarm = 0; | 1024 | int have_alarm = 0; |
1032 | int i, cindex; | 1025 | int i, ret; |
1033 | int ret; | 1026 | struct pmbus_sensor *curr; |
1034 | 1027 | ||
1035 | for (i = 0; i < nlimit; i++) { | 1028 | for (i = 0; i < nlimit; i++) { |
1036 | if (pmbus_check_word_register(client, page, l->reg)) { | 1029 | if (pmbus_check_word_register(client, page, l->reg)) { |
1037 | cindex = data->num_sensors; | 1030 | curr = pmbus_add_sensor(data, name, l->attr, index, |
1038 | pmbus_add_sensor(data, name, l->attr, index, page, | 1031 | page, l->reg, attr->class, |
1039 | l->reg, attr->class, | 1032 | attr->update || l->update, |
1040 | attr->update || l->update, | 1033 | false); |
1041 | false); | ||
1042 | if (l->sbit && (info->func[page] & attr->sfunc)) { | 1034 | if (l->sbit && (info->func[page] & attr->sfunc)) { |
1043 | if (attr->compare) { | 1035 | ret = pmbus_add_boolean(data, name, |
1044 | ret = pmbus_add_boolean_cmp(data, name, | 1036 | l->alarm, index, |
1045 | l->alarm, index, | 1037 | attr->compare ? l->low ? curr : base |
1046 | l->low ? cindex : cbase, | 1038 | : NULL, |
1047 | l->low ? cbase : cindex, | 1039 | attr->compare ? l->low ? base : curr |
1048 | attr->sbase + page, l->sbit); | 1040 | : NULL, |
1049 | if (ret) | 1041 | attr->sbase + page, l->sbit); |
1050 | return ret; | 1042 | if (ret) |
1051 | } else { | 1043 | return ret; |
1052 | ret = pmbus_add_boolean_reg(data, name, | ||
1053 | l->alarm, index, | ||
1054 | attr->sbase + page, l->sbit); | ||
1055 | if (ret) | ||
1056 | return ret; | ||
1057 | } | ||
1058 | have_alarm = 1; | 1044 | have_alarm = 1; |
1059 | } | 1045 | } |
1060 | } | 1046 | } |
@@ -1070,7 +1056,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, | |||
1070 | int index, int page, | 1056 | int index, int page, |
1071 | const struct pmbus_sensor_attr *attr) | 1057 | const struct pmbus_sensor_attr *attr) |
1072 | { | 1058 | { |
1073 | int cbase = data->num_sensors; | 1059 | struct pmbus_sensor *base; |
1074 | int ret; | 1060 | int ret; |
1075 | 1061 | ||
1076 | if (attr->label) { | 1062 | if (attr->label) { |
@@ -1079,11 +1065,11 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, | |||
1079 | if (ret) | 1065 | if (ret) |
1080 | return ret; | 1066 | return ret; |
1081 | } | 1067 | } |
1082 | pmbus_add_sensor(data, name, "input", index, page, attr->reg, | 1068 | base = pmbus_add_sensor(data, name, "input", index, page, attr->reg, |
1083 | attr->class, true, true); | 1069 | attr->class, true, true); |
1084 | if (attr->sfunc) { | 1070 | if (attr->sfunc) { |
1085 | ret = pmbus_add_limit_attrs(client, data, info, name, | 1071 | ret = pmbus_add_limit_attrs(client, data, info, name, |
1086 | index, page, cbase, attr); | 1072 | index, page, base, attr); |
1087 | if (ret < 0) | 1073 | if (ret < 0) |
1088 | return ret; | 1074 | return ret; |
1089 | /* | 1075 | /* |
@@ -1094,9 +1080,10 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, | |||
1094 | if (!ret && attr->gbit && | 1080 | if (!ret && attr->gbit && |
1095 | pmbus_check_byte_register(client, page, | 1081 | pmbus_check_byte_register(client, page, |
1096 | PMBUS_STATUS_BYTE)) { | 1082 | PMBUS_STATUS_BYTE)) { |
1097 | ret = pmbus_add_boolean_reg(data, name, "alarm", index, | 1083 | ret = pmbus_add_boolean(data, name, "alarm", index, |
1098 | PB_STATUS_BASE + page, | 1084 | NULL, NULL, |
1099 | attr->gbit); | 1085 | PB_STATUS_BASE + page, |
1086 | attr->gbit); | ||
1100 | if (ret) | 1087 | if (ret) |
1101 | return ret; | 1088 | return ret; |
1102 | } | 1089 | } |
@@ -1635,13 +1622,13 @@ static int pmbus_add_fan_attributes(struct i2c_client *client, | |||
1635 | base = PB_STATUS_FAN34_BASE + page; | 1622 | base = PB_STATUS_FAN34_BASE + page; |
1636 | else | 1623 | else |
1637 | base = PB_STATUS_FAN_BASE + page; | 1624 | base = PB_STATUS_FAN_BASE + page; |
1638 | ret = pmbus_add_boolean_reg(data, "fan", | 1625 | ret = pmbus_add_boolean(data, "fan", |
1639 | "alarm", index, base, | 1626 | "alarm", index, NULL, NULL, base, |
1640 | PB_FAN_FAN1_WARNING >> (f & 1)); | 1627 | PB_FAN_FAN1_WARNING >> (f & 1)); |
1641 | if (ret) | 1628 | if (ret) |
1642 | return ret; | 1629 | return ret; |
1643 | ret = pmbus_add_boolean_reg(data, "fan", | 1630 | ret = pmbus_add_boolean(data, "fan", |
1644 | "fault", index, base, | 1631 | "fault", index, NULL, NULL, base, |
1645 | PB_FAN_FAN1_FAULT >> (f & 1)); | 1632 | PB_FAN_FAN1_FAULT >> (f & 1)); |
1646 | if (ret) | 1633 | if (ret) |
1647 | return ret; | 1634 | return ret; |