Takashi Iwai 6081ab
From ca8fd8c16a8b77dfcf7f6ce52d2c863220693a78 Mon Sep 17 00:00:00 2001
Takashi Iwai 6081ab
From: Armin Wolf <W_Armin@gmx.de>
Takashi Iwai 6081ab
Date: Sat, 24 Dec 2022 05:18:53 +0100
Takashi Iwai 6081ab
Subject: [PATCH] hwmon: (ftsteutates) Fix scaling of measurements
Takashi Iwai 6081ab
Git-commit: ca8fd8c16a8b77dfcf7f6ce52d2c863220693a78
Takashi Iwai 6081ab
Patch-mainline: v6.3-rc1
Takashi Iwai 6081ab
References: git-fixes
Takashi Iwai 6081ab
Takashi Iwai 6081ab
A user complained that the ftsteutates driver was displaying
Takashi Iwai 6081ab
bogus values since its introduction. This happens because the
Takashi Iwai 6081ab
sensor measurements need to be scaled in order to produce
Takashi Iwai 6081ab
meaningful results:
Takashi Iwai 6081ab
- the fan speed needs to be multiplied by 60 since its in RPS
Takashi Iwai 6081ab
- the temperature is in degrees celsius and needs an offset of 64
Takashi Iwai 6081ab
- the voltage is in 1/256 of 3.3V
Takashi Iwai 6081ab
Takashi Iwai 6081ab
The offical datasheet says the voltage needs to be divided by 256,
Takashi Iwai 6081ab
but this is likely an off-by-one-error, since even the BIOS
Takashi Iwai 6081ab
devides by 255 (otherwise 3.3V could not be measured).
Takashi Iwai 6081ab
Takashi Iwai 6081ab
The voltage channels additionally need a board-specific multiplier,
Takashi Iwai 6081ab
however this can be done by the driver since its board-specific.
Takashi Iwai 6081ab
Takashi Iwai 6081ab
The reason the missing scaling of measurements is the way Fujitsu
Takashi Iwai 6081ab
used this driver when it was still out-of-tree. Back then, all
Takashi Iwai 6081ab
scaling was done in userspace by libsensors, even the generic one.
Takashi Iwai 6081ab
Takashi Iwai 6081ab
Tested on a Fujitsu DS3401-B1.
Takashi Iwai 6081ab
Takashi Iwai 6081ab
Fixes: 08426eda58e0 ("hwmon: Add driver for FTS BMC chip "Teutates"")
Takashi Iwai 6081ab
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Takashi Iwai 6081ab
Link: https://lore.kernel.org/r/20221224041855.83981-2-W_Armin@gmx.de
Takashi Iwai 6081ab
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Takashi Iwai 6081ab
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 6081ab
Takashi Iwai 6081ab
---
Takashi Iwai 6081ab
 Documentation/hwmon/ftsteutates.rst |  4 ++++
Takashi Iwai 6081ab
 drivers/hwmon/ftsteutates.c         | 19 +++++++++++++------
Takashi Iwai 6081ab
 2 files changed, 17 insertions(+), 6 deletions(-)
Takashi Iwai 6081ab
Takashi Iwai 6081ab
diff --git a/Documentation/hwmon/ftsteutates.rst b/Documentation/hwmon/ftsteutates.rst
Takashi Iwai 6081ab
index 58a2483d8d0d..198fa8e2819d 100644
Takashi Iwai 6081ab
--- a/Documentation/hwmon/ftsteutates.rst
Takashi Iwai 6081ab
+++ b/Documentation/hwmon/ftsteutates.rst
Takashi Iwai 6081ab
@@ -22,6 +22,10 @@ enhancements. It can monitor up to 4 voltages, 16 temperatures and
Takashi Iwai 6081ab
 8 fans. It also contains an integrated watchdog which is currently
Takashi Iwai 6081ab
 implemented in this driver.
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
+The 4 voltages require a board-specific multiplier, since the BMC can
Takashi Iwai 6081ab
+only measure voltages up to 3.3V and thus relies on voltage dividers.
Takashi Iwai 6081ab
+Consult your motherboard manual for details.
Takashi Iwai 6081ab
+
Takashi Iwai 6081ab
 To clear a temperature or fan alarm, execute the following command with the
Takashi Iwai 6081ab
 correct path to the alarm file::
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c
Takashi Iwai 6081ab
index f5b8e724a8ca..ffa0bb364877 100644
Takashi Iwai 6081ab
--- a/drivers/hwmon/ftsteutates.c
Takashi Iwai 6081ab
+++ b/drivers/hwmon/ftsteutates.c
Takashi Iwai 6081ab
@@ -12,6 +12,7 @@
Takashi Iwai 6081ab
 #include <linux/i2c.h>
Takashi Iwai 6081ab
 #include <linux/init.h>
Takashi Iwai 6081ab
 #include <linux/jiffies.h>
Takashi Iwai 6081ab
+#include <linux/math.h>
Takashi Iwai 6081ab
 #include <linux/module.h>
Takashi Iwai 6081ab
 #include <linux/mutex.h>
Takashi Iwai 6081ab
 #include <linux/slab.h>
Takashi Iwai 6081ab
@@ -347,13 +348,15 @@ static ssize_t in_value_show(struct device *dev,
Takashi Iwai 6081ab
 {
Takashi Iwai 6081ab
 	struct fts_data *data = dev_get_drvdata(dev);
Takashi Iwai 6081ab
 	int index = to_sensor_dev_attr(devattr)->index;
Takashi Iwai 6081ab
-	int err;
Takashi Iwai 6081ab
+	int value, err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 	err = fts_update_device(data);
Takashi Iwai 6081ab
 	if (err < 0)
Takashi Iwai 6081ab
 		return err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
-	return sprintf(buf, "%u\n", data->volt[index]);
Takashi Iwai 6081ab
+	value = DIV_ROUND_CLOSEST(data->volt[index] * 3300, 255);
Takashi Iwai 6081ab
+
Takashi Iwai 6081ab
+	return sprintf(buf, "%d\n", value);
Takashi Iwai 6081ab
 }
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 static ssize_t temp_value_show(struct device *dev,
Takashi Iwai 6081ab
@@ -361,13 +364,15 @@ static ssize_t temp_value_show(struct device *dev,
Takashi Iwai 6081ab
 {
Takashi Iwai 6081ab
 	struct fts_data *data = dev_get_drvdata(dev);
Takashi Iwai 6081ab
 	int index = to_sensor_dev_attr(devattr)->index;
Takashi Iwai 6081ab
-	int err;
Takashi Iwai 6081ab
+	int value, err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 	err = fts_update_device(data);
Takashi Iwai 6081ab
 	if (err < 0)
Takashi Iwai 6081ab
 		return err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
-	return sprintf(buf, "%u\n", data->temp_input[index]);
Takashi Iwai 6081ab
+	value = (data->temp_input[index] - 64) * 1000;
Takashi Iwai 6081ab
+
Takashi Iwai 6081ab
+	return sprintf(buf, "%d\n", value);
Takashi Iwai 6081ab
 }
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 static ssize_t temp_fault_show(struct device *dev,
Takashi Iwai 6081ab
@@ -436,13 +441,15 @@ static ssize_t fan_value_show(struct device *dev,
Takashi Iwai 6081ab
 {
Takashi Iwai 6081ab
 	struct fts_data *data = dev_get_drvdata(dev);
Takashi Iwai 6081ab
 	int index = to_sensor_dev_attr(devattr)->index;
Takashi Iwai 6081ab
-	int err;
Takashi Iwai 6081ab
+	int value, err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 	err = fts_update_device(data);
Takashi Iwai 6081ab
 	if (err < 0)
Takashi Iwai 6081ab
 		return err;
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
-	return sprintf(buf, "%u\n", data->fan_input[index]);
Takashi Iwai 6081ab
+	value = data->fan_input[index] * 60;
Takashi Iwai 6081ab
+
Takashi Iwai 6081ab
+	return sprintf(buf, "%d\n", value);
Takashi Iwai 6081ab
 }
Takashi Iwai 6081ab
 
Takashi Iwai 6081ab
 static ssize_t fan_source_show(struct device *dev,
Takashi Iwai 6081ab
-- 
Takashi Iwai 6081ab
2.35.3
Takashi Iwai 6081ab