[PATCH v1 5/7] zorro: warp mfd: expose the voltage and temperature sensors

From: Paolo Pisati

Date: Wed Nov 11 2026 - 11:42:57 EST


The diagnostic frame carries the 5 V rail, the backup battery and three
temperatures - the 68060, its NTC and the ARM - as IEEE-754 binary32.

Decode the bit pattern with integer arithmetic into milli-units.

Signed-off-by: Paolo Pisati <p.pisati@xxxxxxxxx>
---
.../ABI/testing/sysfs-driver-warp-mfd | 19 +++++
drivers/zorro/warp-mfd.c | 80 +++++++++++++++++++
drivers/zorro/warp-mfd.h | 4 +
3 files changed, 103 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-warp-mfd b/Documentation/ABI/testing/sysfs-driver-warp-mfd
index 8996d1961b96..fec712b8b9b0 100644
--- a/Documentation/ABI/testing/sysfs-driver-warp-mfd
+++ b/Documentation/ABI/testing/sysfs-driver-warp-mfd
@@ -14,3 +14,22 @@ Contact: Paolo Pisati <p.pisati@xxxxxxxxx>
Description:
(RO) Firmware and hardware version, as four hexadecimal digits:
an fmwver of 2027 is firmware release 20.27.
+
+What: /sys/bus/zorro/devices/zorro<N>/t60int
+What: /sys/bus/zorro/devices/zorro<N>/t60ext
+What: /sys/bus/zorro/devices/zorro<N>/tarm
+Date: November 2026
+KernelVersion: 7.5
+Contact: Paolo Pisati <p.pisati@xxxxxxxxx>
+Description:
+ (RO) Temperatures in degrees Celsius, with one decimal: t60int
+ is the 68060, t60ext its NTC, tarm the ARM co-processor.
+
+What: /sys/bus/zorro/devices/zorro<N>/vbatt
+What: /sys/bus/zorro/devices/zorro<N>/vcc5v
+Date: November 2026
+KernelVersion: 7.5
+Contact: Paolo Pisati <p.pisati@xxxxxxxxx>
+Description:
+ (RO) Voltages in volts, with two decimals: vbatt is the backup
+ battery, vcc5v the 5 V rail.
diff --git a/drivers/zorro/warp-mfd.c b/drivers/zorro/warp-mfd.c
index 61866f678b61..d407c786d44b 100644
--- a/drivers/zorro/warp-mfd.c
+++ b/drivers/zorro/warp-mfd.c
@@ -15,6 +15,7 @@
*/

#include <linux/array_size.h>
+#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/init.h>
@@ -22,6 +23,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/jiffies.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -190,6 +192,73 @@ static int warp_get_status(struct warp_mfd *warp, union warp_reply *rpl)
return 0;
}

+/*
+ * The board reports its sensors as IEEE-754 binary32: decode the
+ * bit pattern by hand and carry the result as milli-units.
+ */
+static int warp_f32_to_milli(u32 bits)
+{
+ int exp = (bits >> 23) & 0xff;
+ u32 frac = bits & GENMASK(22, 0);
+ int shift = exp - 127 - 23;
+ s64 v;
+
+ /*
+ * inf, NaN, zero and subnormals all round to nothing useful here, and
+ * so does anything of 2^23 or more: that is already past what an int
+ * holds in milli-units, let alone what a sensor reports.
+ */
+ if (exp == 0xff || exp == 0 || shift >= 0)
+ return 0;
+ if (shift <= -63) /* smaller than a milli-unit */
+ return 0;
+
+ v = ((s64)(frac | BIT(23)) * 1000) >> -shift;
+ if (v > INT_MAX) /* a shift of -1 or -2 can still overflow */
+ return 0;
+
+ return (bits & BIT(31)) ? -(int)v : (int)v;
+}
+
+/* Render milli-units with @dec decimal places, rounded, as WarpDiag shows them. */
+static int warp_print_milli(char *buf, int milli, unsigned int dec)
+{
+ unsigned int scale = (dec == 1) ? 100 : 10;
+ unsigned int units = (dec == 1) ? 10 : 100;
+ const char *sign = "";
+ unsigned int v;
+
+ if (milli < 0) {
+ sign = "-";
+ milli = -milli;
+ }
+ v = ((unsigned int)milli + scale / 2) / scale;
+
+ return sysfs_emit(buf, "%s%u.%0*u\n", sign, v / units, dec, v % units);
+}
+
+#define warp_config_sensor_attr(name, field, dec) \
+static ssize_t name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ int ret; \
+ struct warp_mfd *warp = dev_get_drvdata(dev); \
+ union warp_reply *rpl; \
+ \
+ rpl = kmalloc_obj(*rpl); \
+ if (!rpl) \
+ return -ENOMEM; \
+ ret = warp_get_status(warp, rpl); \
+ if (ret) \
+ goto out; \
+ ret = warp_print_milli(buf, \
+ warp_f32_to_milli(rpl->diag.field), dec);\
+out: \
+ kfree(rpl); \
+ return ret; \
+} \
+static DEVICE_ATTR_RO(name)
+
#define warp_config_uint_attr(name, field, format_string) \
static ssize_t name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@@ -236,12 +305,23 @@ static DEVICE_ATTR_RO(name)
warp_config_string_attr(boardname, board_name);
warp_config_uint_attr(fmwver, fmw_ver, "%04X");
warp_config_uint_attr(hwver, hw_ver, "%04X");
+/* board sensors: volts to 2 decimals, temperatures to 1, as WarpDiag shows them */
+warp_config_sensor_attr(t60int, t60_internal, 1);
+warp_config_sensor_attr(t60ext, t60_ntc, 1);
+warp_config_sensor_attr(tarm, t_arm, 1);
+warp_config_sensor_attr(vbatt, vbatt, 2);
+warp_config_sensor_attr(vcc5v, vcc5v, 2);

static struct attribute *warp_attrs[] = {
/* RO attr */
&dev_attr_boardname.attr,
&dev_attr_fmwver.attr,
&dev_attr_hwver.attr,
+ &dev_attr_t60int.attr,
+ &dev_attr_t60ext.attr,
+ &dev_attr_tarm.attr,
+ &dev_attr_vbatt.attr,
+ &dev_attr_vcc5v.attr,
NULL
};

diff --git a/drivers/zorro/warp-mfd.h b/drivers/zorro/warp-mfd.h
index 366848545ea4..4fa09fa972d4 100644
--- a/drivers/zorro/warp-mfd.h
+++ b/drivers/zorro/warp-mfd.h
@@ -84,6 +84,10 @@ struct warp_rpl_hdr {
* Reply to WARP_CMD_GET_DIAG. Fields this driver does not expose are kept
* so the ones after them land at the right offset.
*
+ * The board reports its sensors as IEEE-754 binary32. They are kept as raw
+ * bit patterns because the kernel cannot use the FPU; warp_f32_to_milli()
+ * decodes them with integer arithmetic.
+ *
* turbo_level and tz_corr_secs are reported by the firmware but no longer
* maintained by it; treat their contents as stale.
*/
--
2.43.0