* [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
@ 2026-08-04 12:42 ` Binbin Zhou
2026-08-04 13:01 ` sashiko-bot
2026-08-04 12:43 ` [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability Binbin Zhou
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Binbin Zhou @ 2026-08-04 12:42 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones
Cc: Huacai Chen, devicetree, linux-pm, mfd, 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 ea4dd2fb1f47..5f47fa51fb90 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -161,16 +161,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] 13+ messages in thread* Re: [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop
2026-08-04 12:42 ` [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
@ 2026-08-04 13:01 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-08-04 13:01 UTC (permalink / raw)
To: Binbin Zhou; +Cc: conor+dt, mfd, robh, lee, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [High] The driver allows registering any sensor ID from 0 to 3 but unconditionally configures hardware registers for sensor 0.
- [High] The device's hardware interrupt is left enabled when probe fails or the driver is unbound.
- [High] Potential NULL pointer dereference if `device_get_match_data()` returns NULL.
--
--- Patch [1]: [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop ---
commit 04ee4726d4d6013e77a52a26bf79466c2069029a
Author: Binbin Zhou <zhoubinbin@loongson.cn>
thermal/drivers/loongson2: Correct thermal sensor registration loop
This commit fixes the registration loop in loongson2_thermal_probe() by
correctly handling -ENODEV and only aborting on fatal errors. It also
ensures at least one thermal zone is registered before proceeding.
> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> index ea4dd2fb1f473..5f47fa51fb907 100644
> --- a/drivers/thermal/loongson2_thermal.c
> +++ b/drivers/thermal/loongson2_thermal.c
> @@ -161,16 +161,18 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
[Severity: High]
This is a pre-existing issue, but if device_get_match_data() returns NULL
(for example, via manual sysfs binding), can this cause a NULL pointer
dereference earlier in this function?
drivers/thermal/loongson2_thermal.c:loongson2_thermal_probe() {
...
data->chip_data = device_get_match_data(dev);
...
if (data->chip_data->flags & LS2K2000_THSENS_OUT_FLAG) {
...
}
>
> for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
> tzd = devm_thermal_of_zone_register(dev, i, data, thermal_ops);
[Severity: High]
This isn't a bug introduced by this patch, but does this leave the hardware
interrupt enabled if probe fails later or the driver is unbound?
During devm_thermal_of_zone_register(), the thermal core registers the zone
and invokes tz->ops->set_trips(). This calls
loongson2_thermal_set(..., enable=true), which enables the hardware interrupt.
However, there appears to be no corresponding remove function in
loongson2_thermal_driver, nor a devm_add_action_or_reset() callback to
disable the interrupt if devm_request_threaded_irq() fails or the driver is
unbound.
[Severity: High]
This is also a pre-existing issue, but if the device tree specifies a thermal
zone for a sensor ID other than 0, will the hardware configuration match the
intended sensor?
The probe loop registers the zone for sensor index i and breaks, but
loongson2_set_ctrl_regs() uses a statically defined thermal_sensor_sel:
drivers/thermal/loongson2_thermal.c:loongson2_set_ctrl_regs() {
int reg_off = data->chip_data->thermal_sensor_sel * 2;
...
}
It seems this calculates the register offset ignoring the actually registered
sensor ID, potentially resulting in reading from and writing limits to the
hardware registers of sensor 0 instead.
> 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)
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785829933.git.zhoubinbin@loongson.cn?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
2026-08-04 12:42 ` [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
@ 2026-08-04 12:43 ` Binbin Zhou
2026-08-04 12:55 ` sashiko-bot
2026-08-04 12:43 ` [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id Binbin Zhou
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Binbin Zhou @ 2026-08-04 12:43 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones
Cc: Huacai Chen, devicetree, linux-pm, mfd, Binbin Zhou
In preparation for supporting additional Loongson SoCs, relocate the
thermal zone device operations pointer (thermal_ops) from the probe
routine to the per-SoC chip_data structure. This eliminates the need
to add conditional branches in probe() when a new SoC is introduced;
instead, the appropriate ops can be statically assigned in the match
data.
No functional change intended.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 5f47fa51fb90..1a8ca2cd06f1 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -39,6 +39,7 @@
struct loongson2_thermal_chip_data {
unsigned int thermal_sensor_sel;
unsigned int flags;
+ const struct thermal_zone_device_ops *thermal_ops;
};
struct loongson2_thermal_data {
@@ -124,7 +125,6 @@ static const struct thermal_zone_device_ops loongson2_2k2000_of_thermal_ops = {
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 thermal_zone_device *tzd;
@@ -145,10 +145,6 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
data->temp_reg = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(data->temp_reg))
return PTR_ERR(data->temp_reg);
-
- thermal_ops = &loongson2_2k2000_of_thermal_ops;
- } else {
- thermal_ops = &loongson2_2k1000_of_thermal_ops;
}
irq = platform_get_irq(pdev, 0);
@@ -160,7 +156,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
loongson2_thermal_set(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;
@@ -186,11 +182,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,
+ .thermal_ops = &loongson2_2k1000_of_thermal_ops,
};
static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = {
.thermal_sensor_sel = 0,
.flags = LS2K2000_THSENS_OUT_FLAG,
+ .thermal_ops = &loongson2_2k2000_of_thermal_ops,
};
static const struct of_device_id of_loongson2_thermal_match[] = {
--
2.52.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability
2026-08-04 12:43 ` [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability Binbin Zhou
@ 2026-08-04 12:55 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-08-04 12:55 UTC (permalink / raw)
To: Binbin Zhou; +Cc: mfd, lee, robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The driver misuses the `clamp()` macro when setting temperature thresholds, failing to bound the requested trip values to the hardware's supported range `[-40, 125]`.
--
--- Patch [2]: [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability ---
commit 1f38b1d9f1db90805ef5765872a4c9de0db11e9c
Author: Binbin Zhou <zhoubinbin@loongson.cn>
thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability
In preparation for supporting additional Loongson SoCs, this commit
relocates the thermal zone device operations pointer from the probe
routine to the per-SoC chip_data structure. This eliminates the need to
add conditional branches in probe() when a new SoC is introduced.
> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> index 5f47fa51fb907..1a8ca2cd06f1b 100644
> --- a/drivers/thermal/loongson2_thermal.c
> +++ b/drivers/thermal/loongson2_thermal.c
[ ... ]
> @@ -160,7 +156,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
> loongson2_thermal_set(data, 0, 0, false);
>
[Severity: High]
This is a pre-existing issue, but does loongson2_thermal_set() misuse the
clamp macro when setting temperature thresholds?
Looking at drivers/thermal/loongson2_thermal.c:loongson2_thermal_set(), the
arguments to clamp() appear to be in the wrong order:
/* Set low temperature threshold */
loongson2_set_ctrl_regs(data, clamp(-40, low, high), true, enable);
/* Set high temperature threshold */
loongson2_set_ctrl_regs(data, clamp(125, low, high), false, enable);
Because the clamp macro arguments are swapped (using clamp(-40, low, high)
instead of clamp(low, -40, 125) and clamp(high, -40, 125)), values like a
high trip point > 155C are not bounded to 125.
If root sets a thermal trip point > 155C via sysfs, adding HECTO (100) to
156+ results in a value > 255.
When this is written to the 16-bit hardware register, can it overflow into
bit 8 (the enable bit), overwriting the control state and truncating the
threshold to an incorrect value?
Could this cause immediate and continuous hardware thermal alarms (IRQ
storm), rendering the system unusable?
> 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;
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785829933.git.zhoubinbin@loongson.cn?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
2026-08-04 12:42 ` [PATCH v4 1/5] thermal/drivers/loongson2: Correct thermal sensor registration loop Binbin Zhou
2026-08-04 12:43 ` [PATCH v4 2/5] thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC scalability Binbin Zhou
@ 2026-08-04 12:43 ` Binbin Zhou
2026-08-04 12:46 ` sashiko-bot
2026-08-05 6:59 ` Krzysztof Kozlowski
2026-08-04 12:43 ` [PATCH v4 4/5] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
` (2 subsequent siblings)
5 siblings, 2 replies; 13+ messages in thread
From: Binbin Zhou @ 2026-08-04 12:43 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones
Cc: Huacai Chen, devicetree, linux-pm, mfd, Binbin Zhou
The Loongson-2K0300 SoC exposes its chip ID registers through a syscon
interface. Add the specific compatible `loongson,ls2k0300-chipid-syscon`
to the allowed list of syscon bindings so that it can be referenced from
the thermal node via a phandle.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index fe882d3f828b..d3e799410cf7 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -73,6 +73,7 @@ properties:
- hpe,gxp-sysreg
- loongson,ls1b-syscon
- loongson,ls1c-syscon
+ - loongson,ls2k0300-chipid-syscon
- lsi,axxia-syscon
- marvell,armada-3700-cpu-misc
- marvell,armada-3700-nb-pm
--
2.52.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id
2026-08-04 12:43 ` [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id Binbin Zhou
@ 2026-08-04 12:46 ` sashiko-bot
2026-08-05 6:59 ` Krzysztof Kozlowski
1 sibling, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-08-04 12:46 UTC (permalink / raw)
To: Binbin Zhou; +Cc: mfd, conor+dt, robh, devicetree, lee
> The Loongson-2K0300 SoC exposes its chip ID registers through a syscon
> interface. Add the specific compatible `loongson,ls2k0300-chipid-syscon`
> to the allowed list of syscon bindings so that it can be referenced from
> the thermal node via a phandle.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785829933.git.zhoubinbin@loongson.cn?part=3
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id
2026-08-04 12:43 ` [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id Binbin Zhou
2026-08-04 12:46 ` sashiko-bot
@ 2026-08-05 6:59 ` Krzysztof Kozlowski
1 sibling, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2026-08-05 6:59 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones, Huacai Chen,
devicetree, linux-pm, mfd
On Tue, Aug 04, 2026 at 08:43:56PM +0800, Binbin Zhou wrote:
> The Loongson-2K0300 SoC exposes its chip ID registers through a syscon
> interface. Add the specific compatible `loongson,ls2k0300-chipid-syscon`
> to the allowed list of syscon bindings so that it can be referenced from
> the thermal node via a phandle.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 4/5] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (2 preceding siblings ...)
2026-08-04 12:43 ` [PATCH v4 3/5] dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300 chip id Binbin Zhou
@ 2026-08-04 12:43 ` Binbin Zhou
2026-08-04 12:49 ` sashiko-bot
2026-08-04 12:43 ` [PATCH v4 5/5] thermal/drivers/loongson2: Add support " Binbin Zhou
2026-08-05 9:43 ` [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Huacai Chen
5 siblings, 1 reply; 13+ messages in thread
From: Binbin Zhou @ 2026-08-04 12:43 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones
Cc: Huacai Chen, devicetree, linux-pm, mfd, 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] 13+ messages in thread* Re: [PATCH v4 4/5] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300
2026-08-04 12:43 ` [PATCH v4 4/5] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
@ 2026-08-04 12:49 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-08-04 12:49 UTC (permalink / raw)
To: Binbin Zhou; +Cc: mfd, devicetree, lee, robh, conor+dt
> 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>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785829933.git.zhoubinbin@loongson.cn?part=4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 5/5] thermal/drivers/loongson2: Add support for Loongson-2K0300
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (3 preceding siblings ...)
2026-08-04 12:43 ` [PATCH v4 4/5] dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for Loongson-2K0300 Binbin Zhou
@ 2026-08-04 12:43 ` Binbin Zhou
2026-08-04 12:59 ` sashiko-bot
2026-08-05 9:43 ` [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Huacai Chen
5 siblings, 1 reply; 13+ messages in thread
From: Binbin Zhou @ 2026-08-04 12:43 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones
Cc: Huacai Chen, devicetree, linux-pm, mfd, Binbin Zhou
Add support for the thermal sensor found on the Loongson-2K0300 SoC.
The Loongson-2K0300 thermal sensor uses a 10-bit ADC and requires
per-chip calibration. The calibration offset is stored in the CHIP ID
registers, which are accessed via syscon. The driver reads this offset
and applies it when converting the raw ADC value to millicelsius.
To handle old fuse versions that cannot be calibrated correctly, the
driver includes a fallback formula and a validity check. Once invalid
data is detected, the driver falls back to the old formula for future
reads and warns the user.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/thermal/loongson2_thermal.c | 94 ++++++++++++++++++++++++++++-
1 file changed, 92 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
index 1a8ca2cd06f1..51b29b60372a 100644
--- a/drivers/thermal/loongson2_thermal.c
+++ b/drivers/thermal/loongson2_thermal.c
@@ -2,9 +2,11 @@
/*
* Author: zhanghongchen <zhanghongchen@loongson.cn>
* Yinbo Zhu <zhuyinbo@loongson.cn>
+ * Binbin Zhou <zhoubinbin@loongson.cn>
* Copyright (C) 2022-2023 Loongson Technology Corporation Limited
*/
+#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/minmax.h>
@@ -14,6 +16,9 @@
#include <linux/property.h>
#include <linux/thermal.h>
#include <linux/units.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/syscore_ops.h>
#include "thermal_hwmon.h"
@@ -23,18 +28,34 @@
#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8
#define LOONGSON2_THSENS_STATUS_REG 0x10
#define LOONGSON2_THSENS_OUT_REG 0x14
+#define LOONGSON2_THSENS_CFG_REG 0x18
#define LOONGSON2_THSENS_INT_LO BIT(0)
#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_OUT_8B_MASK 0xFF
+#define LOONGSON2_THSENS_OUT_11B_MASK GENMASK(10, 0)
+
+#define LS2K0300_CHIP_ID0 0x10
+#define LS2K0300_CHIP_ID1 0x14
+#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_LOWEST_VALID_TEMP (-55000)
+#define LS2K0300_HIGHEST_VALID_TEMP (125000)
/*
* This flag is used to indicate the temperature reading
* method of the Loongson-2K2000
*/
#define LS2K2000_THSENS_OUT_FLAG BIT(0)
+#define LS2K0300_CHIP_ID_FLAG BIT(1)
+#define LS2K0300_OLD_FUSE_FLAG BIT(2)
struct loongson2_thermal_chip_data {
unsigned int thermal_sensor_sel;
@@ -43,8 +64,11 @@ struct loongson2_thermal_chip_data {
};
struct loongson2_thermal_data {
+ struct device *dev;
void __iomem *ctrl_reg;
void __iomem *temp_reg;
+ struct regmap *regmap_cfg;
+ u32 flags;
const struct loongson2_thermal_chip_data *chip_data;
};
@@ -72,13 +96,54 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data,
return 0;
}
+static int loongson2_2k0300_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ struct loongson2_thermal_data *tdata = thermal_zone_device_priv(tz);
+ int calib_data, calib_offset, temp_mc, raw_adc;
+ u32 chip_id0 = 0, chip_id1 = 0;
+
+ writel(0xff03, tdata->ctrl_reg + LOONGSON2_THSENS_CFG_REG);
+ raw_adc = FIELD_GET(LOONGSON2_THSENS_OUT_11B_MASK,
+ readl(tdata->ctrl_reg + LOONGSON2_THSENS_OUT_REG));
+
+ if (tdata->flags & LS2K0300_OLD_FUSE_FLAG) {
+ *temp = raw_adc * 569 - 394700;
+ return 0;
+ }
+
+ regmap_read(tdata->regmap_cfg, LS2K0300_CHIP_ID0, &chip_id0);
+ regmap_read(tdata->regmap_cfg, LS2K0300_CHIP_ID1, &chip_id1);
+
+ 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);
+ }
+
+ temp_mc = (raw_adc + calib_offset) * 570 - 394700;
+
+ /* For old fuse which can not read right thermal data */
+ if (temp_mc < LS2K0300_LOWEST_VALID_TEMP || temp_mc > LS2K0300_HIGHEST_VALID_TEMP) {
+ dev_warn_once(tdata->dev, "It's an old fuse, thermal %d is not right\n", temp_mc);
+ tdata->flags |= LS2K0300_OLD_FUSE_FLAG;
+ temp_mc = raw_adc * 569 - 394700;
+ }
+ *temp = temp_mc;
+
+ return 0;
+}
+
static int loongson2_2k1000_get_temp(struct thermal_zone_device *tz, int *temp)
{
int val;
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG);
- *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO;
+ *temp = ((val & LOONGSON2_THSENS_OUT_8B_MASK) - HECTO) * KILO;
return 0;
}
@@ -113,6 +178,11 @@ static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low,
return loongson2_thermal_set(data, low/MILLI, high/MILLI, true);
}
+static const struct thermal_zone_device_ops loongson2_2k0300_of_thermal_ops = {
+ .get_temp = loongson2_2k0300_get_temp,
+ .set_trips = loongson2_thermal_set_trips,
+};
+
static const struct thermal_zone_device_ops loongson2_2k1000_of_thermal_ops = {
.get_temp = loongson2_2k1000_get_temp,
.set_trips = loongson2_thermal_set_trips,
@@ -135,6 +205,8 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
return -ENOMEM;
data->chip_data = device_get_match_data(dev);
+ data->flags = data->chip_data->flags;
+ data->dev = dev;
data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->ctrl_reg))
@@ -147,6 +219,14 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
return PTR_ERR(data->temp_reg);
}
+ /* The chip id register is needed for Loongson-2K0300 */
+ if (data->chip_data->flags & LS2K0300_CHIP_ID_FLAG) {
+ 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);
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -179,6 +259,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
return 0;
}
+static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k0300_data = {
+ .thermal_sensor_sel = 0,
+ .flags = LS2K0300_CHIP_ID_FLAG,
+ .thermal_ops = &loongson2_2k0300_of_thermal_ops,
+};
+
static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = {
.thermal_sensor_sel = 0,
.flags = 0,
@@ -192,6 +278,10 @@ static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data
};
static const struct of_device_id of_loongson2_thermal_match[] = {
+ {
+ .compatible = "loongson,ls2k0300-thermal",
+ .data = &loongson2_thermal_ls2k0300_data,
+ },
{
.compatible = "loongson,ls2k1000-thermal",
.data = &loongson2_thermal_ls2k1000_data,
--
2.52.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 5/5] thermal/drivers/loongson2: Add support for Loongson-2K0300
2026-08-04 12:43 ` [PATCH v4 5/5] thermal/drivers/loongson2: Add support " Binbin Zhou
@ 2026-08-04 12:59 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-08-04 12:59 UTC (permalink / raw)
To: Binbin Zhou; +Cc: devicetree, lee, mfd, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The 'old fuse' validity check uses legitimate dynamic temperature bounds, which will permanently disable sensor calibration during real thermal emergencies.
- [Medium] The return values of `regmap_read()` for chip ID registers are ignored, potentially leading to silent failures and miscalculation of temperatures.
- [Medium] Suspicious manual sign-magnitude parsing and missing sign handling for `chip_id0` calibration data.
--
--- Patch [5]: [PATCH v4 5/5] thermal/drivers/loongson2: Add support for Loongson-2K0300 ---
commit 3e3a89cf673b3132da6f690e9200a7140d2ed6ae
Author: Binbin Zhou <zhoubinbin@loongson.cn>
thermal/drivers/loongson2: Add support for Loongson-2K0300
This commit adds support for the thermal sensor on the Loongson-2K0300 SoC.
The sensor uses a 10-bit ADC and requires per-chip calibration offsets read
from syscon CHIP ID registers. A fallback formula and validity check are
included for older fuse versions.
> diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c
> index 1a8ca2cd06f1b..51b29b60372a5 100644
> --- a/drivers/thermal/loongson2_thermal.c
> +++ b/drivers/thermal/loongson2_thermal.c
[ ... ]
> @@ -72,13 +96,54 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data,
> return 0;
> }
>
> +static int loongson2_2k0300_get_temp(struct thermal_zone_device *tz, int *temp)
> +{
> + struct loongson2_thermal_data *tdata = thermal_zone_device_priv(tz);
> + int calib_data, calib_offset, temp_mc, raw_adc;
> + u32 chip_id0 = 0, chip_id1 = 0;
> +
> + writel(0xff03, tdata->ctrl_reg + LOONGSON2_THSENS_CFG_REG);
> + raw_adc = FIELD_GET(LOONGSON2_THSENS_OUT_11B_MASK,
> + readl(tdata->ctrl_reg + LOONGSON2_THSENS_OUT_REG));
> +
> + if (tdata->flags & LS2K0300_OLD_FUSE_FLAG) {
> + *temp = raw_adc * 569 - 394700;
> + return 0;
> + }
> +
> + regmap_read(tdata->regmap_cfg, LS2K0300_CHIP_ID0, &chip_id0);
> + regmap_read(tdata->regmap_cfg, LS2K0300_CHIP_ID1, &chip_id1);
[Severity: Medium]
Is it safe to ignore the return values of these regmap_read() calls?
If regmap_read() fails due to an underlying bus or configuration error, it
will not modify chip_id0 or chip_id1, leaving them at 0. This could cause
the driver to silently compute an uncalibrated temperature without reporting
the read error.
> +
> + 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);
[Severity: Medium]
Does the chip_id0 fallback path have a missing sign bit check?
The code extracts a 12-bit value into calib_data using a 12-bit mask
(LS2K0300_ID0_VAL_MASK is GENMASK(31, 20)). It then immediately applies a
15-bit mask (LS2K0300_COMP_VAL_MASK is GENMASK(14, 0)) to that 12-bit value,
which appears redundant.
Additionally, unlike the chip_id1 branch above which explicitly checks for a
sign bit and negates the offset, this branch lacks sign handling. If the
12-bit fuse data uses a sign bit, interpreting a negative value as a large
positive integer could skew the temperature calculation significantly.
> + }
> +
> + temp_mc = (raw_adc + calib_offset) * 570 - 394700;
> +
> + /* For old fuse which can not read right thermal data */
> + if (temp_mc < LS2K0300_LOWEST_VALID_TEMP || temp_mc > LS2K0300_HIGHEST_VALID_TEMP) {
[Severity: High]
Could this logic permanently disable sensor calibration during a real overheat?
If the physical CPU temperature genuinely exceeds 125 degrees Celsius during
a thermal emergency, this check will incorrectly flag the valid hardware fuse
as invalid.
It then sets the LS2K0300_OLD_FUSE_FLAG, permanently disabling calibration
for all future reads, which causes the sensor to report lower uncalibrated
temperatures exactly when accurate readings are needed to trigger a shutdown.
> + dev_warn_once(tdata->dev, "It's an old fuse, thermal %d is not right\n", temp_mc);
> + tdata->flags |= LS2K0300_OLD_FUSE_FLAG;
> + temp_mc = raw_adc * 569 - 394700;
> + }
> + *temp = temp_mc;
> +
> + return 0;
> +}
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785829933.git.zhoubinbin@loongson.cn?part=5
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC
2026-08-04 12:40 [PATCH v4 0/5] thermal: loongson2: Add support for Loongson-2K0300 SoC Binbin Zhou
` (4 preceding siblings ...)
2026-08-04 12:43 ` [PATCH v4 5/5] thermal/drivers/loongson2: Add support " Binbin Zhou
@ 2026-08-05 9:43 ` Huacai Chen
5 siblings, 0 replies; 13+ messages in thread
From: Huacai Chen @ 2026-08-05 9:43 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yinbo Zhu, zhanghongchen, Rafael J . Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Lee Jones, devicetree,
linux-pm, mfd
For the whole series:
Reviewed-by: Huacai Chen <chenhuacai@loongson.cn>
On Tue, Aug 4, 2026 at 8:41 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> 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 patches have been validated on the Loongson-2K0300 development board.
>
> Thanks.
> Binbin
>
> =========
> V4:
> - Rebase on linux-mfd/for-mfd-next;
> Patch (3/5):
> - Remove the `compatible` adding 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 (5):
> thermal/drivers/loongson2: Correct thermal sensor registration loop
> thermal/drivers/loongson2: Move thermal_ops to chip_data for SoC
> scalability
> dt-bindings: mfd: syscon: Allow syscon compatible for Loongson-2K0300
> chip id
> dt-bindings: thermal: loongson,ls2k-thermal: Add compatible for
> Loongson-2K0300
> thermal/drivers/loongson2: Add support for Loongson-2K0300
>
> .../devicetree/bindings/mfd/syscon.yaml | 1 +
> .../thermal/loongson,ls2k-thermal.yaml | 73 +++++++++---
> drivers/thermal/loongson2_thermal.c | 110 ++++++++++++++++--
> 3 files changed, 156 insertions(+), 28 deletions(-)
>
>
> base-commit: b1eb3de64d02cec71b419b9918d1697797fa156d
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 13+ messages in thread