aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus/pmbus_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus/pmbus_core.c')
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c161
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 {
98struct pmbus_boolean { 98struct 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
103struct pmbus_label { 107struct 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 */
702static int pmbus_get_boolean(struct pmbus_data *data, int index) 701static 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
830static int pmbus_add_boolean(struct pmbus_data *data, 831static 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
854static int pmbus_add_boolean_reg(struct pmbus_data *data, 859static 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
861static 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
869static 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
897static int pmbus_add_label(struct pmbus_data *data, 890static 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;