Messages in this thread Patch in this message | | | From | Florian Fainelli <> | Subject | [PATCH v5 2/2] hwmon: scmi: Scale values to target desired HWMON units | Date | Wed, 8 May 2019 11:46:35 -0700 |
| |
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 appart they are.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> --- drivers/hwmon/scmi-hwmon.c | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index a80183a488c5..2c7b87edf5aa 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -18,6 +18,47 @@ 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 (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 +70,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; -- 2.17.1
| |