]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (cros_ec) Add support for fan target speed
authorThomas Weißschuh <linux@weissschuh.net>
Sun, 18 Jan 2026 09:45:56 +0000 (10:45 +0100)
committerGuenter Roeck <linux@roeck-us.net>
Sat, 31 Jan 2026 15:38:33 +0000 (07:38 -0800)
Use EC_CMD_PWM_GET_FAN_TARGET_RPM to retrieve the target fan speed.
The EC only supports this for the first fan.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20260118-cros_ec-hwmon-pwm-v2-2-77eb1709b031@weissschuh.net
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Documentation/hwmon/cros_ec_hwmon.rst
drivers/hwmon/cros_ec_hwmon.c

index b7dc88d22fdaef0a998879ebb07f899f08163def..ebc8da48fa8a2aa3a8e1449f82f5c199bd88e6dd 100644 (file)
@@ -29,6 +29,9 @@ Supported features
 Fan readings
     Always supported.
 
+Fan target speed
+    If supported by the EC.
+
 Temperature readings
     Always supported.
 
index 48331703f2f50decf245805d735de39105e5f39f..53abd55cba05883b0046744a8ee0c8d17ddd1c40 100644 (file)
@@ -86,6 +86,20 @@ static int cros_ec_hwmon_read_pwm_enable(struct cros_ec_device *cros_ec, u8 inde
        return 0;
 }
 
+static int cros_ec_hwmon_read_fan_target(struct cros_ec_device *cros_ec, u16 *speed)
+{
+       struct ec_response_pwm_get_fan_rpm resp;
+       int ret;
+
+       ret = cros_ec_cmd(cros_ec, 0, EC_CMD_PWM_GET_FAN_TARGET_RPM,
+                         NULL, 0, &resp, sizeof(resp));
+       if (ret < 0)
+               return ret;
+
+       *speed = resp.rpm;
+       return 0;
+}
+
 static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp)
 {
        unsigned int offset;
@@ -143,6 +157,11 @@ static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
                        ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed);
                        if (ret == 0)
                                *val = cros_ec_hwmon_is_error_fan(speed);
+
+               } else if (attr == hwmon_fan_target) {
+                       ret = cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed);
+                       if (ret == 0)
+                               *val = speed;
                }
        } else if (type == hwmon_pwm) {
                if (attr == hwmon_pwm_enable) {
@@ -259,8 +278,13 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type
                                        u32 attr, int channel)
 {
        const struct cros_ec_hwmon_priv *priv = data;
+       u16 speed;
 
        if (type == hwmon_fan) {
+               if (attr == hwmon_fan_target &&
+                   cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed) == -EOPNOTSUPP)
+                       return 0;
+
                if (priv->usable_fans & BIT(channel))
                        return 0444;
        } else if (type == hwmon_pwm) {
@@ -277,7 +301,7 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type
 static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = {
        HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
        HWMON_CHANNEL_INFO(fan,
-                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_TARGET,
                           HWMON_F_INPUT | HWMON_F_FAULT,
                           HWMON_F_INPUT | HWMON_F_FAULT,
                           HWMON_F_INPUT | HWMON_F_FAULT),