+ more people. On Thu, 1 Oct 2026, Daniel Lezcano wrote: > Tie the keyboard thermal mitigation temperature to the platform profile > selected through the ThinkPad embedded controller. > > The EC reports Fn+L, Fn+M and Fn+H events corresponding to low-power, > balanced and performance operating modes. Use these events to update the > passive trip point of the "keyboard-thermal" zone to 49.85°C, 57.85°C > and 59.85°C respectively. > > These thresholds match the thermal mitigation temperatures used by the > platform for the corresponding operating profiles. > > Look up the keyboard thermal zone at probe time and locate the passive > trip named "keyboard-ec-alert". The trip name is used deliberately so > the EC driver can identify the device-tree trip associated with the > platform thermal profile without depending on its position in the trip > table. > > Initialize the thermal mitigation threshold to the balanced profile, > matching the default platform behaviour, and update the thermal zone > whenever a profile change event is reported by the EC so that the new > mitigation temperature takes effect immediately. > > Using the platform_profile API would provide a more appropriate interface > for exposing and managing these operating modes. However, while the API > itself is generic, the platform profile core implementation currently > lives under the ACPI framework. Making it available to device-tree based > platforms requires separating the generic infrastructure from ACPI, > which is a larger and independent piece of work. So the only problem is that platform profile resides underneath acpi namespace in sysfs? -- i. > For now, handle the EC profile events directly and use them to adjust the > thermal mitigation threshold while keeping the thermal policy described > in the device tree. > > This change depends on the keyboard thermal zone and the > "keyboard-ec-alert" trip introduced by the following series. > > Link: https://lore.kernel.org/all/20261001181055.9149-1-daniel.lezcano@oss.qualcomm.com/ > Signed-off-by: Daniel Lezcano > --- > drivers/platform/arm64/lenovo-thinkpad-t14s.c | 109 ++++++++++++++++++ > 1 file changed, 109 insertions(+) > > diff --git a/drivers/platform/arm64/lenovo-thinkpad-t14s.c b/drivers/platform/arm64/lenovo-thinkpad-t14s.c > index e7acb66b77f2..ee39b0382219 100644 > --- a/drivers/platform/arm64/lenovo-thinkpad-t14s.c > +++ b/drivers/platform/arm64/lenovo-thinkpad-t14s.c > @@ -18,8 +18,10 @@ > #include > #include > #include > +#include > #include > #include > +#include > #include > > #define T14S_EC_CMD_ECRD 0x02 > @@ -93,9 +95,16 @@ struct t14s_ec_led_classdev { > struct t14s_ec *ec; > }; > > +struct t14s_ec_thermal_profile { > + struct thermal_zone_device *tzd; > + struct thermal_trip *keyboard_alert; > + enum platform_profile_option current_profile; > +}; > + > struct t14s_ec { > struct regmap *regmap; > struct device *dev; > + struct t14s_ec_thermal_profile profile; > struct t14s_ec_led_classdev led_pwr_btn; > struct t14s_ec_led_classdev led_chrg_orange; > struct t14s_ec_led_classdev led_chrg_white; > @@ -472,6 +481,99 @@ static int t14s_input_probe(struct t14s_ec *ec) > return input_register_device(ec->inputdev); > } > > +static int t14s_platform_profile_temp(enum platform_profile_option profile) > +{ > + /* > + * These thresholds match the temperatures used by the > + * platform firmware for the corresponding operating profiles. > + */ > + switch (profile) { > + case PLATFORM_PROFILE_LOW_POWER: > + return 49850; > + case PLATFORM_PROFILE_BALANCED: > + return 57850; > + case PLATFORM_PROFILE_PERFORMANCE: > + return 59850; > + default: > + return THERMAL_TEMP_INVALID; > + } > +} > + > +static int t14s_platform_profile_set(struct t14s_ec_thermal_profile *tp, > + enum platform_profile_option profile) > +{ > + int temp; > + > + if (!tp->tzd) > + return -ENODEV; > + > + if (tp->current_profile == profile) > + return 0; > + > + temp = t14s_platform_profile_temp(profile); > + if (temp == THERMAL_TEMP_INVALID) > + return -EINVAL; > + > + thermal_zone_set_trip_temp(tp->tzd, tp->keyboard_alert, temp); > + thermal_zone_device_update(tp->tzd, THERMAL_TRIP_CHANGED); > + > + tp->current_profile = profile; > + > + return 0; > +} > + > +static int t14s_profile_find_keyboard_alert(struct thermal_trip *tt, void *data) > +{ > + struct device_node *np; > + struct t14s_ec_thermal_profile *tp = data; > + > + if (tt->type != THERMAL_TRIP_PASSIVE) > + return 0; > + > + np = tt->priv; > + > + if (!np) > + return -EINVAL; > + > + if (!of_node_name_eq(np, "keyboard-ec-alert")) > + return 0; > + > + tp->keyboard_alert = tt; > + > + return 1; > +} > + > +static int t14s_profile_probe(struct t14s_ec_thermal_profile *tp) > +{ > + struct thermal_zone_device *tzd; > + int ret; > + > + tzd = thermal_zone_get_zone_by_name("keyboard-thermal"); > + if (IS_ERR(tzd)) { > + ret = PTR_ERR(tzd); > + > + if (ret == -ENODEV) > + return -EPROBE_DEFER; > + > + return ret; > + } > + > + tp->tzd = tzd; > + > + ret = thermal_zone_for_each_trip(tzd, t14s_profile_find_keyboard_alert, tp); > + if (ret < 0) > + return ret; > + > + if (!tp->keyboard_alert) > + return -ENODEV; > + > + ret = t14s_platform_profile_set(tp, PLATFORM_PROFILE_BALANCED); > + if (ret) > + return ret; > + > + return 0; > +} > + > static irqreturn_t t14s_ec_irq_handler(int irq, void *data) > { > struct t14s_ec *ec = data; > @@ -534,12 +636,15 @@ static irqreturn_t t14s_ec_irq_handler(int irq, void *data) > break; > case T14S_EC_EVT_KEY_FN_L: > dev_dbg(ec->dev, "FN + L - low performance mode\n"); > + t14s_platform_profile_set(&ec->profile, PLATFORM_PROFILE_LOW_POWER); > break; > case T14S_EC_EVT_KEY_FN_M: > dev_dbg(ec->dev, "FN + M - medium performance mode\n"); > + t14s_platform_profile_set(&ec->profile, PLATFORM_PROFILE_BALANCED); > break; > case T14S_EC_EVT_KEY_FN_H: > dev_dbg(ec->dev, "FN + H - high performance mode\n"); > + t14s_platform_profile_set(&ec->profile, PLATFORM_PROFILE_PERFORMANCE); > break; > case T14S_EC_EVT_KEY_FN_T: > dev_dbg(ec->dev, "FN + T - toggle intelligent cooling mode\n"); > @@ -590,6 +695,10 @@ static int t14s_ec_probe(struct i2c_client *client) > if (ret < 0) > return ret; > > + ret = t14s_profile_probe(&ec->profile); > + if (ret < 0) > + return ret; > + > ret = devm_request_threaded_irq(dev, client->irq, NULL, > t14s_ec_irq_handler, > IRQF_ONESHOT, dev_name(dev), ec); > -- i.