Commit db4919ec authored by Eddie James's avatar Eddie James Committed by Guenter Roeck
Browse files

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: default avatarEddie James <eajames@linux.ibm.com>
Reviewed-by: default avatarJoel Stanley <joel@jms.id.au>
Signed-off-by: default avatarJoel Stanley <joel@jms.id.au>
Link: https://lore.kernel.org/r/20201120010315.190737-4-joel@jms.id.au


Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 5ec96d74
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -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++;
			}
		}
	}