diff options
Diffstat (limited to 'drivers/hwmon/scmi-hwmon.c')
-rw-r--r-- | drivers/hwmon/scmi-hwmon.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index a80183a488c5..0c93fc5ca762 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c | |||
@@ -18,6 +18,50 @@ struct scmi_sensors { | |||
18 | const struct scmi_sensor_info **info[hwmon_max]; | 18 | const struct scmi_sensor_info **info[hwmon_max]; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | static inline u64 __pow10(u8 x) | ||
22 | { | ||
23 | u64 r = 1; | ||
24 | |||
25 | while (x--) | ||
26 | r *= 10; | ||
27 | |||
28 | return r; | ||
29 | } | ||
30 | |||
31 | static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value) | ||
32 | { | ||
33 | s8 scale = sensor->scale; | ||
34 | u64 f; | ||
35 | |||
36 | switch (sensor->type) { | ||
37 | case TEMPERATURE_C: | ||
38 | case VOLTAGE: | ||
39 | case CURRENT: | ||
40 | scale += 3; | ||
41 | break; | ||
42 | case POWER: | ||
43 | case ENERGY: | ||
44 | scale += 6; | ||
45 | break; | ||
46 | default: | ||
47 | break; | ||
48 | } | ||
49 | |||
50 | if (scale == 0) | ||
51 | return 0; | ||
52 | |||
53 | if (abs(scale) > 19) | ||
54 | return -E2BIG; | ||
55 | |||
56 | f = __pow10(abs(scale)); | ||
57 | if (scale > 0) | ||
58 | *value *= f; | ||
59 | else | ||
60 | *value = div64_u64(*value, f); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
21 | static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, | 65 | static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, |
22 | u32 attr, int channel, long *val) | 66 | u32 attr, int channel, long *val) |
23 | { | 67 | { |
@@ -29,6 +73,10 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, | |||
29 | 73 | ||
30 | sensor = *(scmi_sensors->info[type] + channel); | 74 | sensor = *(scmi_sensors->info[type] + channel); |
31 | ret = h->sensor_ops->reading_get(h, sensor->id, false, &value); | 75 | ret = h->sensor_ops->reading_get(h, sensor->id, false, &value); |
76 | if (ret) | ||
77 | return ret; | ||
78 | |||
79 | ret = scmi_hwmon_scale(sensor, &value); | ||
32 | if (!ret) | 80 | if (!ret) |
33 | *val = value; | 81 | *val = value; |
34 | 82 | ||