[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250811050752.76030-2-chenchuande@gmail.com>
Date: Mon, 11 Aug 2025 13:07:52 +0800
From: Chuande Chen <chenchuande@...il.com>
To: jdelvare@...e.com
Cc: linux@...ck-us.net,
linux-hwmon@...r.kernel.org,
linux-kernel@...r.kernel.org,
chuachen@...co.com,
chenchuande@...il.com,
groeck7@...il.com
Subject: [PATCH v2 1/1] hwmon: sbtsi_temp: AMD CPU extended temperature range support
From: Chuande Chen <chuachen@...co.com>
Many AMD CPUs can support this feature now.
We would get a wrong CPU DIE temp if don't consider this.
In low-temperature environments, the CPU die temperature
can drop below zero.
So many platform would like to make extended temperature range
as their default configuration.
Default temperature range (0C to 255.875C) degree celsius.
Extended temperature range (-49C to +206.875C) degree celsius.
Ref Doc: AMD V3000 PPR (Doc ID #56558).
Signed-off-by: Chuande Chen <chuachen@...co.com>
---
V1 -> V2: addressed review comments, also save READ_ORDER bit into sbtsi_data
---
drivers/hwmon/sbtsi_temp.c | 46 +++++++++++++++++++++++++++-----------
1 file changed, 33 insertions(+), 13 deletions(-)
diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c
index 3c839f56c..32d6a7162 100644
--- a/drivers/hwmon/sbtsi_temp.c
+++ b/drivers/hwmon/sbtsi_temp.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 2020, Google Inc.
* Copyright (c) 2020, Kun Yi <kunyi@...gle.com>
+ * Copyright (c) 2025, Chuande Chen <chuachen@...co.com>
*/
#include <linux/err.h>
@@ -14,6 +15,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/bitfield.h>
/*
* SB-TSI registers only support SMBus byte data access. "_INT" registers are
@@ -29,8 +31,23 @@
#define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */
#define SBTSI_REG_TEMP_LOW_DEC 0x14 /* RW */
+/*
+ * Bit for reporting value with temperature measurement range.
+ * bit == 0: Use default temperature range (0C to 255.875C).
+ * bit == 1: Use extended temperature range (-49C to +206.875C).
+ */
+#define SBTSI_CONFIG_EXT_RANGE_SHIFT 2
+/*
+ * ReadOrder bit specifies the reading order of integer and
+ * decimal part of CPU temp for atomic reads. If bit == 0,
+ * reading integer part triggers latching of the decimal part,
+ * so integer part should be read first. If bit == 1, read
+ * order should be reversed.
+ */
#define SBTSI_CONFIG_READ_ORDER_SHIFT 5
+#define SBTSI_TEMP_EXT_RANGE_ADJ 49000
+
#define SBTSI_TEMP_MIN 0
#define SBTSI_TEMP_MAX 255875
@@ -38,6 +55,8 @@
struct sbtsi_data {
struct i2c_client *client;
struct mutex lock;
+ bool ext_range_mode;
+ bool read_order;
};
/*
@@ -74,23 +93,11 @@ static int sbtsi_read(struct device *dev, enum hwmon_sensor_types type,
{
struct sbtsi_data *data = dev_get_drvdata(dev);
s32 temp_int, temp_dec;
- int err;
switch (attr) {
case hwmon_temp_input:
- /*
- * ReadOrder bit specifies the reading order of integer and
- * decimal part of CPU temp for atomic reads. If bit == 0,
- * reading integer part triggers latching of the decimal part,
- * so integer part should be read first. If bit == 1, read
- * order should be reversed.
- */
- err = i2c_smbus_read_byte_data(data->client, SBTSI_REG_CONFIG);
- if (err < 0)
- return err;
-
mutex_lock(&data->lock);
- if (err & BIT(SBTSI_CONFIG_READ_ORDER_SHIFT)) {
+ if (data->read_order) {
temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_DEC);
temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_INT);
} else {
@@ -122,6 +129,8 @@ static int sbtsi_read(struct device *dev, enum hwmon_sensor_types type,
return temp_dec;
*val = sbtsi_reg_to_mc(temp_int, temp_dec);
+ if (data->ext_range_mode)
+ *val -= SBTSI_TEMP_EXT_RANGE_ADJ;
return 0;
}
@@ -146,6 +155,8 @@ static int sbtsi_write(struct device *dev, enum hwmon_sensor_types type,
return -EINVAL;
}
+ if (data->ext_range_mode)
+ val += SBTSI_TEMP_EXT_RANGE_ADJ;
val = clamp_val(val, SBTSI_TEMP_MIN, SBTSI_TEMP_MAX);
sbtsi_mc_to_reg(val, &temp_int, &temp_dec);
@@ -203,6 +214,7 @@ static int sbtsi_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct device *hwmon_dev;
struct sbtsi_data *data;
+ int err;
data = devm_kzalloc(dev, sizeof(struct sbtsi_data), GFP_KERNEL);
if (!data)
@@ -214,6 +226,14 @@ static int sbtsi_probe(struct i2c_client *client)
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, &sbtsi_chip_info,
NULL);
+ mutex_lock(&data->lock);
+ err = i2c_smbus_read_byte_data(data->client, SBTSI_REG_CONFIG);
+ mutex_unlock(&data->lock);
+ if (err < 0)
+ return err;
+ data->ext_range_mode = FIELD_GET(BIT(SBTSI_CONFIG_EXT_RANGE_SHIFT), err);
+ data->read_order = FIELD_GET(BIT(SBTSI_CONFIG_READ_ORDER_SHIFT), err);
+
return PTR_ERR_OR_ZERO(hwmon_dev);
}
--
2.39.5 (Apple Git-154)
Powered by blists - more mailing lists