aboutsummaryrefslogtreecommitdiff
path: root/drivers/hwmon/occ
diff options
context:
space:
mode:
authorEddie James2020-11-20 11:33:15 +1030
committerGuenter Roeck2020-12-11 07:42:27 -0800
commitdb4919ec86ff405273a767e1a9b51e2760e73ce5 (patch)
tree0336d1da18f9e0999a41e2dd9e9296b17029ce8d /drivers/hwmon/occ
parent5ec96d74cf28c939e01b829f556832949b4c272a (diff)
hwmon: (occ) Add new temperature sensor type
The latest version of the On-Chip Controller (OCC) has a different format for the temperature sensor data. Add a new temperature sensor version to handle this data. Signed-off-by: Eddie James <eajames@linux.ibm.com> Reviewed-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Joel Stanley <joel@jms.id.au> Link: https://lore.kernel.org/r/20201120010315.190737-4-joel@jms.id.au Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/occ')
-rw-r--r--drivers/hwmon/occ/common.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index a71777990d49..7a5e539b567b 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -41,6 +41,14 @@ struct temp_sensor_2 {
u8 value;
} __packed;
+struct temp_sensor_10 {
+ u32 sensor_id;
+ u8 fru_type;
+ u8 value;
+ u8 throttle;
+ u8 reserved;
+} __packed;
+
struct freq_sensor_1 {
u16 sensor_id;
u16 value;
@@ -307,6 +315,60 @@ static ssize_t occ_show_temp_2(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
}
+static ssize_t occ_show_temp_10(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u32 val = 0;
+ struct temp_sensor_10 *temp;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ temp = ((struct temp_sensor_10 *)sensors->temp.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be32(&temp->sensor_id);
+ break;
+ case 1:
+ val = temp->value;
+ if (val == OCC_TEMP_SENSOR_FAULT)
+ return -EREMOTEIO;
+
+ /*
+ * VRM doesn't return temperature, only alarm bit. This
+ * attribute maps to tempX_alarm instead of tempX_input for
+ * VRM
+ */
+ if (temp->fru_type != OCC_FRU_TYPE_VRM) {
+ /* sensor not ready */
+ if (val == 0)
+ return -EAGAIN;
+
+ val *= 1000;
+ }
+ break;
+ case 2:
+ val = temp->fru_type;
+ break;
+ case 3:
+ val = temp->value == OCC_TEMP_SENSOR_FAULT;
+ break;
+ case 4:
+ val = temp->throttle * 1000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
static ssize_t occ_show_freq_1(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -745,6 +807,10 @@ static int occ_setup_sensor_attrs(struct occ *occ)
num_attrs += (sensors->temp.num_sensors * 4);
show_temp = occ_show_temp_2;
break;
+ case 0x10:
+ num_attrs += (sensors->temp.num_sensors * 5);
+ show_temp = occ_show_temp_10;
+ break;
default:
sensors->temp.num_sensors = 0;
}
@@ -844,6 +910,15 @@ static int occ_setup_sensor_attrs(struct occ *occ)
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
show_temp, NULL, 3, i);
attr++;
+
+ if (sensors->temp.version == 0x10) {
+ snprintf(attr->name, sizeof(attr->name),
+ "temp%d_max", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_temp, NULL,
+ 4, i);
+ attr++;
+ }
}
}