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: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> [sudeep.holla: added check of scale = 0 for early exit in scmi_hwmon_scale] Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
parent
0b673b6486
commit
ac778e6263
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue