* [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC
@ 2026-09-28 4:44 Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou
Hi all:
This patch series adds thermal zone support for the Loongson-2K0300 SoC.
The Loongson-2K0300's thermal sensor is generally compatible with the
existing Loongson-2K series, but it features several key differences:
1. It has an independent CPU ID register for reading chip version
information.
2. The raw temperature output field has been extended from 8 bits to 11
bits.
3. The temperature calculation formula has been updated to incorporate a
correction factor based on the version information.
To ensure robustness on older hardware revisions, a fallback mechanism
is included: if the calculated temperature falls outside the valid range
(-55 TO 125), the driver falls back to a simpler calculation and prints
a warning.
The series also includes fixes and cleanups for the existing Loongson-2
thermal driver, which are necessary to support the new SoC cleanly.
The patchset have been validated on the Loongson-2K series development boards.
Thanks.
Binbin
=========
V6:
- Rebase on linux-pm/thermal;
Patch (2/7):
- New patch;
- Fix incorrect clamp() argument order for thermal trip points;
Patch (3/7):
- New patch;
- Fix Loongson-2K2000 trip point programming by adding a per-SoC
set_trips_regs callback and handling the split HI_GATE registers;
Patch (4/7):
- New patch;
- cleanup: use GENMASK/FIELD_* helpers, add named constants, and factor
common trip point setup;
Patch (5/7):
- New patch;
- refactor: move thermal_zone_device_ops into chip_data and replace the
Loongson-2K2000 flag special case with an optional init_extend_resource
callback;
Patch (7/7):
- Updated the 10-bit output to 11-bit in commit message;
- Temporarily remove the implementation of `set_trips`;
- Remove unnecessary header files;
- Rewrite `get_temp`, separating `read_calib` and `detect_old_fuse` into
new functions to be called during the probe;
- Use macros to define the relevant numbers.
Link to V5:
https://lore.kernel.org/all/cover.1789546118.git.zhoubinbin@loongson.cn/#t
V5:
- Rebase on linux-pm/thermal;
- Drop patch-3 for it was applied.
Link to V4:
https://lore.kernel.org/all/cover.1785829933.git.zhoubinbin@loongson.cn/
V4:
- Rebase on linux-mfd/for-mfd-next;
Patch (3/5):
- Remove the operation that adds `compatible` to the `select` node.
Link to V3:
https://lore.kernel.org/all/cover.1785480242.git.zhoubinbin@loongson.cn/
V3:
Patch (2/5):
- New patch for moving thermal_ops to chip_data;
Patch (3/5):
- Correct spelling errors;
Patch (4/5):
- Add Acked-by from Conor, thanks;
Patch (5/5):
- Keep loongson2_thermal_data->chip_data as const, and use
data->flags as the private data.
- Renmae LOONGSON2_THSENS_OUT_10B_MASK ->
LOONGSON2_THSENS_OUT_11B_MASK;
Link to V2:
https://lore.kernel.org/all/cover.1784619512.git.zhoubinbin@loongson.cn/
V2:
Patch (1/4):
- New patch form Sashiko;
Patch (2/4):
- New patch for adding chipid syscon compatible;
Patch (3/4):
- Use `loongson,chipid` phandle replace reg property;
Patch (3/4):
- Refact `calib_offset` calculate routing;
- Add LS2K0300_OLD_FUSE_FLAG flag.
Link to V1:
https://lore.kernel.org/all/cover.1783670011.git.zhoubinbin@loongson.cn/
Binbin Zhou (7):
thermal/drivers/loongson2: Correct thermal sensor registration loop
thermal/drivers/loongson2: Fix clamp() usage for thermal trip points
thermal/drivers/loongson2: Fix Loongson-2K2000 trip point programming
thermal/drivers/loongson2: Use bitfields and per-SoC thermal ops
thermal/drivers/loongson2: Move per-SoC ops into chip data
dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for
Loongson-2K0300
thermal/drivers/loongson2: Add Loongson-2K0300 support
.../thermal/loongson,ls2k-thermal.yaml | 73 +++-
drivers/thermal/loongson2_thermal.c | 336 ++++++++++++++----
2 files changed, 321 insertions(+), 88 deletions(-)
base-commit: ec0d89150a9381d591344a9f6f5428655c227a7f
--
2.52.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 7:15 ` Daniel Lezcano
2026-09-28 4:44 ` [PATCH v6 2/7] thermal/drivers/loongson2: Fix clamp() usage for thermal trip points Binbin Zhou
` (5 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou, stable, Sashiko
The registration loop in loongson2_thermal_probe() incorrectly uses
dev_err_probe() when the sensor is not present (-ENODEV). In that case,
the driver should continue to the next sensor index rather than treating
it as a fatal error.
Fix this by correctly handling -ENODEV and only returning on other
errors. Also add a final check to ensure at least one thermal zone was
registered.
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/cover.1783670011.git.zhoubinbin@loongson.cn?part=2
Fixes: e7e3a7c35791 ("thermal/drivers/loongson-2: Add thermal management support")
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 4d40fc706a53..99b7392fc68f 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -160,16 +160,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
-
if (!IS_ERR(tzd))
break;
- if (PTR_ERR(tzd) != -ENODEV)
+ if (PTR_ERR(tzd) == -ENODEV)
continue;
- return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
+ return dev_err_probe(dev, PTR_ERR(tzd), "failed to register sensor %d\n", i);
}
+ if (IS_ERR(tzd))
+ return dev_err_probe(dev, -ENODEV, "No thermal sensor registered\n");
+
ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
IRQF_ONESHOT, "loongson2_thermal", tzd);
if (ret < 0)
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 2/7] thermal/drivers/loongson2: Fix clamp() usage for thermal trip points
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 3/7] thermal/drivers/loongson2: Fix Loongson-2K2000 trip point programming Binbin Zhou
` (4 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou, stable
clamp() takes the value to clamp as its first argument, followed by the
minimum and maximum bounds. The current code passes the -40 and 125
limits as the value instead, so the trip thresholds are not clamped to the
supported sensor range.
Correct the arguments so that low and high are clamped to [-40, 125].
Cc: stable@vger.kernel.org
Fixes: 734b5def91b5 ("thermal/drivers/loongson2: Add Loongson-2K2000 support")
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 99b7392fc68f..bcabca360157 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -62,10 +62,10 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data,
int low, int high, bool enable)
{
/* Set low temperature threshold */
- loongson2_set_ctrl_regs(data, clamp(-40, low, high), true, enable);
+ loongson2_set_ctrl_regs(data, clamp(low, -40, 125), true, enable);
/* Set high temperature threshold */
- loongson2_set_ctrl_regs(data, clamp(125, low, high), false, enable);
+ loongson2_set_ctrl_regs(data, clamp(high, -40, 125), false, enable);
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 3/7] thermal/drivers/loongson2: Fix Loongson-2K2000 trip point programming
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 2/7] thermal/drivers/loongson2: Fix clamp() usage for thermal trip points Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 4/7] thermal/drivers/loongson2: Use bitfields and per-SoC thermal ops Binbin Zhou
` (3 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou, stable
Loongson-2K2000 uses a different trip point layout than Loongson-2K1000:
the low 8 bits of the gate value are written to the control register,
while the high 8 bits are written to separate HI_GATE_HI/LOW registers.
The gate value is calculated as (temp + 311) * 0x4000 / 820.
Introduce a per-SoC set_trips_regs() callback. Keep the existing
Loongson-2K1000 logic and add the Loongson-2K2000 implementation.
Move the common clamping into loongson2_thermal_set_trips() and pass
Celsius values to the callback.
Cc: stable@vger.kernel.org
Fixes: 734b5def91b5 ("thermal/drivers/loongson2: Add Loongson-2K2000 support")
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 77 ++++++++++++++++++++---------
1 file changed, 55 insertions(+), 22 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index bcabca360157..45fe6100134e 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -29,15 +29,23 @@
LOONGSON2_THSENS_INT_HIGH)
#define LOONGSON2_THSENS_OUT_MASK 0xFF
+/* Loongson-2K2000-Specific Registers */
+#define LS2K2000_THSENS_HI_GATE_HI_REG 0x18
+#define LS2K2000_THSENS_HI_GATE_LOW_REG 0x1c
+
/*
* This flag is used to indicate the temperature reading
* method of the Loongson-2K2000
*/
#define LS2K2000_THSENS_OUT_FLAG BIT(0)
+struct loongson2_thermal_data;
+
struct loongson2_thermal_chip_data {
unsigned int thermal_sensor_sel;
unsigned int flags;
+ void (*set_trips_regs)(struct loongson2_thermal_data *data,
+ int temp, bool low, bool enable);
};
struct loongson2_thermal_data {
@@ -46,30 +54,40 @@ struct loongson2_thermal_data {
const struct loongson2_thermal_chip_data *chip_data;
};
-static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data,
- int ctrl_data, bool low, bool enable)
+static void loongson2_thermal_set_trip_temp(struct loongson2_thermal_data *data,
+ int low, int high, bool enable)
{
- int reg_ctrl = 0;
- int reg_off = data->chip_data->thermal_sensor_sel * 2;
- int ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG;
+ /* Set low temperature threshold */
+ data->chip_data->set_trips_regs(data, low, true, enable);
- reg_ctrl = ctrl_data + HECTO;
- reg_ctrl |= enable ? 0x100 : 0;
- writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off);
+ /* Set high temperature threshold */
+ data->chip_data->set_trips_regs(data, high, false, enable);
}
-static int loongson2_thermal_set(struct loongson2_thermal_data *data,
- int low, int high, bool enable)
+static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
{
- /* Set low temperature threshold */
- loongson2_set_ctrl_regs(data, clamp(low, -40, 125), true, enable);
+ struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
- /* Set high temperature threshold */
- loongson2_set_ctrl_regs(data, clamp(high, -40, 125), false, enable);
+ low = clamp(low, -40000, 125000);
+ high = clamp(high, -40000, 125000);
+
+ loongson2_thermal_set_trip_temp(data, low / MILLI, high / MILLI, true);
return 0;
}
+static void loongson2_2k1000_set_trips_regs(struct loongson2_thermal_data *data,
+ int temp, bool low, bool enable)
+{
+ int reg_ctrl = 0;
+ int reg_off = data->chip_data->thermal_sensor_sel * 2;
+ int ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG;
+
+ reg_ctrl = temp + HECTO;
+ reg_ctrl |= enable ? 0x100 : 0;
+ writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off);
+}
+
static int loongson2_2k1000_get_temp(struct thermal_zone_device *tz, int *temp)
{
int val;
@@ -81,6 +99,26 @@ static int loongson2_2k1000_get_temp(struct thermal_zone_device *tz, int *temp)
return 0;
}
+static void loongson2_2k2000_set_trips_regs(struct loongson2_thermal_data *data,
+ int temp, bool low, bool enable)
+{
+ int hi_reg, ctrl_reg;
+ int val = 0, gate;
+
+ ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG;
+ gate = (temp + 311) * 0x4000 / 820;
+
+ val = gate & 0xff;
+ val |= enable ? 0x100 : 0;
+ writel(val, data->ctrl_reg + ctrl_reg);
+
+ hi_reg = low ? LS2K2000_THSENS_HI_GATE_LOW_REG : LS2K2000_THSENS_HI_GATE_HI_REG;
+
+ val = readl(data->ctrl_reg + hi_reg);
+ val = (val & ~0xff) | ((gate >> 8) & 0xff);
+ writel(val, data->ctrl_reg + hi_reg);
+}
+
static int loongson2_2k2000_get_temp(struct thermal_zone_device *tz, int *temp)
{
int val;
@@ -104,13 +142,6 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
return IRQ_HANDLED;
}
-static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
-{
- struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
-
- return loongson2_thermal_set(data, low/MILLI, high/MILLI, true);
-}
-
static const struct thermal_zone_device_ops loongson2_2k1000_of_thermal_ops = {
.get_temp = loongson2_2k1000_get_temp,
.set_trips = loongson2_thermal_set_trips,
@@ -156,7 +187,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG);
- loongson2_thermal_set(data, 0, 0, false);
+ loongson2_thermal_set_trip_temp(data, 0, 0, false);
for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
@@ -185,11 +216,13 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = {
.thermal_sensor_sel = 0,
.flags = 0,
+ .set_trips_regs = loongson2_2k1000_set_trips_regs,
};
static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = {
.thermal_sensor_sel = 0,
.flags = LS2K2000_THSENS_OUT_FLAG,
+ .set_trips_regs = loongson2_2k2000_set_trips_regs,
};
static const struct of_device_id of_loongson2_thermal_match[] = {
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 4/7] thermal/drivers/loongson2: Use bitfields and per-SoC thermal ops
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (2 preceding siblings ...)
2026-09-28 4:44 ` [PATCH v6 3/7] thermal/drivers/loongson2: Fix Loongson-2K2000 trip point programming Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 5/7] thermal/drivers/loongson2: Move per-SoC ops into chip data Binbin Zhou
` (2 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou
Replace open-coded masks and shifts with GENMASK()/FIELD_* helpers, and
define named constants for the Loongson-2K2000 temperature conversion
and trip gate calculations.
Split the temperature read and thermal zone ops into Loongson-2K1000 and
Loongson-2K2000 variants, and keep the chip-specific trip register
callback in the chip data. This prepares the driver for further SoC
support.
No functional change intended.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 123 ++++++++++++++++------------
1 file changed, 72 insertions(+), 51 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 45fe6100134e..0660a74fd922 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -5,6 +5,7 @@
* Copyright (C) 2022-2023 Loongson Technology Corporation Limited
*/
+#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/minmax.h>
@@ -27,11 +28,23 @@
#define LOONGSON2_THSENS_INT_HIGH BIT(1)
#define LOONGSON2_THSENS_INT_EN (LOONGSON2_THSENS_INT_LO | \
LOONGSON2_THSENS_INT_HIGH)
-#define LOONGSON2_THSENS_OUT_MASK 0xFF
+#define LOONGSON2_THSENS_CTRL_INTEN BIT(8)
+
+#define LOONGSON2_THSENS_OUT_8B_MASK GENMASK(7, 0)
+#define LOONGSON2_THSENS_OUT_16B_MASK GENMASK(15, 0)
+
+#define LOONGSON2_LOWEST_VALID_TEMP (-40000)
+#define LOONGSON2_HIGHEST_VALID_TEMP (125000)
/* Loongson-2K2000-Specific Registers */
#define LS2K2000_THSENS_HI_GATE_HI_REG 0x18
#define LS2K2000_THSENS_HI_GATE_LOW_REG 0x1c
+#define LS2K2000_GATE0_VAL_MASK GENMASK(7, 0)
+#define LS2K2000_THSENS_SEL_MASK GENMASK(11, 10)
+
+#define LS2K2000_TEMP_MUL (820)
+#define LS2K2000_TEMP_DIV (0x4000)
+#define LS2K2000_TEMP_OFFSET (311)
/*
* This flag is used to indicate the temperature reading
@@ -64,71 +77,101 @@ static void loongson2_thermal_set_trip_temp(struct loongson2_thermal_data *data,
data->chip_data->set_trips_regs(data, high, false, enable);
}
-static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
+static int loognson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
{
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
- low = clamp(low, -40000, 125000);
- high = clamp(high, -40000, 125000);
+ low = clamp(low, LOONGSON2_LOWEST_VALID_TEMP, LOONGSON2_HIGHEST_VALID_TEMP);
+ high = clamp(high, LOONGSON2_LOWEST_VALID_TEMP, LOONGSON2_HIGHEST_VALID_TEMP);
loongson2_thermal_set_trip_temp(data, low / MILLI, high / MILLI, true);
return 0;
}
-static void loongson2_2k1000_set_trips_regs(struct loongson2_thermal_data *data,
+static int ls2k1000_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
+ int val;
+
+ val = FIELD_GET(LOONGSON2_THSENS_OUT_8B_MASK,
+ readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG));
+ *temp = (val - HECTO) * KILO;
+
+ return 0;
+}
+
+static void ls2k1000_thermal_set_trips_regs(struct loongson2_thermal_data *data,
int temp, bool low, bool enable)
{
- int reg_ctrl = 0;
- int reg_off = data->chip_data->thermal_sensor_sel * 2;
int ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG;
+ int reg_off = data->chip_data->thermal_sensor_sel * 2;
+ int reg_ctrl = 0;
reg_ctrl = temp + HECTO;
- reg_ctrl |= enable ? 0x100 : 0;
+ if (enable)
+ reg_ctrl |= LOONGSON2_THSENS_CTRL_INTEN;
+
writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off);
}
-static int loongson2_2k1000_get_temp(struct thermal_zone_device *tz, int *temp)
+static int ls2k2000_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
- int val;
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
+ int val;
- val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG);
- *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO;
+ val = FIELD_GET(LOONGSON2_THSENS_OUT_16B_MASK, readl(data->temp_reg));
+ *temp = (val * LS2K2000_TEMP_MUL / LS2K2000_TEMP_DIV - LS2K2000_TEMP_OFFSET) * KILO;
return 0;
}
-static void loongson2_2k2000_set_trips_regs(struct loongson2_thermal_data *data,
+static void ls2k2000_thermal_set_trips_regs(struct loongson2_thermal_data *data,
int temp, bool low, bool enable)
{
int hi_reg, ctrl_reg;
int val = 0, gate;
ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG;
- gate = (temp + 311) * 0x4000 / 820;
+ gate = (temp + LS2K2000_TEMP_OFFSET) * LS2K2000_TEMP_DIV / LS2K2000_TEMP_MUL;
+
+ val = FIELD_PREP(LS2K2000_GATE0_VAL_MASK, FIELD_GET(GENMASK(7, 0), gate)) |
+ FIELD_PREP(LS2K2000_THSENS_SEL_MASK, 0);
+ if (enable)
+ val |= LOONGSON2_THSENS_CTRL_INTEN;
- val = gate & 0xff;
- val |= enable ? 0x100 : 0;
writel(val, data->ctrl_reg + ctrl_reg);
hi_reg = low ? LS2K2000_THSENS_HI_GATE_LOW_REG : LS2K2000_THSENS_HI_GATE_HI_REG;
val = readl(data->ctrl_reg + hi_reg);
- val = (val & ~0xff) | ((gate >> 8) & 0xff);
+ val &= ~LS2K2000_GATE0_VAL_MASK;
+ val |= FIELD_PREP(LS2K2000_GATE0_VAL_MASK, FIELD_GET(GENMASK(15, 8), gate));
+
writel(val, data->ctrl_reg + hi_reg);
}
-static int loongson2_2k2000_get_temp(struct thermal_zone_device *tz, int *temp)
-{
- int val;
- struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
+static const struct thermal_zone_device_ops ls2k1000_thermal_zone_ops = {
+ .get_temp = ls2k1000_thermal_get_temp,
+ .set_trips = loognson2_thermal_set_trips,
+};
- val = readl(data->temp_reg);
- *temp = ((val & 0xffff) * 820 / 0x4000 - 311) * KILO;
+static const struct thermal_zone_device_ops ls2k2000_thermal_zone_ops = {
+ .get_temp = ls2k2000_thermal_get_temp,
+ .set_trips = loognson2_thermal_set_trips,
+};
- return 0;
-}
+static const struct loongson2_thermal_chip_data ls2k1000_thermal_chip_data = {
+ .thermal_sensor_sel = 0,
+ .flags = 0,
+ .set_trips_regs = ls2k1000_thermal_set_trips_regs,
+};
+
+static const struct loongson2_thermal_chip_data ls2k2000_thermal_chip_data = {
+ .thermal_sensor_sel = 0,
+ .flags = LS2K2000_THSENS_OUT_FLAG,
+ .set_trips_regs = ls2k2000_thermal_set_trips_regs,
+};
static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
{
@@ -142,16 +185,6 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
return IRQ_HANDLED;
}
-static const struct thermal_zone_device_ops loongson2_2k1000_of_thermal_ops = {
- .get_temp = loongson2_2k1000_get_temp,
- .set_trips = loongson2_thermal_set_trips,
-};
-
-static const struct thermal_zone_device_ops loongson2_2k2000_of_thermal_ops = {
- .get_temp = loongson2_2k2000_get_temp,
- .set_trips = loongson2_thermal_set_trips,
-};
-
static int loongson2_thermal_probe(struct platform_device *pdev)
{
const struct thermal_zone_device_ops *thermal_ops;
@@ -176,9 +209,9 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
if (IS_ERR(data->temp_reg))
return PTR_ERR(data->temp_reg);
- thermal_ops = &loongson2_2k2000_of_thermal_ops;
+ thermal_ops = &ls2k2000_thermal_zone_ops;
} else {
- thermal_ops = &loongson2_2k1000_of_thermal_ops;
+ thermal_ops = &ls2k1000_thermal_zone_ops;
}
irq = platform_get_irq(pdev, 0);
@@ -213,26 +246,14 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
return 0;
}
-static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = {
- .thermal_sensor_sel = 0,
- .flags = 0,
- .set_trips_regs = loongson2_2k1000_set_trips_regs,
-};
-
-static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = {
- .thermal_sensor_sel = 0,
- .flags = LS2K2000_THSENS_OUT_FLAG,
- .set_trips_regs = loongson2_2k2000_set_trips_regs,
-};
-
static const struct of_device_id of_loongson2_thermal_match[] = {
{
.compatible = "loongson,ls2k1000-thermal",
- .data = &loongson2_thermal_ls2k1000_data,
+ .data = &ls2k1000_thermal_chip_data,
},
{
.compatible = "loongson,ls2k2000-thermal",
- .data = &loongson2_thermal_ls2k2000_data,
+ .data = &ls2k2000_thermal_chip_data,
},
{ /* end */ }
};
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 5/7] thermal/drivers/loongson2: Move per-SoC ops into chip data
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (3 preceding siblings ...)
2026-09-28 4:44 ` [PATCH v6 4/7] thermal/drivers/loongson2: Use bitfields and per-SoC thermal ops Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 6/7] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 7/7] thermal/drivers/loongson2: Add Loongson-2K0300 support Binbin Zhou
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou
Store the thermal_zone_device_ops pointer and the optional extended
resource initializer in struct loongson2_thermal_chip_data instead of
selecting them through flags in probe.
Rename the second mapped resource from temp_reg to extend_reg, and let
Loongson-2K2000 initialize it from its own init_extend_resource()
callback. This makes adding new SoCs with different register layouts
easier.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 50 ++++++++++++++++-------------
1 file changed, 27 insertions(+), 23 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 0660a74fd922..17aa1d80a2e6 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -46,24 +46,20 @@
#define LS2K2000_TEMP_DIV (0x4000)
#define LS2K2000_TEMP_OFFSET (311)
-/*
- * This flag is used to indicate the temperature reading
- * method of the Loongson-2K2000
- */
-#define LS2K2000_THSENS_OUT_FLAG BIT(0)
-
struct loongson2_thermal_data;
struct loongson2_thermal_chip_data {
unsigned int thermal_sensor_sel;
- unsigned int flags;
+ const struct thermal_zone_device_ops *thermal_ops;
void (*set_trips_regs)(struct loongson2_thermal_data *data,
int temp, bool low, bool enable);
+ int (*init_extend_resource)(struct platform_device *pdev,
+ struct loongson2_thermal_data *data);
};
struct loongson2_thermal_data {
void __iomem *ctrl_reg;
- void __iomem *temp_reg;
+ void __iomem *extend_reg;
const struct loongson2_thermal_chip_data *chip_data;
};
@@ -120,7 +116,7 @@ static int ls2k2000_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
int val;
- val = FIELD_GET(LOONGSON2_THSENS_OUT_16B_MASK, readl(data->temp_reg));
+ val = FIELD_GET(LOONGSON2_THSENS_OUT_16B_MASK, readl(data->extend_reg));
*temp = (val * LS2K2000_TEMP_MUL / LS2K2000_TEMP_DIV - LS2K2000_TEMP_OFFSET) * KILO;
return 0;
@@ -151,6 +147,17 @@ static void ls2k2000_thermal_set_trips_regs(struct loongson2_thermal_data *data,
writel(val, data->ctrl_reg + hi_reg);
}
+static int ls2k2000_thermal_init_extend_resource(struct platform_device *pdev,
+ struct loongson2_thermal_data *data)
+{
+ /* The temperature output register is separate for Loongson-2K2000 */
+ data->extend_reg = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(data->extend_reg))
+ return PTR_ERR(data->extend_reg);
+
+ return 0;
+}
+
static const struct thermal_zone_device_ops ls2k1000_thermal_zone_ops = {
.get_temp = ls2k1000_thermal_get_temp,
.set_trips = loognson2_thermal_set_trips,
@@ -163,14 +170,15 @@ static const struct thermal_zone_device_ops ls2k2000_thermal_zone_ops = {
static const struct loongson2_thermal_chip_data ls2k1000_thermal_chip_data = {
.thermal_sensor_sel = 0,
- .flags = 0,
+ .thermal_ops = &ls2k1000_thermal_zone_ops,
.set_trips_regs = ls2k1000_thermal_set_trips_regs,
};
static const struct loongson2_thermal_chip_data ls2k2000_thermal_chip_data = {
.thermal_sensor_sel = 0,
- .flags = LS2K2000_THSENS_OUT_FLAG,
+ .thermal_ops = &ls2k2000_thermal_zone_ops,
.set_trips_regs = ls2k2000_thermal_set_trips_regs,
+ .init_extend_resource = ls2k2000_thermal_init_extend_resource,
};
static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
@@ -187,9 +195,8 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
static int loongson2_thermal_probe(struct platform_device *pdev)
{
- const struct thermal_zone_device_ops *thermal_ops;
- struct device *dev = &pdev->dev;
struct loongson2_thermal_data *data;
+ struct device *dev = &pdev->dev;
struct thermal_zone_device *tzd;
int ret, irq, i;
@@ -198,20 +205,17 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
return -ENOMEM;
data->chip_data = device_get_match_data(dev);
+ if (!data->chip_data)
+ return -EINVAL;
data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->ctrl_reg))
return PTR_ERR(data->ctrl_reg);
- /* The temperature output register is separate for Loongson-2K2000 */
- if (data->chip_data->flags & LS2K2000_THSENS_OUT_FLAG) {
- data->temp_reg = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(data->temp_reg))
- return PTR_ERR(data->temp_reg);
-
- thermal_ops = &ls2k2000_thermal_zone_ops;
- } else {
- thermal_ops = &ls2k1000_thermal_zone_ops;
+ if (data->chip_data->init_extend_resource) {
+ ret = data->chip_data->init_extend_resource(pdev, data);
+ if (ret)
+ return ret;
}
irq = platform_get_irq(pdev, 0);
@@ -223,7 +227,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
loongson2_thermal_set_trip_temp(data, 0, 0, false);
for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
- tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
+ tzd = devm_thermal_of_zone_register(dev, i, data, data->chip_data->thermal_ops);
if (!IS_ERR(tzd))
break;
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 6/7] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (4 preceding siblings ...)
2026-09-28 4:44 ` [PATCH v6 5/7] thermal/drivers/loongson2: Move per-SoC ops into chip data Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 7/7] thermal/drivers/loongson2: Add Loongson-2K0300 support Binbin Zhou
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou, Conor Dooley
Add a new compatible string `loongson,ls2k0300-thermal` for the thermal
sensor found on the Loongson-2K0300 SoC.
The hardware differs from existing SoCs in that it requires a phandle to
a syscon node that provides the CHIP ID register, used as a compensation
source in the temperature calculation.
Update the binding to make `loongson,chipid` required for this new
compatible, and clarify the register region requirements for each
variant.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../thermal/loongson,ls2k-thermal.yaml | 73 ++++++++++++++-----
1 file changed, 55 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
index 79e691b08341..d312e27737a2 100644
--- a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
@@ -10,13 +10,11 @@ maintainers:
- zhanghongchen <zhanghongchen@loongson.cn>
- Yinbo Zhu <zhuyinbo@loongson.cn>
-allOf:
- - $ref: /schemas/thermal/thermal-sensor.yaml#
-
properties:
compatible:
oneOf:
- enum:
+ - loongson,ls2k0300-thermal
- loongson,ls2k1000-thermal
- loongson,ls2k2000-thermal
- items:
@@ -34,28 +32,56 @@ properties:
'#thermal-sensor-cells':
const: 1
+ loongson,chipid:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon with the Loongson-2K0300 CHIP ID.
+
required:
- compatible
- reg
- interrupts
-if:
- properties:
- compatible:
- contains:
- enum:
- - loongson,ls2k2000-thermal
+allOf:
+ - $ref: /schemas/thermal/thermal-sensor.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: loongson,ls2k0300-thermal
+ then:
+ properties:
+ reg:
+ items:
+ - description: Thermal base register region
+ required:
+ - loongson,chipid
-then:
- properties:
- reg:
- minItems: 2
- maxItems: 2
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: loongson,ls2k1000-thermal
+ then:
+ properties:
+ loongson,chipid: false
+ reg:
+ items:
+ - description: Thermal base register region
-else:
- properties:
- reg:
- maxItems: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: loongson,ls2k2000-thermal
+ then:
+ properties:
+ loongson,chipid: false
+ reg:
+ items:
+ - description: Thermal base register region
+ - description: Thermal data output register region
unevaluatedProperties: false
@@ -69,3 +95,14 @@ examples:
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
#thermal-sensor-cells = <1>;
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ thermal-sensor@16001500 {
+ compatible = "loongson,ls2k0300-thermal";
+ reg = <0x16001500 0x30>;
+ interrupt-parent = <&liointc1>;
+ interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+ loongson,chipid = <&chipid>;
+ #thermal-sensor-cells = <1>;
+ };
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 7/7] thermal/drivers/loongson2: Add Loongson-2K0300 support
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (5 preceding siblings ...)
2026-09-28 4:44 ` [PATCH v6 6/7] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
@ 2026-09-28 4:44 ` Binbin Zhou
6 siblings, 0 replies; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 4:44 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm,
Binbin Zhou
The Loongson-2K0300 sensor provides an 11-bit output and requires
calibration data from the CHIP ID registers. Read the calibration offset
throughthe `loongson,chipid` syscon phandle, initialize the sensor
configuration register, and calculate the temperature with the
calibrated slope and offset.
Early Loongson-2K0300 fuse revisions may provide unusable calibration
data. If the calibrated formula reports a temperature outside the valid
sensor range, fall back to the old-fuse slope with a zero calibration
offset.
The set_trips callback of Loongson-2K0300 will be added in the future.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 136 ++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 17aa1d80a2e6..a53d70b824f3 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -8,10 +8,12 @@
#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/mfd/syscon.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
+#include <linux/regmap.h>
#include <linux/thermal.h>
#include <linux/units.h>
@@ -31,11 +33,37 @@
#define LOONGSON2_THSENS_CTRL_INTEN BIT(8)
#define LOONGSON2_THSENS_OUT_8B_MASK GENMASK(7, 0)
+#define LOONGSON2_THSENS_OUT_11B_MASK GENMASK(10, 0)
#define LOONGSON2_THSENS_OUT_16B_MASK GENMASK(15, 0)
#define LOONGSON2_LOWEST_VALID_TEMP (-40000)
#define LOONGSON2_HIGHEST_VALID_TEMP (125000)
+/* Loongson-2K0300-Specific Registers */
+#define LS2K0300_CHIP_ID0 0x10
+#define LS2K0300_CHIP_ID1 0x14
+
+#define LS2K0300_THSENS_CFG_REG 0x18
+#define LS2K0300_THSENS_INIT_MASK 0xff03
+
+#define LS2K0300_EXTERN_ID BIT(4)
+#define LS2K0300_ID0_VAL_MASK GENMASK(31, 20)
+#define LS2K0300_ID1_VAL_MASK GENMASK(15, 0)
+
+#define LS2K0300_COMP_VAL_MASK GENMASK(14, 0)
+#define LS2K0300_COMP_SIGN_BIT BIT(15)
+
+#define LS2K0300_TEMP_SLOPE (570) /* m°C/LSB, calibrated */
+#define LS2K0300_TEMP_SLOPE_OLD (569) /* m°C/LSB, old fuse */
+#define LS2K0300_TEMP_OFFSET (394700) /* m°C */
+
+/*
+ * Set when the on-chip calibration data is unusable (early 2K0300
+ * fuse revision). The driver then uses LS2K0300_TEMP_SLOPE_OLD with
+ * calib_offset = 0 instead of the calibrated formula.
+ */
+#define LS2K0300_OLD_FUSE_FLAG BIT(0)
+
/* Loongson-2K2000-Specific Registers */
#define LS2K2000_THSENS_HI_GATE_HI_REG 0x18
#define LS2K2000_THSENS_HI_GATE_LOW_REG 0x1c
@@ -60,12 +88,18 @@ struct loongson2_thermal_chip_data {
struct loongson2_thermal_data {
void __iomem *ctrl_reg;
void __iomem *extend_reg;
+ struct regmap *regmap_cfg;
+ unsigned int flags;
+ int calib_offset;
const struct loongson2_thermal_chip_data *chip_data;
};
static void loongson2_thermal_set_trip_temp(struct loongson2_thermal_data *data,
int low, int high, bool enable)
{
+ if (!data->chip_data->set_trips_regs)
+ return;
+
/* Set low temperature threshold */
data->chip_data->set_trips_regs(data, low, true, enable);
@@ -85,6 +119,94 @@ static int loognson2_thermal_set_trips(struct thermal_zone_device *tz, int low,
return 0;
}
+static int ls2k0300_adc_to_temp_mc(struct loongson2_thermal_data *data, int slope)
+{
+ int raw_adc;
+
+ raw_adc = FIELD_GET(LOONGSON2_THSENS_OUT_11B_MASK,
+ readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG));
+
+ return (raw_adc + data->calib_offset) * slope - LS2K0300_TEMP_OFFSET;
+}
+
+static int ls2k0300_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
+ int slope = LS2K0300_TEMP_SLOPE;
+
+ if (data->flags & LS2K0300_OLD_FUSE_FLAG)
+ slope = LS2K0300_TEMP_SLOPE_OLD;
+
+ *temp = ls2k0300_adc_to_temp_mc(data, slope);
+
+ return 0;
+}
+
+static void ls2k0300_thermal_detect_old_fuse(struct device *dev,
+ struct loongson2_thermal_data *data)
+{
+ int temp;
+
+ temp = ls2k0300_adc_to_temp_mc(data, LS2K0300_TEMP_SLOPE);
+
+ if (temp < LOONGSON2_LOWEST_VALID_TEMP ||
+ temp > LOONGSON2_HIGHEST_VALID_TEMP) {
+ dev_warn(dev, "calibrated temperature %d m°C out of range [%d, %d], using old fuse formula\n",
+ temp, LOONGSON2_LOWEST_VALID_TEMP, LOONGSON2_HIGHEST_VALID_TEMP);
+ data->flags = LS2K0300_OLD_FUSE_FLAG;
+ data->calib_offset = 0;
+ }
+}
+
+static int ls2k0300_thermal_read_calib(struct loongson2_thermal_data *data)
+{
+ u32 chip_id0, chip_id1;
+ int calib_data, calib_offset, ret;
+
+ ret = regmap_read(data->regmap_cfg, LS2K0300_CHIP_ID0, &chip_id0);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(data->regmap_cfg, LS2K0300_CHIP_ID1, &chip_id1);
+ if (ret)
+ return ret;
+
+ if (chip_id0 & LS2K0300_EXTERN_ID) {
+ calib_data = FIELD_GET(LS2K0300_ID1_VAL_MASK, chip_id1);
+ calib_offset = FIELD_GET(LS2K0300_COMP_VAL_MASK, calib_data);
+ if (calib_data & LS2K0300_COMP_SIGN_BIT)
+ calib_offset = -calib_offset;
+ } else {
+ calib_data = FIELD_GET(LS2K0300_ID0_VAL_MASK, chip_id0);
+ calib_offset = FIELD_GET(LS2K0300_COMP_VAL_MASK, calib_data);
+ }
+
+ data->calib_offset = calib_offset;
+ return 0;
+}
+
+static int ls2k0300_thermal_init_extend_resource(struct platform_device *pdev,
+ struct loongson2_thermal_data *data)
+{
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ data->regmap_cfg =
+ syscon_regmap_lookup_by_phandle(dev->of_node, "loongson,chipid");
+ if (IS_ERR(data->regmap_cfg))
+ return PTR_ERR(data->regmap_cfg);
+
+ ret = ls2k0300_thermal_read_calib(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to read calibration data\n");
+
+ writel(LS2K0300_THSENS_INIT_MASK, data->ctrl_reg + LS2K0300_THSENS_CFG_REG);
+
+ ls2k0300_thermal_detect_old_fuse(dev, data);
+
+ return 0;
+}
+
static int ls2k1000_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
@@ -158,6 +280,10 @@ static int ls2k2000_thermal_init_extend_resource(struct platform_device *pdev,
return 0;
}
+static const struct thermal_zone_device_ops ls2k0300_thermal_zone_ops = {
+ .get_temp = ls2k0300_thermal_get_temp,
+};
+
static const struct thermal_zone_device_ops ls2k1000_thermal_zone_ops = {
.get_temp = ls2k1000_thermal_get_temp,
.set_trips = loognson2_thermal_set_trips,
@@ -168,6 +294,12 @@ static const struct thermal_zone_device_ops ls2k2000_thermal_zone_ops = {
.set_trips = loognson2_thermal_set_trips,
};
+static const struct loongson2_thermal_chip_data ls2k0300_thermal_chip_data = {
+ .thermal_sensor_sel = 0,
+ .thermal_ops = &ls2k0300_thermal_zone_ops,
+ .init_extend_resource = ls2k0300_thermal_init_extend_resource,
+};
+
static const struct loongson2_thermal_chip_data ls2k1000_thermal_chip_data = {
.thermal_sensor_sel = 0,
.thermal_ops = &ls2k1000_thermal_zone_ops,
@@ -251,6 +383,10 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
}
static const struct of_device_id of_loongson2_thermal_match[] = {
+ {
+ .compatible = "loongson,ls2k0300-thermal",
+ .data = &ls2k0300_thermal_chip_data,
+ },
{
.compatible = "loongson,ls2k1000-thermal",
.data = &ls2k1000_thermal_chip_data,
--
2.52.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-28 4:44 ` [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
@ 2026-09-28 7:15 ` Daniel Lezcano
2026-09-28 8:17 ` Binbin Zhou
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Lezcano @ 2026-09-28 7:15 UTC (permalink / raw)
To: Binbin Zhou, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-pm, stable,
Sashiko
On 9/28/26 06:44, Binbin Zhou wrote:
> The registration loop in loongson2_thermal_probe() incorrectly uses
> dev_err_probe() when the sensor is not present (-ENODEV). In that case,
> the driver should continue to the next sensor index rather than treating
> it as a fatal error.
>
> Fix this by correctly handling -ENODEV and only returning on other
> errors. Also add a final check to ensure at least one thermal zone was
> registered.
>
> Cc: stable@vger.kernel.org
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/cover.1783670011.git.zhoubinbin@loongson.cn?part=2
> Fixes: e7e3a7c35791 ("thermal/drivers/loongson-2: Add thermal management support")
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> drivers/thermal/loongson2_thermal.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> index 4d40fc706a53..99b7392fc68f 100644
> --- a/drivers/thermal/loongson2_thermal.c
> +++ b/drivers/thermal/loongson2_thermal.c
> @@ -160,16 +160,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
>
> for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
> -
> if (!IS_ERR(tzd))
> break;
>
> - if (PTR_ERR(tzd) != -ENODEV)
> + if (PTR_ERR(tzd) == -ENODEV)
> continue;
>
> - return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
> + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register sensor %d\n", i);
> }
>
> + if (IS_ERR(tzd))
> + return dev_err_probe(dev, -ENODEV, "No thermal sensor registered\n");
> +
> ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
> IRQF_ONESHOT, "loongson2_thermal", tzd);
> if (ret < 0)
The [no]error paths are confusing and prone to error, eg: 'if there is
no error then check if there is an error', 'when exiting the loop
without registering any sensor, then we assume tzd is -ENODEV'.
Please make a less cumbersome and implicit checks here. For example
count the number of sensors and then do the check against.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-28 7:15 ` Daniel Lezcano
@ 2026-09-28 8:17 ` Binbin Zhou
2026-09-28 13:23 ` Daniel Lezcano
0 siblings, 1 reply; 15+ messages in thread
From: Binbin Zhou @ 2026-09-28 8:17 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
Hi Daniel:
Thanks for your review.
On Mon, Sep 28, 2026 at 3:15 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
> On 9/28/26 06:44, Binbin Zhou wrote:
> > The registration loop in loongson2_thermal_probe() incorrectly uses
> > dev_err_probe() when the sensor is not present (-ENODEV). In that case,
> > the driver should continue to the next sensor index rather than treating
> > it as a fatal error.
> >
> > Fix this by correctly handling -ENODEV and only returning on other
> > errors. Also add a final check to ensure at least one thermal zone was
> > registered.
> >
> > Cc: stable@vger.kernel.org
> > Reported-by: Sashiko <sashiko-bot@kernel.org>
> > Closes: https://sashiko.dev/#/patchset/cover.1783670011.git.zhoubinbin@loongson.cn?part=2
> > Fixes: e7e3a7c35791 ("thermal/drivers/loongson-2: Add thermal management support")
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > drivers/thermal/loongson2_thermal.c | 8 +++++---
> > 1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> > index 4d40fc706a53..99b7392fc68f 100644
> > --- a/drivers/thermal/loongson2_thermal.c
> > +++ b/drivers/thermal/loongson2_thermal.c
> > @@ -160,16 +160,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
> >
> > for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> > tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
> > -
> > if (!IS_ERR(tzd))
> > break;
> >
> > - if (PTR_ERR(tzd) != -ENODEV)
> > + if (PTR_ERR(tzd) == -ENODEV)
> > continue;
> >
> > - return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
> > + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register sensor %d\n", i);
>
>
> > }
> >
> > + if (IS_ERR(tzd))
> > + return dev_err_probe(dev, -ENODEV, "No thermal sensor registered\n");
> > +
> > ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
> > IRQF_ONESHOT, "loongson2_thermal", tzd);
> > if (ret < 0)
>
>
> The [no]error paths are confusing and prone to error, eg: 'if there is
> no error then check if there is an error', 'when exiting the loop
> without registering any sensor, then we assume tzd is -ENODEV'.
>
> Please make a less cumbersome and implicit checks here. For example
> count the number of sensors and then do the check against.
I thought about it, and you're right—I made the logic here too complicated.
Let's use `sensor_count` as the counter. Is the following check logic clearer?
u32 sensor_count = 0;
for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
tzd = devm_thermal_of_zone_register(dev, i, data,
data->chip_data->thermal_ops);
if (IS_ERR(tzd)) {
if (PTR_ERR(tzd) == -ENODEV)
continue;
return dev_err_probe(dev, PTR_ERR(tzd),
"failed to register sensor %d", i);
}
sensor_count++;
break;
}
if (!sensor_count)
return dev_err_probe(dev, -ENODEV, "no thermal sensor
registered");
--
Thanks.
Binbin
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-28 8:17 ` Binbin Zhou
@ 2026-09-28 13:23 ` Daniel Lezcano
2026-09-29 3:06 ` Binbin Zhou
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Lezcano @ 2026-09-28 13:23 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
On 9/28/26 10:17, Binbin Zhou wrote:
> Hi Daniel:
>
> Thanks for your review.
>
> On Mon, Sep 28, 2026 at 3:15 PM Daniel Lezcano
> <daniel.lezcano@oss.qualcomm.com> wrote:
>>
>> On 9/28/26 06:44, Binbin Zhou wrote:
>>> The registration loop in loongson2_thermal_probe() incorrectly uses
>>> dev_err_probe() when the sensor is not present (-ENODEV). In that case,
>>> the driver should continue to the next sensor index rather than treating
>>> it as a fatal error.
>>>
>>> Fix this by correctly handling -ENODEV and only returning on other
>>> errors. Also add a final check to ensure at least one thermal zone was
>>> registered.
>>>
>>> Cc: stable@vger.kernel.org
>>> Reported-by: Sashiko <sashiko-bot@kernel.org>
>>> Closes: https://sashiko.dev/#/patchset/cover.1783670011.git.zhoubinbin@loongson.cn?part=2
>>> Fixes: e7e3a7c35791 ("thermal/drivers/loongson-2: Add thermal management support")
>>> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
>>> ---
>>> drivers/thermal/loongson2_thermal.c | 8 +++++---
>>> 1 file changed, 5 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
>>> index 4d40fc706a53..99b7392fc68f 100644
>>> --- a/drivers/thermal/loongson2_thermal.c
>>> +++ b/drivers/thermal/loongson2_thermal.c
>>> @@ -160,16 +160,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
>>>
>>> for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
>>> tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
>>> -
>>> if (!IS_ERR(tzd))
>>> break;
>>>
>>> - if (PTR_ERR(tzd) != -ENODEV)
>>> + if (PTR_ERR(tzd) == -ENODEV)
>>> continue;
>>>
>>> - return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
>>> + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register sensor %d\n", i);
>>
>>
>>> }
>>>
>>> + if (IS_ERR(tzd))
>>> + return dev_err_probe(dev, -ENODEV, "No thermal sensor registered\n");
>>> +
>>> ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
>>> IRQF_ONESHOT, "loongson2_thermal", tzd);
>>> if (ret < 0)
>>
>>
>> The [no]error paths are confusing and prone to error, eg: 'if there is
>> no error then check if there is an error', 'when exiting the loop
>> without registering any sensor, then we assume tzd is -ENODEV'.
>>
>> Please make a less cumbersome and implicit checks here. For example
>> count the number of sensors and then do the check against.
>
> I thought about it, and you're right—I made the logic here too complicated.
> Let's use `sensor_count` as the counter. Is the following check logic clearer?
>
> u32 sensor_count = 0;
>
> for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> tzd = devm_thermal_of_zone_register(dev, i, data,
> data->chip_data->thermal_ops);
> if (IS_ERR(tzd)) {
> if (PTR_ERR(tzd) == -ENODEV)
> continue;
>
> return dev_err_probe(dev, PTR_ERR(tzd),
> "failed to register sensor %d", i);
> }
>
> sensor_count++;
If I'm not mistaken in the previous version, the loop exits at the first
registered sensor
if (!IS_ERR(tzd))
break;
Here all the available sensors are registered
> break;
> }
>
> if (!sensor_count)
> return dev_err_probe(dev, -ENODEV, "no thermal sensor
> registered");
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-28 13:23 ` Daniel Lezcano
@ 2026-09-29 3:06 ` Binbin Zhou
2026-09-29 5:46 ` Daniel Lezcano
0 siblings, 1 reply; 15+ messages in thread
From: Binbin Zhou @ 2026-09-29 3:06 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
Hi Daniel:
On Mon, Sep 28, 2026 at 9:23 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
> On 9/28/26 10:17, Binbin Zhou wrote:
> > Hi Daniel:
> >
> > Thanks for your review.
> >
> > On Mon, Sep 28, 2026 at 3:15 PM Daniel Lezcano
> > <daniel.lezcano@oss.qualcomm.com> wrote:
> >>
> >> On 9/28/26 06:44, Binbin Zhou wrote:
> >>> The registration loop in loongson2_thermal_probe() incorrectly uses
> >>> dev_err_probe() when the sensor is not present (-ENODEV). In that case,
> >>> the driver should continue to the next sensor index rather than treating
> >>> it as a fatal error.
> >>>
> >>> Fix this by correctly handling -ENODEV and only returning on other
> >>> errors. Also add a final check to ensure at least one thermal zone was
> >>> registered.
> >>>
> >>> Cc: stable@vger.kernel.org
> >>> Reported-by: Sashiko <sashiko-bot@kernel.org>
> >>> Closes: https://sashiko.dev/#/patchset/cover.1783670011.git.zhoubinbin@loongson.cn?part=2
> >>> Fixes: e7e3a7c35791 ("thermal/drivers/loongson-2: Add thermal management support")
> >>> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> >>> ---
> >>> drivers/thermal/loongson2_thermal.c | 8 +++++---
> >>> 1 file changed, 5 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> >>> index 4d40fc706a53..99b7392fc68f 100644
> >>> --- a/drivers/thermal/loongson2_thermal.c
> >>> +++ b/drivers/thermal/loongson2_thermal.c
> >>> @@ -160,16 +160,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
> >>>
> >>> for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> >>> tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
> >>> -
> >>> if (!IS_ERR(tzd))
> >>> break;
> >>>
> >>> - if (PTR_ERR(tzd) != -ENODEV)
> >>> + if (PTR_ERR(tzd) == -ENODEV)
> >>> continue;
> >>>
> >>> - return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
> >>> + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register sensor %d\n", i);
> >>
> >>
> >>> }
> >>>
> >>> + if (IS_ERR(tzd))
> >>> + return dev_err_probe(dev, -ENODEV, "No thermal sensor registered\n");
> >>> +
> >>> ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
> >>> IRQF_ONESHOT, "loongson2_thermal", tzd);
> >>> if (ret < 0)
> >>
> >>
> >> The [no]error paths are confusing and prone to error, eg: 'if there is
> >> no error then check if there is an error', 'when exiting the loop
> >> without registering any sensor, then we assume tzd is -ENODEV'.
> >>
> >> Please make a less cumbersome and implicit checks here. For example
> >> count the number of sensors and then do the check against.
> >
> > I thought about it, and you're right—I made the logic here too complicated.
> > Let's use `sensor_count` as the counter. Is the following check logic clearer?
> >
> > u32 sensor_count = 0;
> >
> > for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> > tzd = devm_thermal_of_zone_register(dev, i, data,
> > data->chip_data->thermal_ops);
> > if (IS_ERR(tzd)) {
> > if (PTR_ERR(tzd) == -ENODEV)
> > continue;
> >
> > return dev_err_probe(dev, PTR_ERR(tzd),
> > "failed to register sensor %d", i);
> > }
> >
> > sensor_count++;
>
> If I'm not mistaken in the previous version, the loop exits at the first
> registered sensor
>
> if (!IS_ERR(tzd))
> break;
>
> Here all the available sensors are registered
The name `sensor_count` might be a bit misleading, but here the loop
exits after the first success:
sensor_count++;
break;
Let’s rename it:
bool registered = false;
...
for (...) {
tzd = devm_thermal_of_zone_register(...);
if (IS_ERR(tzd)) {
if (PTR_ERR(tzd) == -ENODEV)
continue;
return dev_err_probe(dev, PTR_ERR(tzd),
"failed to register sensor %d", i);
}
registered = true;
break;
}
if (!registered)
return dev_err_probe(dev, -ENODEV, "no thermal sensor registered");
>
> > break;
> > }
> >
> > if (!sensor_count)
> > return dev_err_probe(dev, -ENODEV, "no thermal sensor
> > registered");
> >
> >
>
--
Thanks.
Binbin
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-29 3:06 ` Binbin Zhou
@ 2026-09-29 5:46 ` Daniel Lezcano
2026-09-29 8:23 ` Binbin Zhou
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Lezcano @ 2026-09-29 5:46 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
On 9/29/26 05:06, Binbin Zhou wrote:
> Hi Daniel:
[ ... ]
>>>> Please make a less cumbersome and implicit checks here. For example
>>>> count the number of sensors and then do the check against.
>>>
>>> I thought about it, and you're right—I made the logic here too complicated.
>>> Let's use `sensor_count` as the counter. Is the following check logic clearer?
>>>
>>> u32 sensor_count = 0;
>>>
>>> for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
>>> tzd = devm_thermal_of_zone_register(dev, i, data,
>>> data->chip_data->thermal_ops);
>>> if (IS_ERR(tzd)) {
>>> if (PTR_ERR(tzd) == -ENODEV)
>>> continue;
>>>
>>> return dev_err_probe(dev, PTR_ERR(tzd),
>>> "failed to register sensor %d", i);
>>> }
>>>
>>> sensor_count++;
>>
>> If I'm not mistaken in the previous version, the loop exits at the first
>> registered sensor
>>
>> if (!IS_ERR(tzd))
>> break;
>>
>> Here all the available sensors are registered
>
> The name `sensor_count` might be a bit misleading, but here the loop
> exits after the first success:
>
> sensor_count++;
> break;
>
> Let’s rename it:
Can you clarify why only the first sensor found stops the thermal zones
registration ?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-29 5:46 ` Daniel Lezcano
@ 2026-09-29 8:23 ` Binbin Zhou
2026-09-29 8:43 ` Daniel Lezcano
0 siblings, 1 reply; 15+ messages in thread
From: Binbin Zhou @ 2026-09-29 8:23 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
Hi Daniel:
On Tue, Sep 29, 2026 at 1:46 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
> On 9/29/26 05:06, Binbin Zhou wrote:
> > Hi Daniel:
>
> [ ... ]
>
> >>>> Please make a less cumbersome and implicit checks here. For example
> >>>> count the number of sensors and then do the check against.
> >>>
> >>> I thought about it, and you're right—I made the logic here too complicated.
> >>> Let's use `sensor_count` as the counter. Is the following check logic clearer?
> >>>
> >>> u32 sensor_count = 0;
> >>>
> >>> for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> >>> tzd = devm_thermal_of_zone_register(dev, i, data,
> >>> data->chip_data->thermal_ops);
> >>> if (IS_ERR(tzd)) {
> >>> if (PTR_ERR(tzd) == -ENODEV)
> >>> continue;
> >>>
> >>> return dev_err_probe(dev, PTR_ERR(tzd),
> >>> "failed to register sensor %d", i);
> >>> }
> >>>
> >>> sensor_count++;
> >>
> >> If I'm not mistaken in the previous version, the loop exits at the first
> >> registered sensor
> >>
> >> if (!IS_ERR(tzd))
> >> break;
> >>
> >> Here all the available sensors are registered
> >
> > The name `sensor_count` might be a bit misleading, but here the loop
> > exits after the first success:
> >
> > sensor_count++;
> > break;
> >
> > Let’s rename it:
>
> Can you clarify why only the first sensor found stops the thermal zones
> registration ?
This section of code is based on the original version by zhuyinbo; I
noticed that you’ve had related discussions about it before[1][2].
I’ve reviewed all Loongson-2K CPUs that support thermal monitoring,
and they all have only one temperature sensor, with “SEL” set to 0.
As I understand it, given the current situation, the loop here doesn’t
seem necessary—physically, there is only one temperature sensor (even
though its SEL value might theoretically be non-zero).
`LOONGSON2_MAX_SENSOR_SEL_NUM` does not accurately reflect the number
of temperature sensors; it is merely an interrupt input selection, so
using it here does not seem entirely appropriate.
Therefore, I believe treating the Loongson-2K thermal driver as a
single thermal sensor better aligns with the current hardware
behavior.
Just use:
devm_thermal_of_zone_register(dev, 0, data, thermal_ops);
[1]: https://lore.kernel.org/all/ac5b3982-a658-e05b-1b5c-3aeeda1585ed@loongson.cn/
[2]: https://lore.kernel.org/all/8ca44091-35fd-cc24-9896-0317772c5620@loongson.cn/
--
Thanks.
Binbin
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-09-29 8:23 ` Binbin Zhou
@ 2026-09-29 8:43 ` Daniel Lezcano
0 siblings, 0 replies; 15+ messages in thread
From: Daniel Lezcano @ 2026-09-29 8:43 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, Rafael J . Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-pm, stable, Sashiko
On 9/29/26 10:23, Binbin Zhou wrote:
> Hi Daniel:
>
> On Tue, Sep 29, 2026 at 1:46 PM Daniel Lezcano
> <daniel.lezcano@oss.qualcomm.com> wrote:
>>
>> On 9/29/26 05:06, Binbin Zhou wrote:
>>> Hi Daniel:
>>
>> [ ... ]
>>
>>>>>> Please make a less cumbersome and implicit checks here. For example
>>>>>> count the number of sensors and then do the check against.
>>>>>
>>>>> I thought about it, and you're right—I made the logic here too complicated.
>>>>> Let's use `sensor_count` as the counter. Is the following check logic clearer?
>>>>>
>>>>> u32 sensor_count = 0;
>>>>>
>>>>> for (unsigned int i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
>>>>> tzd = devm_thermal_of_zone_register(dev, i, data,
>>>>> data->chip_data->thermal_ops);
>>>>> if (IS_ERR(tzd)) {
>>>>> if (PTR_ERR(tzd) == -ENODEV)
>>>>> continue;
>>>>>
>>>>> return dev_err_probe(dev, PTR_ERR(tzd),
>>>>> "failed to register sensor %d", i);
>>>>> }
>>>>>
>>>>> sensor_count++;
>>>>
>>>> If I'm not mistaken in the previous version, the loop exits at the first
>>>> registered sensor
>>>>
>>>> if (!IS_ERR(tzd))
>>>> break;
>>>>
>>>> Here all the available sensors are registered
>>>
>>> The name `sensor_count` might be a bit misleading, but here the loop
>>> exits after the first success:
>>>
>>> sensor_count++;
>>> break;
>>>
>>> Let’s rename it:
>>
>> Can you clarify why only the first sensor found stops the thermal zones
>> registration ?
>
> This section of code is based on the original version by zhuyinbo; I
> noticed that you’ve had related discussions about it before[1][2].
>
> I’ve reviewed all Loongson-2K CPUs that support thermal monitoring,
> and they all have only one temperature sensor, with “SEL” set to 0.
>
> As I understand it, given the current situation, the loop here doesn’t
> seem necessary—physically, there is only one temperature sensor (even
> though its SEL value might theoretically be non-zero).
> `LOONGSON2_MAX_SENSOR_SEL_NUM` does not accurately reflect the number
> of temperature sensors; it is merely an interrupt input selection, so
> using it here does not seem entirely appropriate.
>
> Therefore, I believe treating the Loongson-2K thermal driver as a
> single thermal sensor better aligns with the current hardware
> behavior.
Sure, if the Loongson-2K is only one sensor based board then no need to
have this loop.
In the future, if there are more sensors coming with a new board, they
can be described in platform private data
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-09-29 8:44 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28 4:44 [PATCH v6 0/7] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 1/7] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
2026-09-28 7:15 ` Daniel Lezcano
2026-09-28 8:17 ` Binbin Zhou
2026-09-28 13:23 ` Daniel Lezcano
2026-09-29 3:06 ` Binbin Zhou
2026-09-29 5:46 ` Daniel Lezcano
2026-09-29 8:23 ` Binbin Zhou
2026-09-29 8:43 ` Daniel Lezcano
2026-09-28 4:44 ` [PATCH v6 2/7] thermal/drivers/loongson2: Fix clamp() usage for thermal trip points Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 3/7] thermal/drivers/loongson2: Fix Loongson-2K2000 trip point programming Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 4/7] thermal/drivers/loongson2: Use bitfields and per-SoC thermal ops Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 5/7] thermal/drivers/loongson2: Move per-SoC ops into chip data Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 6/7] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
2026-09-28 4:44 ` [PATCH v6 7/7] thermal/drivers/loongson2: Add Loongson-2K0300 support Binbin Zhou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox