Commit ac778e62 authored by Florian Fainelli's avatar Florian Fainelli Committed by Sudeep Holla

hwmon: scmi: Scale values to target desired HWMON units

If the SCMI firmware implementation is reporting values in a scale that
is different from the HWMON units, we need to scale up or down the value
according to how far apart they are.
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
[sudeep.holla: added check of scale = 0 for early exit in scmi_hwmon_scale]
Signed-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 0b673b64
......@@ -18,6 +18,50 @@ struct scmi_sensors {
const struct scmi_sensor_info **info[hwmon_max];
};
static inline u64 __pow10(u8 x)
{
u64 r = 1;
while (x--)
r *= 10;
return r;
}
static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
{
s8 scale = sensor->scale;
u64 f;
switch (sensor->type) {
case TEMPERATURE_C:
case VOLTAGE:
case CURRENT:
scale += 3;
break;
case POWER:
case ENERGY:
scale += 6;
break;
default:
break;
}
if (scale == 0)
return 0;
if (abs(scale) > 19)
return -E2BIG;
f = __pow10(abs(scale));
if (scale > 0)
*value *= f;
else
*value = div64_u64(*value, f);
return 0;
}
static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
......@@ -29,6 +73,10 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
sensor = *(scmi_sensors->info[type] + channel);
ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
if (ret)
return ret;
ret = scmi_hwmon_scale(sensor, &value);
if (!ret)
*val = value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment