[PATCH v2] rtc: ab-eoz9: fix negative temperature readings
From: Yuehong Wu
Date: Sun Nov 08 2026 - 22:46:16 EST
The temperature register is coded with an offset of ABEOZ953_TEMP_MIN
(-60 degrees C), so the driver computes "raw + ABEOZ953_TEMP_MIN".
regmap_read() hands the raw value back in an unsigned int, which makes
that addition - and the multiplication by 1000 that follows - unsigned as
well: -60 becomes 0xffffffc4 and 1000 * (raw - 60) wraps around for every
raw value below 60.
On 64-bit systems the wrapped unsigned int is then zero-extended into the
long hwmon attribute, so every temperature below 0 degrees C is reported
as a huge positive value: raw 0 (the -60 degrees C code) becomes
4294907296 instead of -60000, raw 30 (-30 degrees C) becomes 4294937296
instead of -30000. This also contradicts temp1_min, which the same
driver reports as -60000, and consumers that only look for negative
values (thermal governors, monitoring daemons) do not discard the bogus
value.
Perform the arithmetic on a signed value.
Fixes: 67075b63cce2 ("rtc: add AB-RTCMC-32.768kHz-EOZ9 RTC support")
Cc: <stable@xxxxxxxxxxxxxxx>
Signed-off-by: Yuehong Wu <wuyuehong@xxxxxxxxxxxxxxxxxxxx>
---
v2: no code change; restore the first line of the commit message, which
was lost when v1 was converted to plain text.
The two expressions were checked with a small user space model of the
same types: raw 0 gives 4294907296 with the old expression and -60000
with this fix, raw 30 gives 4294937296 and -30000.
Compile-tested with gcc and W=1 (CONFIG_RTC_DRV_ABEOZ9=m); there is no
AB-RTCMC-32.768kHz-EOZ9 hardware here, so this was not exercised on a
device.
drivers/rtc/rtc-ab-eoz9.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
--- a/drivers/rtc/rtc-ab-eoz9.c
+++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -399,7 +399,7 @@ static int abeoz9z3_temp_read(struct device *dev,
ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
if (ret < 0)
return ret;
- *temp = 1000 * (val + ABEOZ953_TEMP_MIN);
+ *temp = 1000 * ((int)val + ABEOZ953_TEMP_MIN);
return 0;
case hwmon_temp_max:
*temp = 1000 * ABEOZ953_TEMP_MAX;