* [PATCH v1 0/3] Lenovo ThinkPad T14s EC thermal monitoring and thermal zone integration
@ 2026-06-24 21:08 Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed Daniel Lezcano
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Daniel Lezcano @ 2026-06-24 21:08 UTC (permalink / raw)
To: sre, hansg, ilpo.jarvinen, linux, andersson, konradybcio, robh,
krzk+dt, conor+dt
Cc: bryan.odonoghue, platform-driver-x86, linux-kernel, linux-hwmon,
linux-arm-msm, devicetree
Hi,
This series extends the Lenovo ThinkPad T14s embedded controller driver
with environmental monitoring capabilities and integrates the exposed
sensors into the Linux thermal framework.
The EC provides access to several platform temperature sensors covering
the SoC, keyboard area, bottom cover, charging circuitry, QTM module and
SSD, as well as fan speed information. These sensors are currently used
by the firmware for thermal management but are not exposed to Linux.
The first patch adds hwmon support for the EC temperature sensors and fan
RPM reporting.
The second patch wires EC thermal notifications into the hwmon event
framework, allowing userspace to receive alarm notifications when the EC
reports thermal zone state changes.
The last patch exposes the EC as a thermal sensor provider in the device
tree and defines thermal zones for the keyboard skin temperature and the
charging circuitry temperature. This allows the generic thermal
framework to react to EC-reported temperatures and apply standard Linux
thermal mitigation policies.
With the latest patch, this series fixes thermal issues happening on
this platform where a kernel compilation leads to a system reboot.
Tested on a Lenovo ThinkPad T14s Gen 6 (Snapdragon X Elite).
Thanks,
Daniel
Daniel Lezcano (3):
drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures
and fan speed
platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon
arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin
and charging sensors
.../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 68 +++++-
drivers/platform/arm64/lenovo-thinkpad-t14s.c | 193 +++++++++++++++++-
2 files changed, 255 insertions(+), 6 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed
2026-06-24 21:08 [PATCH v1 0/3] Lenovo ThinkPad T14s EC thermal monitoring and thermal zone integration Daniel Lezcano
@ 2026-06-24 21:08 ` Daniel Lezcano
2026-06-24 21:22 ` sashiko-bot
2026-06-24 21:08 ` [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors Daniel Lezcano
2 siblings, 1 reply; 7+ messages in thread
From: Daniel Lezcano @ 2026-06-24 21:08 UTC (permalink / raw)
To: sre, hansg, ilpo.jarvinen, linux, andersson, konradybcio, robh,
krzk+dt, conor+dt
Cc: bryan.odonoghue, platform-driver-x86, linux-kernel, linux-hwmon,
linux-arm-msm, devicetree
Expose the Lenovo ThinkPad T14s EC environmental sensors through
the hwmon subsystem.
The driver now registers a hwmon device providing access to six EC
temperature sensors corresponding to the SoC, keyboard area, base
cover, PMIC/charging circuitry, QTM module and SSD. Sensor labels
are exported to allow user space to identify each measurement.
Additionally, expose the system fan speed by reading the fan RPM
registers from the embedded controller.
This allows standard monitoring tools such as lm-sensors to report
platform temperatures and fan speed.
Signed-off-by: Daniel Lezcano daniel.lezcano@oss.qualcomm.com
---
drivers/platform/arm64/lenovo-thinkpad-t14s.c | 147 ++++++++++++++++++
1 file changed, 147 insertions(+)
diff --git a/drivers/platform/arm64/lenovo-thinkpad-t14s.c b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
index 5590302a5694..142464623f0e 100644
--- a/drivers/platform/arm64/lenovo-thinkpad-t14s.c
+++ b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
+#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
@@ -67,6 +68,16 @@
#define T14S_EC_EVT_KEY_FN_F11 0x7a
#define T14S_EC_EVT_KEY_FN_G 0x7e
+#define T14S_EC_SYS_THERM0 0x78 /* SoC (CPU+GPU) */
+#define T14S_EC_SYS_THERM1 0x79 /* Keyboard */
+#define T14S_EC_SYS_THERM2 0x7a /* Back cover */
+#define T14S_EC_SYS_THERM3 0x7b /* Charger / PMIC */
+#define T14S_EC_SYS_THERM6 0x7c /* QTM West */
+#define T14S_EC_SYS_THERM7 0x7d /* SSD */
+
+#define T14S_EC_FAN_RPM_LSB 0x84
+#define T14S_EC_FAN_RPM_MSB 0x85
+
/* Hardware LED blink rate is 1 Hz (500ms off, 500ms on) */
#define T14S_EC_BLINK_RATE_ON_OFF_MS 500
@@ -93,9 +104,19 @@ struct t14s_ec_led_classdev {
struct t14s_ec *ec;
};
+struct t14s_ec_hwmon_sys_thermx {
+ const char *label;
+ int reg;
+};
+
+struct t14s_ec_hwmon {
+ struct t14s_ec_hwmon_sys_thermx *sys_thermx;
+};
+
struct t14s_ec {
struct regmap *regmap;
struct device *dev;
+ struct t14s_ec_hwmon ec_hwmon;
struct t14s_ec_led_classdev led_pwr_btn;
struct t14s_ec_led_classdev led_chrg_orange;
struct t14s_ec_led_classdev led_chrg_white;
@@ -555,6 +576,128 @@ static irqreturn_t t14s_ec_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static umode_t t14s_ec_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_temp:
+ return 0444;
+ case hwmon_fan:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static int t14s_ec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct t14s_ec *ec = dev_get_drvdata(dev);
+ switch (type) {
+ case hwmon_temp:
+ if (attr == hwmon_temp_label) {
+ *str = ec->ec_hwmon.sys_thermx[channel].label;
+ return 0;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int t14s_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct t14s_ec *ec = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ if (attr == hwmon_temp_input) {
+ ret = t14s_ec_read(ec, ec->ec_hwmon.sys_thermx[channel].reg, &value);
+ if (ret)
+ return ret;
+ *val = value * 1000;
+
+ return 0;
+ }
+ break;
+
+ case hwmon_fan:
+ if (attr == hwmon_fan_input) {
+ int lsb, msb;
+ ret = t14s_ec_read(ec, T14S_EC_FAN_RPM_LSB, &lsb);
+ if (ret)
+ return ret;
+
+ ret = t14s_ec_read(ec, T14S_EC_FAN_RPM_MSB, &msb);
+ if (ret)
+ return ret;
+
+ *val = 0;
+ *val = lsb + (msb << 8);
+
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static const struct hwmon_ops t14s_ec_hwmon_ops = {
+ .is_visible = t14s_ec_hwmon_is_visible,
+ .read = t14s_ec_hwmon_read,
+ .read_string = t14s_ec_hwmon_read_string,
+};
+
+static const struct hwmon_channel_info *t14s_ec_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL),
+ HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info t14s_ec_chip_info = {
+ .ops = &t14s_ec_hwmon_ops,
+ .info = t14s_ec_hwmon_info,
+};
+
+static int t14s_ec_hwmon_probe(struct t14s_ec *ec)
+{
+ struct device *dev;
+ struct t14s_ec_hwmon_sys_thermx sys_thermx[] = {
+ { T14S_EC_SYS_THERM0, "soc" },
+ { T14S_EC_SYS_THERM1, "keyboard" },
+ { T14S_EC_SYS_THERM2, "base" },
+ { T14S_EC_SYS_THERM3, "pmbm" },
+ { T14S_EC_SYS_THERM6, "qtm" },
+ { T14S_EC_SYS_THERM7, "ssd" },
+ };
+
+ ec->ec_hwmon.sys_thermx = devm_kmemdup_array(ec->dev, sys_thermx,
+ ARRAY_SIZE(sys_thermx),
+ sizeof(sys_thermx[0]), GFP_KERNEL);
+ if (!ec->ec_hwmon.sys_thermx)
+ return -ENOMEM;
+
+ dev = devm_hwmon_device_register_with_info(ec->dev, "t14s_ec", ec,
+ &t14s_ec_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(dev);
+}
+
static int t14s_ec_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -590,6 +733,10 @@ static int t14s_ec_probe(struct i2c_client *client)
if (ret < 0)
return ret;
+ ret = t14s_ec_hwmon_probe(ec);
+ if (ret < 0)
+ return ret;
+
ret = devm_request_threaded_irq(dev, client->irq, NULL,
t14s_ec_irq_handler,
IRQF_ONESHOT, dev_name(dev), ec);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon
2026-06-24 21:08 [PATCH v1 0/3] Lenovo ThinkPad T14s EC thermal monitoring and thermal zone integration Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed Daniel Lezcano
@ 2026-06-24 21:08 ` Daniel Lezcano
2026-06-24 21:21 ` sashiko-bot
2026-06-24 21:08 ` [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors Daniel Lezcano
2 siblings, 1 reply; 7+ messages in thread
From: Daniel Lezcano @ 2026-06-24 21:08 UTC (permalink / raw)
To: sre, hansg, ilpo.jarvinen, linux, andersson, konradybcio, robh,
krzk+dt, conor+dt
Cc: bryan.odonoghue, platform-driver-x86, linux-kernel, linux-hwmon,
linux-arm-msm, devicetree
The EC generates thermal zone status change notifications for a subset
of the exposed temperature sensors. Wire these EC events to the hwmon
notification framework so userspace can be informed when a thermal alarm
state changes.
Associate each hwmon temperature channel with its corresponding EC
thermal event and emit hwmon_temp_alarm notifications through
hwmon_notify_event() when the EC reports a thermal zone status change.
Also register thermal zones in the hwmon chip capabilities and keep a
reference to the hwmon device to allow event propagation from the IRQ
handler.
This allows userspace monitoring tools to receive thermal alarm
updates without polling the sensors and gives the opportuniy to the
kernel to cool them down.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
drivers/platform/arm64/lenovo-thinkpad-t14s.c | 66 ++++++++++++++-----
1 file changed, 51 insertions(+), 15 deletions(-)
diff --git a/drivers/platform/arm64/lenovo-thinkpad-t14s.c b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
index 142464623f0e..276bb51da33a 100644
--- a/drivers/platform/arm64/lenovo-thinkpad-t14s.c
+++ b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
@@ -107,10 +107,13 @@ struct t14s_ec_led_classdev {
struct t14s_ec_hwmon_sys_thermx {
const char *label;
int reg;
+ u8 event;
};
struct t14s_ec_hwmon {
+ struct device *dev;
struct t14s_ec_hwmon_sys_thermx *sys_thermx;
+ size_t num_sys_thermx;
};
struct t14s_ec {
@@ -493,6 +496,20 @@ static int t14s_input_probe(struct t14s_ec *ec)
return input_register_device(ec->inputdev);
}
+static void t14s_ec_hwmon_notify_event(struct t14s_ec *ec, u8 event)
+{
+ for (int i = 0; i < ec->ec_hwmon.num_sys_thermx; i++) {
+ if (ec->ec_hwmon.sys_thermx[i].event != event)
+ continue;
+
+ hwmon_notify_event(ec->ec_hwmon.dev, hwmon_temp,
+ hwmon_temp_alarm, i);
+
+ dev_dbg(ec->dev, "Thermal Zone (%s) Status Change Event\n",
+ ec->ec_hwmon.sys_thermx[i].label);
+ }
+}
+
static irqreturn_t t14s_ec_irq_handler(int irq, void *data)
{
struct t14s_ec *ec = data;
@@ -542,13 +559,9 @@ static irqreturn_t t14s_ec_irq_handler(int irq, void *data)
dev_dbg(ec->dev, "LID closed\n");
break;
case T14S_EC_EVT_THERMAL_TZ40:
- dev_dbg(ec->dev, "Thermal Zone 40 Status Change Event (CPU/GPU)\n");
- break;
case T14S_EC_EVT_THERMAL_TZ42:
- dev_dbg(ec->dev, "Thermal Zone 42 Status Change Event (Battery)\n");
- break;
case T14S_EC_EVT_THERMAL_TZ39:
- dev_dbg(ec->dev, "Thermal Zone 39 Status Change Event (CPU/GPU)\n");
+ t14s_ec_hwmon_notify_event(ec, val);
break;
case T14S_EC_EVT_KEY_FN_G:
dev_dbg(ec->dev, "FN + G - toggle double-tapping\n");
@@ -658,6 +671,7 @@ static const struct hwmon_ops t14s_ec_hwmon_ops = {
};
static const struct hwmon_channel_info *t14s_ec_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
@@ -676,14 +690,34 @@ static const struct hwmon_chip_info t14s_ec_chip_info = {
static int t14s_ec_hwmon_probe(struct t14s_ec *ec)
{
- struct device *dev;
struct t14s_ec_hwmon_sys_thermx sys_thermx[] = {
- { T14S_EC_SYS_THERM0, "soc" },
- { T14S_EC_SYS_THERM1, "keyboard" },
- { T14S_EC_SYS_THERM2, "base" },
- { T14S_EC_SYS_THERM3, "pmbm" },
- { T14S_EC_SYS_THERM6, "qtm" },
- { T14S_EC_SYS_THERM7, "ssd" },
+ {
+ .label = "soc",
+ .reg = T14S_EC_SYS_THERM0,
+ .event = T14S_EC_EVT_THERMAL_TZ39
+ },
+ {
+ .label = "keyboard",
+ .reg = T14S_EC_SYS_THERM1,
+ .event = T14S_EC_EVT_THERMAL_TZ40
+ },
+ {
+ .label = "base",
+ .reg = T14S_EC_SYS_THERM2,
+ },
+ {
+ .label = "pmbm",
+ .reg = T14S_EC_SYS_THERM3,
+ .event = T14S_EC_EVT_THERMAL_TZ42
+ },
+ {
+ .label = "qtm",
+ .reg = T14S_EC_SYS_THERM6
+ },
+ {
+ .label = "ssd",
+ .reg = T14S_EC_SYS_THERM7
+ },
};
ec->ec_hwmon.sys_thermx = devm_kmemdup_array(ec->dev, sys_thermx,
@@ -692,10 +726,12 @@ static int t14s_ec_hwmon_probe(struct t14s_ec *ec)
if (!ec->ec_hwmon.sys_thermx)
return -ENOMEM;
- dev = devm_hwmon_device_register_with_info(ec->dev, "t14s_ec", ec,
- &t14s_ec_chip_info, NULL);
+ ec->ec_hwmon.num_sys_thermx = ARRAY_SIZE(sys_thermx);
+
+ ec->ec_hwmon.dev = devm_hwmon_device_register_with_info(ec->dev, "t14s_ec", ec,
+ &t14s_ec_chip_info, NULL);
- return PTR_ERR_OR_ZERO(dev);
+ return PTR_ERR_OR_ZERO(ec->ec_hwmon.dev);
}
static int t14s_ec_probe(struct i2c_client *client)
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors
2026-06-24 21:08 [PATCH v1 0/3] Lenovo ThinkPad T14s EC thermal monitoring and thermal zone integration Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon Daniel Lezcano
@ 2026-06-24 21:08 ` Daniel Lezcano
2026-06-24 21:18 ` sashiko-bot
2 siblings, 1 reply; 7+ messages in thread
From: Daniel Lezcano @ 2026-06-24 21:08 UTC (permalink / raw)
To: sre, hansg, ilpo.jarvinen, linux, andersson, konradybcio, robh,
krzk+dt, conor+dt
Cc: bryan.odonoghue, platform-driver-x86, linux-kernel, linux-hwmon,
linux-arm-msm, devicetree
Add thermal zone descriptions for the keyboard skin temperature and
battery charging circuitry sensors exposed by the embedded controller.
Expose the EC as a thermal sensor provider and define two thermal zones
using the temperatures reported by the EC:
- a keyboard skin temperature zone with passive and hot trip points,
- a charging circuitry temperature zone with multiple passive trip
points and CPU frequency mitigation levels.
The charging thermal zone progressively throttles the different CPU
clusters as the charging circuitry temperature rises and triggers a hot
condition at the highest trip point.
This provides thermal framework integration for the EC temperature
sensors and enables platform thermal management through standard thermal
zone definitions.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
.../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 68 ++++++++++++++++++-
1 file changed, 67 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
index 5d49df41be02..e27533665c8d 100644
--- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
@@ -979,7 +979,7 @@ &i2c6 {
status = "okay";
- embedded-controller@28 {
+ ec: embedded-controller@28 {
compatible = "lenovo,thinkpad-t14s-ec";
reg = <0x28>;
@@ -988,6 +988,8 @@ embedded-controller@28 {
pinctrl-0 = <&ec_int_n_default>;
pinctrl-names = "default";
+ #thermal-sensor-cells = <1>;
+
wakeup-source;
};
};
@@ -1729,3 +1731,67 @@ &usb_mp_qmpphy1 {
status = "okay";
};
+
+&thermal_zones {
+ ec-keyboard-thermal {
+ polling-delay = <5000>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors = <&ec 1>;
+
+ trips {
+ trip-point0 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <62000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ ec-charging-thermal {
+ polling-delay = <5000>;
+ polling-delay-passive = <2000>;
+
+ thermal-sensors = <&ec 3>;
+
+ trips {
+ psv0: trip-point0 {
+ temperature = <55000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ alert0: trip-point1 {
+ temperature = <63000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&psv0>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu8 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu9 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu10 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu11 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+
+ };
+ };
+
+ };
+};
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors
2026-06-24 21:08 ` [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors Daniel Lezcano
@ 2026-06-24 21:18 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-24 21:18 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-hwmon, robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit message claims the charging thermal zone uses 'multiple passive trip points' to 'progressively throttle the different CPU clusters', but the implementation provides only a single passive trip point that throttles all CPUs simultaneously.
--
commit 165036bedb34a29493f4bd0a7af23dab152aff0c
Author: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors
Add thermal zone descriptions for the keyboard skin temperature and battery
charging circuitry sensors exposed by the embedded controller.
> - a charging circuitry temperature zone with multiple passive trip
> points and CPU frequency mitigation levels.
>
> The charging thermal zone progressively throttles the different CPU
> clusters as the charging circuitry temperature rises and triggers a hot
> condition at the highest trip point.
[Severity: Medium]
Does the implementation match this commit message description?
The commit message claims there are multiple passive trip points and
progressive throttling across different CPU clusters. Is a chunk of the patch
missing, or should the commit message be updated to reflect the final design
shown below?
> diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
> --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
> +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
[ ... ]
> + ec-charging-thermal {
> + polling-delay = <5000>;
> + polling-delay-passive = <2000>;
> +
> + thermal-sensors = <&ec 3>;
> +
> + trips {
> + psv0: trip-point0 {
> + temperature = <55000>;
> + hysteresis = <0>;
> + type = "passive";
> + };
> +
> + alert0: trip-point1 {
> + temperature = <63000>;
> + hysteresis = <0>;
> + type = "hot";
> + };
> + };
[Severity: Medium]
Only a single passive trip point is defined here in ec-charging-thermal,
which doesn't match the "multiple passive trip points" mentioned in the
commit message.
> +
> + cooling-maps {
> + map0 {
> + trip = <&psv0>;
> + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu8 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu9 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu10 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&cpu11 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> +
> + };
> + };
[Severity: Medium]
Additionally, all 12 CPUs are tied uniformly to this single trip point.
Should this define progressive throttling across different CPU clusters as
described in the commit message?
> +
> + };
> +};
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624210825.264454-1-daniel.lezcano@oss.qualcomm.com?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon
2026-06-24 21:08 ` [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon Daniel Lezcano
@ 2026-06-24 21:21 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-24 21:21 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-hwmon, robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Missing HWMON_T_ALARM capability prevents sysfs notification from working.
--
commit 1242d377b6327e98b089989a953188982e0ca595
Author: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon
This patch wires up EC thermal zone status change notifications to the hwmon
notification framework. It associates hwmon temperature channels with EC
thermal events and emits hwmon_temp_alarm notifications to userspace.
> diff --git a/drivers/platform/arm64/lenovo-thinkpad-t14s.c b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
> index 142464623f0e8..276bb51da33a3 100644
> --- a/drivers/platform/arm64/lenovo-thinkpad-t14s.c
> +++ b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
[ ... ]
> @@ -493,6 +496,20 @@ static int t14s_input_probe(struct t14s_ec *ec)
> return input_register_device(ec->inputdev);
> }
>
> +static void t14s_ec_hwmon_notify_event(struct t14s_ec *ec, u8 event)
> +{
> + for (int i = 0; i < ec->ec_hwmon.num_sys_thermx; i++) {
> + if (ec->ec_hwmon.sys_thermx[i].event != event)
> + continue;
> +
> + hwmon_notify_event(ec->ec_hwmon.dev, hwmon_temp,
> + hwmon_temp_alarm, i);
> +
> + dev_dbg(ec->dev, "Thermal Zone (%s) Status Change Event\n",
> + ec->ec_hwmon.sys_thermx[i].label);
> + }
> +}
> +
[ ... ]
> @@ -658,6 +671,7 @@ static const struct hwmon_ops t14s_ec_hwmon_ops = {
> };
>
> static const struct hwmon_channel_info *t14s_ec_hwmon_info[] = {
> + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
> HWMON_CHANNEL_INFO(temp,
> HWMON_T_INPUT | HWMON_T_LABEL,
> HWMON_T_INPUT | HWMON_T_LABEL,
> HWMON_T_INPUT | HWMON_T_LABEL,
> HWMON_T_INPUT | HWMON_T_LABEL,
> HWMON_T_INPUT | HWMON_T_LABEL,
> HWMON_T_INPUT | HWMON_T_LABEL),
[Severity: Medium]
Will the hwmon_temp_alarm notifications successfully reach userspace?
The channel configuration array does not include the HWMON_T_ALARM capability
for any of the temperature channels. Without this, the hwmon core will not
create the corresponding tempX_alarm sysfs attributes.
When t14s_ec_hwmon_notify_event() calls hwmon_notify_event() for
hwmon_temp_alarm, it appears the sysfs notification will fail silently because
the attribute does not exist. The thermal subsystem still receives the event
via hwmon_thermal_notify(), but userspace monitoring tools will not be able to
read or poll the sysfs attributes.
Does HWMON_T_ALARM need to be added to the channel configurations here to make
the sysfs event notification work as described in the commit message?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624210825.264454-1-daniel.lezcano@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed
2026-06-24 21:08 ` [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed Daniel Lezcano
@ 2026-06-24 21:22 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-24 21:22 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: robh, conor+dt, devicetree, linux-hwmon
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Direct calls to `t14s_ec_read` bypass the `regmap` mutex, violating the mandatory 10ms hardware recovery delay between EC commands.
- [Medium] Reading the fan RPM requires two separate I2C transfers for the LSB and MSB, allowing the hardware value to update in between and cause torn reads.
- [Low] Passing `int *` arguments to a function expecting `unsigned int *` for I2C register reads.
Pre-existing issues:
- [High] The `t14s_ec_read` function passes buffers allocated on the kernel stack to `__i2c_transfer()`, which violates DMA mapping rules and can cause panics.
--
commit d0870f0c919ef26da98287c26fc38bc327dcd76b
Author: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed
Expose the Lenovo ThinkPad T14s EC environmental sensors through
the hwmon subsystem.
> diff --git a/drivers/platform/arm64/lenovo-thinkpad-t14s.c b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
> index 5590302a5694f..142464623f0e8 100644
> --- a/drivers/platform/arm64/lenovo-thinkpad-t14s.c
> +++ b/drivers/platform/arm64/lenovo-thinkpad-t14s.c
[ ... ]
> @@ -555,6 +576,128 @@ static irqreturn_t t14s_ec_irq_handler(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> +static umode_t t14s_ec_hwmon_is_visible(const void *drvdata,
[ ... ]
> +static int t14s_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> + u32 attr, int channel, long *val)
> +{
> + struct t14s_ec *ec = dev_get_drvdata(dev);
> + unsigned int value;
> + int ret;
> +
> + switch (type) {
> + case hwmon_temp:
> + if (attr == hwmon_temp_input) {
> + ret = t14s_ec_read(ec, ec->ec_hwmon.sys_thermx[channel].reg, &value);
[Severity: High]
Does calling t14s_ec_read() directly here bypass the regmap mutex?
Because the embedded controller requires a 10ms hardware recovery delay between
commands, regmap serializes accesses and includes the sleep while holding the
lock. Calling t14s_ec_read() directly appears to bypass this locking, potentially
allowing concurrent sysfs reads to interleave with other subsystem I2C
transfers and violate the hardware constraint.
[Severity: High]
This isn't a bug introduced by this patch, but because this exposes new sysfs
attributes that userspace can trigger, does t14s_ec_read() pass stack-allocated
buffers to __i2c_transfer()?
Looking at t14s_ec_read():
static int t14s_ec_read(void *context, unsigned int reg,
unsigned int *val)
{
...
u8 buf[4] = {T14S_EC_CMD_ECRD, reg, 0x00, 0x01};
struct i2c_msg request, response;
u8 result;
...
request.buf = buf;
...
response.buf = &result;
...
ret = __i2c_transfer(client->adapter, &request, 1);
On ARM64 architectures with CONFIG_VMAP_STACK, passing stack memory to I2C
drivers using DMA (like Qualcomm GENI) can trigger a BUG() panic or corrupt
adjacent physical memory. Is it possible to use heap-allocated buffers here
instead?
> + if (ret)
> + return ret;
> + *val = value * 1000;
> +
> + return 0;
> + }
> + break;
> +
> + case hwmon_fan:
> + if (attr == hwmon_fan_input) {
> + int lsb, msb;
> + ret = t14s_ec_read(ec, T14S_EC_FAN_RPM_LSB, &lsb);
[Severity: Low]
Does this pass pointers of type int * to t14s_ec_read() which expects
unsigned int *?
Newer compilers like GCC 14 treat -Wincompatible-pointer-types as an
error by default, which might break the build here.
[Severity: Medium]
Is there a risk of torn reads when reading the lsb and msb sequentially?
Because t14s_ec_read() enforces a 10ms sleep after each I2C transfer, there is
a large race window between reading T14S_EC_FAN_RPM_LSB and
T14S_EC_FAN_RPM_MSB. If the fan RPM rolls over (e.g., from 0x01ff to 0x0200)
during that window, could we combine an old lsb with a new msb and report
a wildly incorrect fan speed?
> + if (ret)
> + return ret;
> +
> + ret = t14s_ec_read(ec, T14S_EC_FAN_RPM_MSB, &msb);
> + if (ret)
> + return ret;
> +
> + *val = 0;
> + *val = lsb + (msb << 8);
> +
> + return 0;
> + }
> + break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624210825.264454-1-daniel.lezcano@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-24 21:22 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 21:08 [PATCH v1 0/3] Lenovo ThinkPad T14s EC thermal monitoring and thermal zone integration Daniel Lezcano
2026-06-24 21:08 ` [PATCH v1 1/3] drivers/platform: lenovo-t14s-ec: Add hwmon support for temperatures and fan speed Daniel Lezcano
2026-06-24 21:22 ` sashiko-bot
2026-06-24 21:08 ` [PATCH v1 2/3] platform: arm64: thinkpad-t14s-ec: Wire EC thermal events to hwmon Daniel Lezcano
2026-06-24 21:21 ` sashiko-bot
2026-06-24 21:08 ` [PATCH v1 3/3] arm64: dts: qcom: x1e78100-t14s: Add thermal zones for keyboard skin and charging sensors Daniel Lezcano
2026-06-24 21:18 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.