Skip to content

Commit afa7c56

Browse files
t-8chgroeck
authored andcommitted
hwmon: (cros_ec) Add support for temperature thresholds
Implement reading temperature thresholds through EC_CMD_THERMAL_GET_THRESHOLD/EC_CMD_THERMAL_SET_THRESHOLD. Thresholds are mapped as follows between the EC and hwmon: hwmon_temp_max - EC_TEMP_THRESH_WARN hwmon_temp_crit - EC_TEMP_THRESH_HIGH hwmon_temp_emergency - EC_TEMP_THRESH_HALT 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-4-77eb1709b031@weissschuh.net [groeck: Rearrange code to no longer use unreachable() since that causes a hiccup with some versions of gcc and objtool] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent 11c5802 commit afa7c56

2 files changed

Lines changed: 57 additions & 3 deletions

File tree

Documentation/hwmon/cros_ec_hwmon.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Fan target speed
3535
Temperature readings
3636
Always supported.
3737

38+
Temperature thresholds
39+
If supported by the EC.
40+
3841
PWM fan control
3942
If the EC also supports setting fan PWM values and fan mode.
4043

drivers/hwmon/cros_ec_hwmon.c

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct cros_ec_hwmon_priv {
2828
const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES];
2929
u8 usable_fans;
3030
bool fan_control_supported;
31+
bool temp_threshold_supported;
3132
u8 manual_fans; /* bits to indicate whether the fan is set to manual */
3233
u8 manual_fan_pwm[EC_FAN_SPEED_ENTRIES];
3334
};
@@ -116,6 +117,23 @@ static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8
116117
return 0;
117118
}
118119

120+
static int cros_ec_hwmon_read_temp_threshold(struct cros_ec_device *cros_ec, u8 index,
121+
enum ec_temp_thresholds threshold, u32 *temp)
122+
{
123+
struct ec_params_thermal_get_threshold_v1 req = {};
124+
struct ec_thermal_config resp;
125+
int ret;
126+
127+
req.sensor_num = index;
128+
ret = cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_GET_THRESHOLD,
129+
&req, sizeof(req), &resp, sizeof(resp));
130+
if (ret < 0)
131+
return ret;
132+
133+
*temp = resp.temp_host[threshold];
134+
return 0;
135+
}
136+
119137
static bool cros_ec_hwmon_is_error_fan(u16 speed)
120138
{
121139
return speed == EC_FAN_SPEED_NOT_PRESENT || speed == EC_FAN_SPEED_STALLED;
@@ -134,12 +152,29 @@ static long cros_ec_hwmon_temp_to_millicelsius(u8 temp)
134152
return kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSOR_OFFSET));
135153
}
136154

155+
static bool cros_ec_hwmon_attr_is_temp_threshold(u32 attr)
156+
{
157+
return attr == hwmon_temp_max ||
158+
attr == hwmon_temp_crit ||
159+
attr == hwmon_temp_emergency;
160+
}
161+
162+
static enum ec_temp_thresholds cros_ec_hwmon_attr_to_thres(u32 attr)
163+
{
164+
if (attr == hwmon_temp_max)
165+
return EC_TEMP_THRESH_WARN;
166+
else if (attr == hwmon_temp_crit)
167+
return EC_TEMP_THRESH_HIGH;
168+
return EC_TEMP_THRESH_HALT; /* attr == hwmon_temp_emergency */
169+
}
170+
137171
static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
138172
u32 attr, int channel, long *val)
139173
{
140174
struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev);
141175
int ret = -EOPNOTSUPP;
142176
u8 control_method;
177+
u32 threshold;
143178
u8 pwm_value;
144179
u16 speed;
145180
u8 temp;
@@ -187,6 +222,13 @@ static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
187222
ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp);
188223
if (ret == 0)
189224
*val = cros_ec_hwmon_is_error_temp(temp);
225+
226+
} else if (cros_ec_hwmon_attr_is_temp_threshold(attr)) {
227+
ret = cros_ec_hwmon_read_temp_threshold(priv->cros_ec, channel,
228+
cros_ec_hwmon_attr_to_thres(attr),
229+
&threshold);
230+
if (ret == 0)
231+
*val = kelvin_to_millicelsius(threshold);
190232
}
191233
}
192234

@@ -291,8 +333,14 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type
291333
if (priv->fan_control_supported && priv->usable_fans & BIT(channel))
292334
return 0644;
293335
} else if (type == hwmon_temp) {
294-
if (priv->temp_sensor_names[channel])
295-
return 0444;
336+
if (priv->temp_sensor_names[channel]) {
337+
if (cros_ec_hwmon_attr_is_temp_threshold(attr)) {
338+
if (priv->temp_threshold_supported)
339+
return 0444;
340+
} else {
341+
return 0444;
342+
}
343+
}
296344
}
297345

298346
return 0;
@@ -310,7 +358,8 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = {
310358
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
311359
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
312360
HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
313-
#define CROS_EC_HWMON_TEMP_PARAMS (HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL)
361+
#define CROS_EC_HWMON_TEMP_PARAMS (HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL | \
362+
HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_EMERGENCY)
314363
HWMON_CHANNEL_INFO(temp,
315364
CROS_EC_HWMON_TEMP_PARAMS,
316365
CROS_EC_HWMON_TEMP_PARAMS,
@@ -520,6 +569,8 @@ static int cros_ec_hwmon_probe(struct platform_device *pdev)
520569
cros_ec_hwmon_probe_temp_sensors(dev, priv, thermal_version);
521570
cros_ec_hwmon_probe_fans(priv);
522571
priv->fan_control_supported = cros_ec_hwmon_probe_fan_control_supported(priv->cros_ec);
572+
priv->temp_threshold_supported = is_cros_ec_cmd_available(priv->cros_ec,
573+
EC_CMD_THERMAL_GET_THRESHOLD, 1);
523574
cros_ec_hwmon_register_fan_cooling_devices(dev, priv);
524575

525576
hwmon_dev = devm_hwmon_device_register_with_info(dev, "cros_ec", priv,

0 commit comments

Comments
 (0)