hwmon: (cros_ec) Add support for fan target speed

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>
This commit is contained in:
Thomas Weißschuh 2026-01-18 10:45:56 +01:00 committed by Guenter Roeck
parent 18ccf48656
commit bd7a455aee
2 changed files with 28 additions and 1 deletions

View file

@ -29,6 +29,9 @@ Supported features
Fan readings
Always supported.
Fan target speed
If supported by the EC.
Temperature readings
Always supported.

View 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),