From 88769791bc50dd677b258b50bfbd811440cc2ca2 Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Fri, 11 Sep 2026 15:38:22 +0530 Subject: [PATCH 1/4] dt-bindings: embedded-controller: qcom,hamoa-crd-ec: Add thermal sensors Describe the Hamoa embedded controller as a thermal-sensor provider with one cell for selecting one of up to seven thermistors. The populated channels are discovered from the EC firmware capability response, while board thermal zones can reference a channel with <&ec N>. Signed-off-by: Anvesh Jain P --- .../embedded-controller/qcom,hamoa-crd-ec.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml b/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml index c07483aa59370..e42b92b8a00ab 100644 --- a/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml +++ b/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml @@ -15,6 +15,9 @@ description: EC running on different MCU chips. The EC handles things like fan control, temperature sensors, access to EC internal state changes. +allOf: + - $ref: /schemas/thermal/thermal-sensor.yaml# + properties: compatible: oneOf: @@ -33,6 +36,14 @@ properties: interrupts: maxItems: 1 + "#thermal-sensor-cells": + description: + The EC exposes up to 7 onboard thermistors (indices 0-6). Which + indices are physically populated on a given board is discovered at + runtime from EC firmware capabilities and is not described in the + devicetree; a board may reference any index 0-6. + const: 1 + required: - compatible - reg @@ -50,6 +61,7 @@ examples: embedded-controller@76 { compatible = "qcom,hamoa-crd-ec"; reg = <0x76>; + #thermal-sensor-cells = <1>; interrupts-extended = <&tlmm 66 IRQ_TYPE_LEVEL_HIGH>; }; From 46b4ed2ea5532448967b3b0b47b3cc0e3f2a397f Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Fri, 11 Sep 2026 15:38:25 +0530 Subject: [PATCH 2/4] platform: arm64: qcom-hamoa-ec: Add thermistor sensors Register each thermistor reported by the EC thermal capability response with devm_thermal_of_zone_register(). Read signed 16-bit temperatures returned by the EC and convert the 0.1 degree Celsius values to the millidegree units expected by the thermal framework. Signed-off-by: Anvesh Jain P --- drivers/platform/arm64/qcom-hamoa-ec.c | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/drivers/platform/arm64/qcom-hamoa-ec.c b/drivers/platform/arm64/qcom-hamoa-ec.c index 5ca7308c60774..11639d3613513 100644 --- a/drivers/platform/arm64/qcom-hamoa-ec.c +++ b/drivers/platform/arm64/qcom-hamoa-ec.c @@ -16,16 +16,19 @@ #include #include #include +#include #define EC_SCI_EVT_READ_CMD 0x05 #define EC_FW_VERSION_CMD 0x0e #define EC_MODERN_STANDBY_CMD 0x23 +#define EC_THERMISTOR_TEMP_CMD 0x29 /* + thermistor_id (0-6) selects thermistor 1-7 */ #define EC_FAN_DBG_CONTROL_CMD 0x30 #define EC_SCI_EVT_CONTROL_CMD 0x35 #define EC_THERMAL_CAP_CMD 0x42 #define EC_FW_VERSION_RESP_LEN 4 #define EC_THERMAL_CAP_RESP_LEN 3 +#define EC_THERMISTOR_TEMP_RESP_LEN 3 #define EC_FAN_DEBUG_CMD_LEN 6 #define EC_FAN_SPEED_DATA_SIZE 4 @@ -39,6 +42,7 @@ #define EC_MAX_FAN_CNT 2 #define EC_FAN_NAME_SIZE 20 #define EC_FAN_MAX_PWM 255 +#define EC_MAX_THERMISTOR_CNT 7 enum qcom_ec_sci_events { EC_FAN1_STATUS_CHANGE_EVT = 0x30, @@ -64,6 +68,7 @@ struct qcom_ec_thermal_cap { #define EC_THERMAL_FAN_CNT(x) (FIELD_GET(GENMASK(1, 0), (x))) #define EC_THERMAL_FAN_TYPE(x) (FIELD_GET(GENMASK(4, 2), (x))) #define EC_THERMAL_THERMISTOR_MASK(x) (FIELD_GET(GENMASK(7, 0), (x))) +#define EC_THERMISTOR_PRESENT(mask, id) ((mask) & BIT(id)) u8 fan_cnt; u8 fan_type; u8 thermistor_mask; @@ -81,6 +86,12 @@ struct qcom_ec { struct qcom_ec_thermal_cap thermal_cap; struct qcom_ec_version version; struct i2c_client *client; + struct qcom_ec_thermal_zone *ec_tz; +}; + +struct qcom_ec_thermal_zone { + struct qcom_ec *ec; + u8 thermistor_id; }; static int qcom_ec_read(struct qcom_ec *ec, u8 cmd, u8 resp_len, u8 *resp) @@ -181,6 +192,43 @@ static int qcom_ec_thermal_capabilities(struct device *dev) return 0; } +/* + * EC Thermistor Temperature (cmd 0x29 + thermistor_id, id 0-6 selects + * thermistor 1-7): + * + * Read Response: + * ---------------------------------------------------------------------- + * | Offset | Name | Description | + * ---------------------------------------------------------------------- + * | 0x00 | Byte count | Number of bytes in response (=2) | + * ---------------------------------------------------------------------- + * | 0x01 (LSB)| Temperature | Signed 16-bit, unit of 0.1 degC, | + * | 0x02 (MSB)| | range -40..+125 degC | + * ---------------------------------------------------------------------- + */ +static int qcom_ec_thermistor_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct qcom_ec_thermal_zone *ec_tz = thermal_zone_device_priv(tz); + struct qcom_ec *ec = ec_tz->ec; + u8 resp[EC_THERMISTOR_TEMP_RESP_LEN]; + s16 raw; + int ret; + + ret = qcom_ec_read(ec, EC_THERMISTOR_TEMP_CMD + ec_tz->thermistor_id, + EC_THERMISTOR_TEMP_RESP_LEN, resp); + if (ret < 0) + return ret; + + raw = (s16)get_unaligned_le16(&resp[1]); + *temp = raw * 100; + + return 0; +} + +static const struct thermal_zone_device_ops qcom_ec_thermistor_ops = { + .get_temp = qcom_ec_thermistor_get_temp, +}; + static irqreturn_t qcom_ec_irq(int irq, void *data) { struct qcom_ec *ec = data; @@ -374,6 +422,32 @@ static int qcom_ec_probe(struct i2c_client *client) if (ret < 0) return dev_err_probe(dev, ret, "Failed to read thermal capabilities\n"); + if (ec->thermal_cap.thermistor_mask) { + ec->ec_tz = devm_kcalloc(dev, EC_MAX_THERMISTOR_CNT, sizeof(*ec->ec_tz), + GFP_KERNEL); + if (!ec->ec_tz) + return -ENOMEM; + + for (i = 0; i < EC_MAX_THERMISTOR_CNT; i++) { + struct qcom_ec_thermal_zone *ec_tz = &ec->ec_tz[i]; + struct thermal_zone_device *tzd; + + if (!EC_THERMISTOR_PRESENT(ec->thermal_cap.thermistor_mask, i)) + continue; + + ec_tz->ec = ec; + ec_tz->thermistor_id = i; + + tzd = devm_thermal_of_zone_register(dev, i, ec_tz, &qcom_ec_thermistor_ops); + if (IS_ERR(tzd)) { + ret = PTR_ERR(tzd); + if (ret != -ENODEV) + dev_warn(dev, "Failed to register thermistor%u zone: %d\n", + i, ret); + } + } + } + if (ec->thermal_cap.fan_cnt == 0) { dev_warn(dev, FW_BUG "Failed to get fan count, firmware update required\n"); return 0; From 1220048ae0a39557f2d3b8769c0cba7338e597f0 Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Fri, 11 Sep 2026 15:38:27 +0530 Subject: [PATCH 3/4] arm64: dts: qcom: glymur-crd: Add thermal sensor cells to EC Advertise one thermal-sensor cell on the embedded controller so board thermal zones can reference the firmware-reported thermistors by index. Signed-off-by: Anvesh Jain P --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index fb552aa006607..e3070fe96ddc4 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -882,6 +882,7 @@ embedded-controller@76 { compatible = "qcom,glymur-crd-ec", "qcom,hamoa-crd-ec"; reg = <0x76>; + #thermal-sensor-cells = <1>; interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; From 331fee1c4159e2d0f51708223c20de07e54c85ed Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Wed, 16 Sep 2026 17:57:46 +0530 Subject: [PATCH 4/4] arm64: dts: qcom: glymur: Add EC thermal zones Describe the EC-reported SoC, keyboard, and cover temperature sensors as thermal zones on the Glymur CRD. Signed-off-by: Anvesh Jain P --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index e3070fe96ddc4..2c981ec4ee6c4 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -609,6 +609,20 @@ }; }; +&thermal_zones { + ec-soc-thermal { + thermal-sensors = <&ec 0>; + }; + + ec-kbd-thermal { + thermal-sensors = <&ec 1>; + }; + + ec-cover-thermal { + thermal-sensors = <&ec 2>; + }; +}; + &i2c0 { clock-frequency = <400000>; @@ -879,7 +893,7 @@ status = "okay"; - embedded-controller@76 { + ec: embedded-controller@76 { compatible = "qcom,glymur-crd-ec", "qcom,hamoa-crd-ec"; reg = <0x76>; #thermal-sensor-cells = <1>;