summaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2019-06-17 04:54:11 -0700
committerOlof Johansson <olof@lixom.net>2019-06-17 04:54:11 -0700
commitdf767c0a437c9094ca2d79d37c1c5cf559039f53 (patch)
tree37a0b624989bd727ed60cc6025f95ba6b1687e00 /drivers/hwmon
parentc3bd15a0786ef7e32482a7dced21d79286b6f36c (diff)
parentac778e62634eee0685b622605b063a49edf2f2d1 (diff)
downloadlinux-df767c0a437c9094ca2d79d37c1c5cf559039f53.tar.bz2
Merge tag 'scmi-updates-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers
ARM SCMI updates/fixes for v5.3 1. Correction to ARM document ID referred in SCMI protocol binding 2. Fix to correct bitfield definitions for SENSOR_DESC attributes which otherwise will calculate sensor values on wrong scale 3. Adds the missing rate_discrete flag setting so that discrete clocks are handled correctly. Without this fix it assumes continuous range which is incorrect 4. Adds support to read and scale the sensor values based on the factor read from the firmware * tag 'scmi-updates-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: hwmon: scmi: Scale values to target desired HWMON units firmware: arm_scmi: fetch and store sensor scale firmware: arm_scmi: update rate_discrete in clock_describe_rates_get firmware: arm_scmi: fix bitfield definitions for SENSOR_DESC attributes dt-bindings: arm: fix the document ID for SCMI protocol documentation Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/scmi-hwmon.c48
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 {
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;