From: Sung-Chi Li via B4 Relay <devnull+lschyi.google.com@kernel.org>
To: "Benson Leung" <bleung@chromium.org>,
"Guenter Roeck" <groeck@chromium.org>,
"Thomas Weißschuh" <linux@weissschuh.net>,
"Guenter Roeck" <linux@roeck-us.net>,
"Jonathan Corbet" <corbet@lwn.net>
Cc: chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org,
Sung-Chi Li <lschyi@google.com>,
Sung-Chi Li <lschyi@chromium.org>
Subject: [PATCH v6 3/3] hwmon: (cros_ec) register fans into thermal framework cooling devices
Date: Thu, 11 Sep 2025 06:56:36 +0000 [thread overview]
Message-ID: <20250911-cros_ec_fan-v6-3-a1446cc098af@google.com> (raw)
In-Reply-To: <20250911-cros_ec_fan-v6-0-a1446cc098af@google.com>
From: Sung-Chi Li <lschyi@chromium.org>
Register fans connected under EC as thermal cooling devices as well, so
these fans can then work with the thermal framework.
During the driver probing phase, we will also try to register each fan
as a thermal cooling device based on previous probe result (whether the
there are fans connected on that channel, and whether EC supports fan
control). The basic get max state, get current state, and set current
state methods are then implemented as well.
Signed-off-by: Sung-Chi Li <lschyi@chromium.org>
Acked-by: Thomas Weißschuh <linux@weissschuh.net>
---
Documentation/hwmon/cros_ec_hwmon.rst | 2 +
drivers/hwmon/cros_ec_hwmon.c | 83 +++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cros_ec_hwmon.rst
index 355557a08c9a54b4c177bafde3743e7dc02218be..6db812708325f7abb6d319af3312b4079e6923c6 100644
--- a/Documentation/hwmon/cros_ec_hwmon.rst
+++ b/Documentation/hwmon/cros_ec_hwmon.rst
@@ -27,3 +27,5 @@ Fan and temperature readings are supported. PWM fan control is also supported if
the EC also supports setting fan PWM values and fan mode. Note that EC will
switch fan control mode back to auto when suspended. This driver will restore
the fan state to what they were before suspended when resumed.
+If a fan is controllable, this driver will register that fan as a cooling device
+in the thermal framework as well.
diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c
index 9eddc554ddefde42f70c09689b64ad9e636a3020..48331703f2f50decf245805d735de39105e5f39f 100644
--- a/drivers/hwmon/cros_ec_hwmon.c
+++ b/drivers/hwmon/cros_ec_hwmon.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
+#include <linux/thermal.h>
#include <linux/types.h>
#include <linux/units.h>
@@ -31,6 +32,11 @@ struct cros_ec_hwmon_priv {
u8 manual_fan_pwm[EC_FAN_SPEED_ENTRIES];
};
+struct cros_ec_hwmon_cooling_priv {
+ struct cros_ec_hwmon_priv *hwmon_priv;
+ u8 index;
+};
+
static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index, u16 *speed)
{
int ret;
@@ -308,6 +314,42 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = {
NULL
};
+static int cros_ec_hwmon_cooling_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *val)
+{
+ *val = 255;
+ return 0;
+}
+
+static int cros_ec_hwmon_cooling_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *val)
+{
+ const struct cros_ec_hwmon_cooling_priv *priv = cdev->devdata;
+ u8 read_val;
+ int ret;
+
+ ret = cros_ec_hwmon_read_pwm_value(priv->hwmon_priv->cros_ec, priv->index, &read_val);
+ if (ret)
+ return ret;
+
+ *val = read_val;
+ return 0;
+}
+
+static int cros_ec_hwmon_cooling_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long val)
+{
+ const struct cros_ec_hwmon_cooling_priv *priv = cdev->devdata;
+
+ return cros_ec_hwmon_write_pwm_input(priv->hwmon_priv->cros_ec, priv->index, val);
+}
+
+static const struct thermal_cooling_device_ops cros_ec_thermal_cooling_ops = {
+ .get_max_state = cros_ec_hwmon_cooling_get_max_state,
+ .get_cur_state = cros_ec_hwmon_cooling_get_cur_state,
+ .set_cur_state = cros_ec_hwmon_cooling_set_cur_state,
+};
+
static const struct hwmon_ops cros_ec_hwmon_ops = {
.read = cros_ec_hwmon_read,
.read_string = cros_ec_hwmon_read_string,
@@ -386,6 +428,46 @@ static bool cros_ec_hwmon_probe_fan_control_supported(struct cros_ec_device *cro
CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION);
}
+static void cros_ec_hwmon_register_fan_cooling_devices(struct device *dev,
+ struct cros_ec_hwmon_priv *priv)
+{
+ struct cros_ec_hwmon_cooling_priv *cpriv;
+ struct thermal_cooling_device *cdev;
+ const char *type;
+ size_t i;
+
+ if (!IS_ENABLED(CONFIG_THERMAL))
+ return;
+
+ if (!priv->fan_control_supported)
+ return;
+
+ for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) {
+ if (!(priv->usable_fans & BIT(i)))
+ continue;
+
+ cpriv = devm_kzalloc(dev, sizeof(*cpriv), GFP_KERNEL);
+ if (!cpriv)
+ continue;
+
+ type = devm_kasprintf(dev, GFP_KERNEL, "%s-fan%zu", dev_name(dev), i);
+ if (!type) {
+ dev_warn(dev, "no memory to compose cooling device type for fan %zu\n", i);
+ continue;
+ }
+
+ cpriv->hwmon_priv = priv;
+ cpriv->index = i;
+ cdev = devm_thermal_of_cooling_device_register(dev, NULL, type, cpriv,
+ &cros_ec_thermal_cooling_ops);
+ if (IS_ERR(cdev)) {
+ dev_warn(dev, "failed to register fan %zu as a cooling device: %pe\n", i,
+ cdev);
+ continue;
+ }
+ }
+}
+
static int cros_ec_hwmon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -413,6 +495,7 @@ static int cros_ec_hwmon_probe(struct platform_device *pdev)
cros_ec_hwmon_probe_temp_sensors(dev, priv, thermal_version);
cros_ec_hwmon_probe_fans(priv);
priv->fan_control_supported = cros_ec_hwmon_probe_fan_control_supported(priv->cros_ec);
+ cros_ec_hwmon_register_fan_cooling_devices(dev, priv);
hwmon_dev = devm_hwmon_device_register_with_info(dev, "cros_ec", priv,
&cros_ec_hwmon_chip_info, NULL);
--
2.51.0.384.g4c02a37b29-goog
next prev parent reply other threads:[~2025-09-11 6:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-11 6:56 [PATCH v6 0/3] Export fan control and register fans as " Sung-Chi Li via B4 Relay
2025-09-11 6:56 ` [PATCH v6 1/3] platform/chrome: update pwm fan control host commands Sung-Chi Li via B4 Relay
2025-09-24 19:30 ` Guenter Roeck
2025-09-11 6:56 ` [PATCH v6 2/3] hwmon: (cros_ec) add PWM control over fans Sung-Chi Li via B4 Relay
2025-09-24 19:31 ` Guenter Roeck
2025-09-11 6:56 ` Sung-Chi Li via B4 Relay [this message]
2025-09-24 19:31 ` [PATCH v6 3/3] hwmon: (cros_ec) register fans into thermal framework cooling devices Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250911-cros_ec_fan-v6-3-a1446cc098af@google.com \
--to=devnull+lschyi.google.com@kernel.org \
--cc=bleung@chromium.org \
--cc=chrome-platform@lists.linux.dev \
--cc=corbet@lwn.net \
--cc=groeck@chromium.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=linux@weissschuh.net \
--cc=lschyi@chromium.org \
--cc=lschyi@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®