From nobody Mon Jun 8 09:53:01 2026 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E84B54218A0; Fri, 29 May 2026 20:32:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; cv=none; b=VevTBqRPllDmHD8Hw9PxamgbyeWMRNrJi5gIwvxM1KG603lfCQwjXBhTglV2qRBFTREer1QgAFA56PlUjcv0/xZrOfakhOO3mSU1tlaeXMsuoz3egp9gokpEyrT7GLVqLJ9ScNCCzNqBcqxN+6TxhKDPaqFV3ny8H9EvNX8nFa4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; c=relaxed/simple; bh=9dhz5D1a0Ksv2nfOCHB6O5HOpDxXY+m49njNGjn9knQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OFHx1/bMHgkLJtS60OH3YBa5HdIoxyutQlO6Hl8w9366cSLAf+BwqkUbvsFkPB28/gACqep6nJV1VDzaqn4phZBrY/qblErpXvaAgekBVB2w+I2ycJ8M6xo630Cf0kvvIfL1I7qSUeGCuEM/je/wg/IS836ubd/kOk4R8Mv2yzM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=jET+S+XO; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="jET+S+XO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1780086726; bh=9dhz5D1a0Ksv2nfOCHB6O5HOpDxXY+m49njNGjn9knQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jET+S+XOKIwlGDn3p9uF4Bqxygg9yWYu2JyjNw1ktmSRfMVJvFWd7RT9rRILEwCZE 44P/Yq9s0HQf0zc5raGKh5NggeTjL5Up9o6zAthO656A1V4mso484LoCy5QSwD4ocb SYMif3iZodMf/t0LPi4dD0dj/Ye7Mbtdt5N0RXno= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Fri, 29 May 2026 22:31:52 +0200 Subject: [PATCH 1/5] hwmon: (cros_ec) Implement custom kelvin to celsius conversions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260529-cros_ec-hwmon-fan-curve-v1-1-da6792b3830f@weissschuh.net> References: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> In-Reply-To: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> To: Guenter Roeck , Benson Leung , Shuah Khan Cc: Guenter Roeck , chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780086726; l=2067; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=9dhz5D1a0Ksv2nfOCHB6O5HOpDxXY+m49njNGjn9knQ=; b=t6zV1I7u0qOz71i5ZZNII8yQZZHNU+cgLiLNE+o04Ee69DBaUNYOQ/vMHLWC8AMxOdmizsz97 lG/f6RXJBFRCddiP8rAfUPMyuI2M70uKcsdngpqgfwp6YXbRxo1m70+ X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= The ChromeOS EC APIs use integers representing degrees kelvin for temperatures. The default conversions from linux/units.h will then always convert these integer degrees celsius with a 150 millidegree offset. This is a bit confusing, as it also differs from other CrOS EC tooling. Internally the EC uses a kelvin to celsius offset of a round 273, so the current conversion is also not entirely accurate. Implement a custom conversion which preserves round values. Signed-off-by: Thomas Wei=C3=9Fschuh --- drivers/hwmon/cros_ec_hwmon.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 7c308b0a4b9e..f1b6c9c2d2a3 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -147,9 +147,23 @@ static bool cros_ec_hwmon_is_error_temp(u8 temp) temp =3D=3D EC_TEMP_SENSOR_NOT_CALIBRATED; } =20 +/* This differs slightly from the variant in units.h to avoid rounding inc= onsistencies. */ +#define CROS_EC_HWMON_ABSOLUTE_ZERO_MILLICELSIUS (-273000) + +static long cros_ec_hwmon_kelvin_to_millicelsius(long t) +{ + return t * MILLIDEGREE_PER_DEGREE + CROS_EC_HWMON_ABSOLUTE_ZERO_MILLICELS= IUS; +} + +static long cros_ec_hwmon_millicelsius_to_kelvin(long t) +{ + return DIV_ROUND_CLOSEST(t - CROS_EC_HWMON_ABSOLUTE_ZERO_MILLICELSIUS, + MILLIDEGREE_PER_DEGREE); +} + static long cros_ec_hwmon_temp_to_millicelsius(u8 temp) { - return kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSOR_OFFSET)); + return cros_ec_hwmon_kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSO= R_OFFSET)); } =20 static bool cros_ec_hwmon_attr_is_temp_threshold(u32 attr) @@ -228,7 +242,7 @@ static int cros_ec_hwmon_read(struct device *dev, enum = hwmon_sensor_types type, cros_ec_hwmon_attr_to_thres(attr), &threshold); if (ret =3D=3D 0) - *val =3D kelvin_to_millicelsius(threshold); + *val =3D cros_ec_hwmon_kelvin_to_millicelsius(threshold); } } =20 --=20 2.54.0 From nobody Mon Jun 8 09:53:01 2026 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A13003769E7; Fri, 29 May 2026 20:32:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; cv=none; b=JurBylQ35MxQERc/rJatFh9Sax1czeC8Qtih03nc9vtzxtGkVcHf1AobhgGzyQ5sy1qUVc7acWh33Hk0L1l03vkLetbezbuxh9uyu98zs5eeafD8TXM3bxvuU4fRRxjIhdS0raCu/eS+RsyydcOD/cg3qahopIDGK26dVFsewHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; c=relaxed/simple; bh=y9mUKi//PlqZu2QSuyKWMN9pMtbs4+4wS0GlSxHpeSU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kcvxztDZ11+kHKLNw/RT5XaSDzrqPGGsbWIWOD9LmqujhB6G7P9p+OFSaKmDrg3F8HYuWIX8poT1qLGuOcg7vbA12g6TY/cpekBCcK0O3bcDByQYzysY69vK78+/mn9nIUDNnm6esF1XP8n65qdgMY1g1L98tFa0+T/jwZ0FgKc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=nH+xZrNJ; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="nH+xZrNJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1780086726; bh=y9mUKi//PlqZu2QSuyKWMN9pMtbs4+4wS0GlSxHpeSU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nH+xZrNJpZnam2AvbXeZpFHajCPHLvtn/hmoU8tD1Bm3nnxWQSjPU577lsN6bAspU i2y95W/GG46c6dBAkRIaYmVEzMqPsaiaPzBKs0KaT2CwLwKn3OsseHEVpkO5KSXWpE OxTqfU49f4ifRv0mCitfODq6YSGXvSAp7eCFz9kI= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Fri, 29 May 2026 22:31:53 +0200 Subject: [PATCH 2/5] hwmon: (cros_ec) Prepare the addition of custom groups Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260529-cros_ec-hwmon-fan-curve-v1-2-da6792b3830f@weissschuh.net> References: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> In-Reply-To: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> To: Guenter Roeck , Benson Leung , Shuah Khan Cc: Guenter Roeck , chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780086726; l=1185; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=y9mUKi//PlqZu2QSuyKWMN9pMtbs4+4wS0GlSxHpeSU=; b=QigvaSdZKf2GXxy3SgGLjEaN2QhCsV8opJ9veA/GK9z5dX7MSgqzPooqcoXwfEexEAb0IZctb q/eXuxm3HMEAQx9K2y4pYHRQUg1wwNO7uQ+3Yw20+zv8JbMuZFjOrOH X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= An upcoming change will add a custom sysfs attribute group. Set up the scaffolding for that. Signed-off-by: Thomas Wei=C3=9Fschuh --- drivers/hwmon/cros_ec_hwmon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index f1b6c9c2d2a3..932e45caba9c 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -402,6 +402,10 @@ static const struct hwmon_channel_info * const cros_ec= _hwmon_info[] =3D { NULL }; =20 +static const struct attribute_group *cros_ec_hwmon_groups[] =3D { + NULL +}; + static int cros_ec_hwmon_cooling_get_max_state(struct thermal_cooling_devi= ce *cdev, unsigned long *val) { @@ -588,7 +592,8 @@ static int cros_ec_hwmon_probe(struct platform_device *= pdev) cros_ec_hwmon_register_fan_cooling_devices(dev, priv); =20 hwmon_dev =3D devm_hwmon_device_register_with_info(dev, "cros_ec", priv, - &cros_ec_hwmon_chip_info, NULL); + &cros_ec_hwmon_chip_info, + cros_ec_hwmon_groups); platform_set_drvdata(pdev, priv); =20 return PTR_ERR_OR_ZERO(hwmon_dev); --=20 2.54.0 From nobody Mon Jun 8 09:53:01 2026 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7808426ECF; Fri, 29 May 2026 20:32:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086733; cv=none; b=aDpuv0zdwfm5vylnsfC31+roHE3PLBn+F8dyp/BlJ9i2RtXVN9yNG6FOGNU1/MLFCkkMzuFibKttqKIsycpNAIhwhQg10d9niVtl5HkAt1h6pJl3s+OUJoVsx9K1smSkXW26gVWBWCzPKgG4gnAP8GJ32z4Ai7SR0JlH8/wJz+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086733; c=relaxed/simple; bh=3QsUbMpVUkArcusVPY5UErnvHj9XVnkKMZ9qLaQv+ec=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oA0OnJ366E7EfEw3lWO30OAd4kRlFuOvL4TQszBunpt/2qfGSrPJEcDHivVsOW8f9hoYXxHQIPKbtx8X6dpU+fkf7ZGtM0cJ22h7ixwK6Rb87IIkoPYBZptfYbmq78AMhSeOkg5CRUD6ZXTWHgXhw/RNS6gNWRIHIK+svuA3fqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=ZUYZ4HwK; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="ZUYZ4HwK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1780086726; bh=3QsUbMpVUkArcusVPY5UErnvHj9XVnkKMZ9qLaQv+ec=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZUYZ4HwKdBPDloKDwUIuUqtWK46h579aQ1iG0VO40wAPg8nIJlQ0HW832gCJ/Ol+w UP9/5ZWgUXG5zea3LqjvOfVRjcdmilYE9qViwLZTyCk05txHIl06PobzHcmONxxZVB lpTiH+Br/j1wrxYyG6/DgVE8+Pg4ayOjvqDbRRso= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Fri, 29 May 2026 22:31:54 +0200 Subject: [PATCH 3/5] hwmon: (cros_ec) Split out cros_ec_hwmon_get_thermal_config() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260529-cros_ec-hwmon-fan-curve-v1-3-da6792b3830f@weissschuh.net> References: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> In-Reply-To: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> To: Guenter Roeck , Benson Leung , Shuah Khan Cc: Guenter Roeck , chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780086726; l=1631; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=3QsUbMpVUkArcusVPY5UErnvHj9XVnkKMZ9qLaQv+ec=; b=hBk5vPotZsuEiZk110/iVOK7EQrmj929+wBI5/BxszFadaZ0liGYn8nHDSKxfVOoE5xmktH/W cjaE7fFQQl4DKZz55N2xrxKMP+zk8utw/pdeXW/YeWrG/uaBMdpAXtd X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= Some upcoming changes require access to the raw 'struct ec_thermal_config'. Split out the logic to get it from the EC into a new helper. Signed-off-by: Thomas Wei=C3=9Fschuh --- drivers/hwmon/cros_ec_hwmon.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 932e45caba9c..a6cc909e56b7 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -117,19 +117,31 @@ static int cros_ec_hwmon_read_temp(struct cros_ec_dev= ice *cros_ec, u8 index, u8 return 0; } =20 -static int cros_ec_hwmon_read_temp_threshold(struct cros_ec_device *cros_e= c, u8 index, - enum ec_temp_thresholds threshold, u32 *temp) +static int cros_ec_hwmon_get_thermal_config(struct cros_ec_device *cros_ec= , u8 index, + struct ec_thermal_config *config) { struct ec_params_thermal_get_threshold_v1 req =3D {}; - struct ec_thermal_config resp; int ret; =20 req.sensor_num =3D index; ret =3D cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_GET_THRESHOLD, - &req, sizeof(req), &resp, sizeof(resp)); + &req, sizeof(req), config, sizeof(*config)); if (ret < 0) return ret; =20 + return 0; +} + +static int cros_ec_hwmon_read_temp_threshold(struct cros_ec_device *cros_e= c, u8 index, + enum ec_temp_thresholds threshold, u32 *temp) +{ + struct ec_thermal_config resp; + int ret; + + ret =3D cros_ec_hwmon_get_thermal_config(cros_ec, index, &resp); + if (ret) + return ret; + *temp =3D resp.temp_host[threshold]; return 0; } --=20 2.54.0 From nobody Mon Jun 8 09:53:01 2026 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C179C40C5B0; Fri, 29 May 2026 20:32:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; cv=none; b=Jl8GhXJB4E8Y2AICNbdeY6dtF0aN4Ew8tplaIj3ybeY56o6qb3/ufMrzse04cEiiKP17Jh4bUfWorRHJicqBoFaESkKkGlYGUz3Xi1t8dSBycZYrkkaL5dP9kvalxoIz7KWt8wMe/5SKrMP2iq7JtUvh16Ghqh6CyTk6UrtkCv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086730; c=relaxed/simple; bh=x4m5aMe8NaCbr7VItgqtb5OnFt/0Y9A57oQd9W+rVoU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M7F/NC87O/znv+n+we1VpHRztClcNVNcCoAp5SpSYVqMuBscFzSzEpmP221UHBe1pVjxfd8tlz54qrWf/KrmtWRKDKlAXGrdAfeG/mnXb8sPkw9mD9kkP+AfG7i85y7YzwtxVeoCoJdl+mDLEw88wmToj2aFMH8ThN82DEALN4M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=Eu327Uzt; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="Eu327Uzt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1780086726; bh=x4m5aMe8NaCbr7VItgqtb5OnFt/0Y9A57oQd9W+rVoU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Eu327Uztx0i8QLZ6Aam9bssYgLn6vr0svyCiAu03cnIp7vLpuzZs+Rbgh0tnmwl77 FOAQF942awP2x6i+ZbPaNCr045BakulCeuPf13GIXZCmWLkuXNVdfm5nUce4ReIPLQ fgOXPlHG9fN9JZEyFJP9do9WsC2jTqJo7iXllgcg= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Fri, 29 May 2026 22:31:55 +0200 Subject: [PATCH 4/5] hwmon: (cros_ec) Add support for displaying fan curves Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260529-cros_ec-hwmon-fan-curve-v1-4-da6792b3830f@weissschuh.net> References: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> In-Reply-To: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> To: Guenter Roeck , Benson Leung , Shuah Khan Cc: Guenter Roeck , chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780086726; l=7273; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=x4m5aMe8NaCbr7VItgqtb5OnFt/0Y9A57oQd9W+rVoU=; b=ZMqBcAvPUg/sDCYfR+m7h8wq6n7sRd0qMXmgtKBCzby5jQxBphG4AoDtpZyt7PhwF4gHbjwO5 H0x9qXCc0+7CEidbNO70gVjGNAVfqTqSQ6mJjLe119ZzSpZa38RoDSy X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= The automatic fan control mode of the embedded controller uses fan curves with two trigger points to calculate the target fan speed. All temperature sensors affect all fans. Expose these fan curves through the standard hwmon sysfs ABI. Signed-off-by: Thomas Wei=C3=9Fschuh --- Documentation/hwmon/cros_ec_hwmon.rst | 3 + drivers/hwmon/cros_ec_hwmon.c | 139 ++++++++++++++++++++++++++++++= ++++ 2 files changed, 142 insertions(+) diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cr= os_ec_hwmon.rst index 9ccab721e7c2..7a8683227252 100644 --- a/Documentation/hwmon/cros_ec_hwmon.rst +++ b/Documentation/hwmon/cros_ec_hwmon.rst @@ -46,3 +46,6 @@ PWM fan control =20 If a fan is controllable, this driver will register that fan as a cool= ing device in the thermal framework as well. + +Fan curves: + If supported by the EC. Reading only. diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index a6cc909e56b7..731143f8c6b2 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -7,6 +7,7 @@ =20 #include #include +#include #include #include #include @@ -17,6 +18,8 @@ #include #include =20 +#define to_dev_attr(_attr) container_of_const(_attr, struct device_attribu= te, attr) + #define DRV_NAME "cros-ec-hwmon" =20 #define CROS_EC_HWMON_PWM_GET_FAN_DUTY_CMD_VERSION 0 @@ -372,6 +375,141 @@ static umode_t cros_ec_hwmon_is_visible(const void *d= ata, enum hwmon_sensor_type return 0; } =20 +static bool cros_ec_hwmon_attr_is_temp_fan_off(const struct sensor_device_= attribute_2 *attr) +{ + return attr->nr =3D=3D 0; +} + +static ssize_t temp_auto_point_pwm_show(struct device *dev, struct device_= attribute *attr, + char *buf) +{ + struct sensor_device_attribute_2 *sattr =3D to_sensor_dev_attr_2(attr); + + if (cros_ec_hwmon_attr_is_temp_fan_off(sattr)) + return sysfs_emit(buf, "0\n"); + else /* temp_fan_max */ + return sysfs_emit(buf, "255\n"); +} + +static ssize_t temp_auto_point_temp_show(struct device *dev, struct device= _attribute *attr, + char *buf) +{ + struct sensor_device_attribute_2 *sattr =3D to_sensor_dev_attr_2(attr); + struct cros_ec_hwmon_priv *priv =3D dev_get_drvdata(dev); + struct ec_thermal_config config; + u32 temp; + int ret; + + scoped_guard(hwmon_lock, dev) { + ret =3D cros_ec_hwmon_get_thermal_config(priv->cros_ec, sattr->index, &c= onfig); + if (ret) + return ret; + } + + if (cros_ec_hwmon_attr_is_temp_fan_off(sattr)) + temp =3D config.temp_fan_off; + else /* temp_fan_max */ + temp =3D config.temp_fan_max; + + if (temp =3D=3D 0) + return -ENODATA; + + return sysfs_emit(buf, "%ld\n", cros_ec_hwmon_kelvin_to_millicelsius(temp= )); +} + +#define CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(_idx) \ + static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point1_pwm, \ + temp_auto_point_pwm, 0, (_idx) - 1); \ + static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point2_pwm, \ + temp_auto_point_pwm, 1, (_idx) - 1); \ + static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point1_temp, \ + temp_auto_point_temp, 0, (_idx) - 1); \ + static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point2_temp, \ + temp_auto_point_temp, 1, (_idx) - 1) \ + +#define CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(_idx) \ + &sensor_dev_attr_temp ## _idx ## _auto_point1_pwm.dev_attr.attr, \ + &sensor_dev_attr_temp ## _idx ## _auto_point1_temp.dev_attr.attr, \ + &sensor_dev_attr_temp ## _idx ## _auto_point2_pwm.dev_attr.attr, \ + &sensor_dev_attr_temp ## _idx ## _auto_point2_temp.dev_attr.attr \ + +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(1); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(2); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(3); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(4); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(5); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(6); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(7); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(8); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(9); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(10); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(11); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(12); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(13); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(14); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(15); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(16); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(17); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(18); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(19); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(20); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(21); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(22); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(23); +CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(24); + +static struct attribute *cros_ec_hwmon_fan_curve_attrs[] =3D { + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(1), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(2), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(3), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(4), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(5), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(6), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(7), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(8), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(9), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(10), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(11), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(12), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(13), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(14), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(15), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(16), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(17), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(18), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(19), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(20), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(21), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(22), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(23), + CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(24), + NULL +}; + +static_assert(ARRAY_SIZE(cros_ec_hwmon_fan_curve_attrs) =3D=3D + ARRAY_SIZE(((struct cros_ec_hwmon_priv *)NULL)->temp_sensor_names) = * 4 + 1); + +static umode_t cros_ec_hwmon_fan_curve_is_visible(struct kobject *kobj, + struct attribute *attr, int idx) +{ + struct sensor_device_attribute_2 *sattr =3D to_sensor_dev_attr_2(to_dev_a= ttr(attr)); + struct device *dev =3D kobj_to_dev(kobj); + struct cros_ec_hwmon_priv *priv =3D dev_get_drvdata(dev); + + if (!priv->temp_threshold_supported) + return 0; + + if (!priv->temp_sensor_names[sattr->index]) + return 0; + + return attr->mode; +} + +static const struct attribute_group cros_ec_hwmon_fan_curve_group =3D { + .attrs =3D cros_ec_hwmon_fan_curve_attrs, + .is_visible =3D cros_ec_hwmon_fan_curve_is_visible, +}; + static const struct hwmon_channel_info * const cros_ec_hwmon_info[] =3D { HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), HWMON_CHANNEL_INFO(fan, @@ -415,6 +553,7 @@ static const struct hwmon_channel_info * const cros_ec_= hwmon_info[] =3D { }; =20 static const struct attribute_group *cros_ec_hwmon_groups[] =3D { + &cros_ec_hwmon_fan_curve_group, NULL }; =20 --=20 2.54.0 From nobody Mon Jun 8 09:53:01 2026 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 264674218A3; Fri, 29 May 2026 20:32:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086731; cv=none; b=B8qkZ0SvhV+OG5ePt1IrWMQdA9A89AgpDDrQRqpLwZJeog1pSYGrV1ij++jZqliXVusiNiEOLGeR8gjR356CyS/4ZYIvo6DdB6SdMMFoLTg/VTGnaH0Nn4YgvATidtTqeyg4mmDdc1uY1kFstldWVffQw7Ol2cKx1LyWgQ1OMl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780086731; c=relaxed/simple; bh=QZvBUP1hs/bohg2wpRQ1DiYUpKav0hya0+CvfYNx0H0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=G5yfXMl1kFN3qn4rlB8aK22L+zpr8OcBimAT1RSYjb3yN+84hWMU6Q1YhBQ2oWMK3L6iq1T8OiBO6Eewg80q/PSR42rYYz72o85EW4N7mpYlyC82BjMlT3QZKzCGUmQWUFVLyWppvonOlmVbviDSElHrCYq5ZWST7sDa4BwEnvQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=D06kodnv; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="D06kodnv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1780086727; bh=QZvBUP1hs/bohg2wpRQ1DiYUpKav0hya0+CvfYNx0H0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=D06kodnvV46PJ10fqgMLc95Z69+PWsi83QkCrEJacQaFTvBODDeDypcCitX8J2Zev I6Z/N6f9/vO9AztWnsGKGDwsgbak4TPCoxwGhFUv2bdNsLdlLfLG1Qbdk1mL2ZgTpi vPXBQTwG5u74FmnYCBpcoRaaPOrMXJzwcy/9uVZ8= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Fri, 29 May 2026 22:31:56 +0200 Subject: [PATCH 5/5] hwmon: (cros_ec) Allow modification of fan curves Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260529-cros_ec-hwmon-fan-curve-v1-5-da6792b3830f@weissschuh.net> References: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> In-Reply-To: <20260529-cros_ec-hwmon-fan-curve-v1-0-da6792b3830f@weissschuh.net> To: Guenter Roeck , Benson Leung , Shuah Khan Cc: Guenter Roeck , chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780086726; l=4312; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=QZvBUP1hs/bohg2wpRQ1DiYUpKav0hya0+CvfYNx0H0=; b=BoF9oYNY5sX5IFEw40Hio3ttzYXeEvRjjyW7S4GYoDMs/hK2stzPIgKWEqxffWPu+MDaIIrRj /0PCHiamk+8D0W1B36ENM7O9BhaREmQnALbqWzbRT+EINhb0TZpwc4e X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= The fan curves used by the embedded controller can be configured. Expose this through the standard hwmon sysfs ABI. Only allow the curves to be made more aggressive than the current ones. Signed-off-by: Thomas Wei=C3=9Fschuh --- Documentation/hwmon/cros_ec_hwmon.rst | 2 +- drivers/hwmon/cros_ec_hwmon.c | 68 +++++++++++++++++++++++++++++++= ++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cr= os_ec_hwmon.rst index 7a8683227252..a3d0e43c8833 100644 --- a/Documentation/hwmon/cros_ec_hwmon.rst +++ b/Documentation/hwmon/cros_ec_hwmon.rst @@ -48,4 +48,4 @@ PWM fan control in the thermal framework as well. =20 Fan curves: - If supported by the EC. Reading only. + If supported by the EC. Reading and writing. diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 731143f8c6b2..fb73a00ebeeb 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -135,6 +137,22 @@ static int cros_ec_hwmon_get_thermal_config(struct cro= s_ec_device *cros_ec, u8 i return 0; } =20 +static int cros_ec_hwmon_set_thermal_config(struct cros_ec_device *cros_ec= , u8 index, + const struct ec_thermal_config *config) +{ + struct ec_params_thermal_set_threshold_v1 req =3D {}; + int ret; + + req.sensor_num =3D index; + req.cfg =3D *config; + ret =3D cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_SET_THRESHOLD, + &req, sizeof(req), NULL, 0); + if (ret < 0) + return ret; + + return 0; +} + static int cros_ec_hwmon_read_temp_threshold(struct cros_ec_device *cros_e= c, u8 index, enum ec_temp_thresholds threshold, u32 *temp) { @@ -417,14 +435,60 @@ static ssize_t temp_auto_point_temp_show(struct devic= e *dev, struct device_attri return sysfs_emit(buf, "%ld\n", cros_ec_hwmon_kelvin_to_millicelsius(temp= )); } =20 +static ssize_t temp_auto_point_temp_store(struct device *dev, struct devic= e_attribute *attr, + const char *buf, size_t size) +{ + struct sensor_device_attribute_2 *sattr =3D to_sensor_dev_attr_2(attr); + struct cros_ec_hwmon_priv *priv =3D dev_get_drvdata(dev); + struct ec_thermal_config config; + u32 *temp_field; + s64 temp; + int ret; + + ret =3D kstrtos64(buf, 10, &temp); + if (ret) + return ret; + + temp =3D cros_ec_hwmon_millicelsius_to_kelvin(temp); + + if (overflows_type(temp, config.temp_fan_off)) + return -ERANGE; + + guard(hwmon_lock)(dev); + + ret =3D cros_ec_hwmon_get_thermal_config(priv->cros_ec, sattr->index, &co= nfig); + if (ret) + return ret; + + if (cros_ec_hwmon_attr_is_temp_fan_off(sattr)) + temp_field =3D &config.temp_fan_off; + else /* temp_fan_max */ + temp_field =3D &config.temp_fan_max; + + /* Only allow values which are more aggressive than the current ones */ + if (temp > *temp_field) + return -EINVAL; + + *temp_field =3D temp; + + if (config.temp_fan_off > config.temp_fan_max) + return -EINVAL; + + ret =3D cros_ec_hwmon_set_thermal_config(priv->cros_ec, sattr->index, &co= nfig); + if (ret) + return ret; + + return size; +} + #define CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS(_idx) \ static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point1_pwm, \ temp_auto_point_pwm, 0, (_idx) - 1); \ static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point2_pwm, \ temp_auto_point_pwm, 1, (_idx) - 1); \ - static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point1_temp, \ + static SENSOR_DEVICE_ATTR_2_RW(temp ## _idx ## _auto_point1_temp, \ temp_auto_point_temp, 0, (_idx) - 1); \ - static SENSOR_DEVICE_ATTR_2_RO(temp ## _idx ## _auto_point2_temp, \ + static SENSOR_DEVICE_ATTR_2_RW(temp ## _idx ## _auto_point2_temp, \ temp_auto_point_temp, 1, (_idx) - 1) \ =20 #define CROS_EC_HWMON_TEMP_AUTO_POINT_ATTRS_PTRS(_idx) \ --=20 2.54.0