1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ChromeOS EC driver for hwmon 4 * 5 * Copyright (C) 2024 Thomas Weißschuh <linux@weissschuh.net> 6 */ 7 8 #include <linux/device.h> 9 #include <linux/hwmon.h> 10 #include <linux/math.h> 11 #include <linux/mod_devicetable.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/platform_data/cros_ec_commands.h> 15 #include <linux/platform_data/cros_ec_proto.h> 16 #include <linux/thermal.h> 17 #include <linux/types.h> 18 #include <linux/units.h> 19 20 #define DRV_NAME "cros-ec-hwmon" 21 22 #define CROS_EC_HWMON_PWM_GET_FAN_DUTY_CMD_VERSION 0 23 #define CROS_EC_HWMON_PWM_SET_FAN_DUTY_CMD_VERSION 1 24 #define CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION 2 25 26 struct cros_ec_hwmon_priv { 27 struct cros_ec_device *cros_ec; 28 const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES]; 29 u8 usable_fans; 30 bool fan_control_supported; 31 bool temp_threshold_supported; 32 u8 manual_fans; /* bits to indicate whether the fan is set to manual */ 33 u8 manual_fan_pwm[EC_FAN_SPEED_ENTRIES]; 34 }; 35 36 struct cros_ec_hwmon_cooling_priv { 37 struct cros_ec_hwmon_priv *hwmon_priv; 38 u8 index; 39 }; 40 41 static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index, u16 *speed) 42 { 43 int ret; 44 __le16 __speed; 45 46 ret = cros_ec_cmd_readmem(cros_ec, EC_MEMMAP_FAN + index * 2, 2, &__speed); 47 if (ret < 0) 48 return ret; 49 50 *speed = le16_to_cpu(__speed); 51 return 0; 52 } 53 54 static int cros_ec_hwmon_read_pwm_value(struct cros_ec_device *cros_ec, u8 index, u8 *pwm_value) 55 { 56 struct ec_params_pwm_get_fan_duty req = { 57 .fan_idx = index, 58 }; 59 struct ec_response_pwm_get_fan_duty resp; 60 int ret; 61 62 ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_PWM_GET_FAN_DUTY_CMD_VERSION, 63 EC_CMD_PWM_GET_FAN_DUTY, &req, sizeof(req), &resp, sizeof(resp)); 64 if (ret < 0) 65 return ret; 66 67 *pwm_value = (u8)DIV_ROUND_CLOSEST(le32_to_cpu(resp.percent) * 255, 100); 68 return 0; 69 } 70 71 static int cros_ec_hwmon_read_pwm_enable(struct cros_ec_device *cros_ec, u8 index, 72 u8 *control_method) 73 { 74 struct ec_params_auto_fan_ctrl_v2 req = { 75 .cmd = EC_AUTO_FAN_CONTROL_CMD_GET, 76 .fan_idx = index, 77 }; 78 struct ec_response_auto_fan_control resp; 79 int ret; 80 81 ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION, 82 EC_CMD_THERMAL_AUTO_FAN_CTRL, &req, sizeof(req), &resp, sizeof(resp)); 83 if (ret < 0) 84 return ret; 85 86 *control_method = resp.is_auto ? 2 : 1; 87 return 0; 88 } 89 90 static int cros_ec_hwmon_read_fan_target(struct cros_ec_device *cros_ec, u16 *speed) 91 { 92 struct ec_response_pwm_get_fan_rpm resp; 93 int ret; 94 95 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_PWM_GET_FAN_TARGET_RPM, 96 NULL, 0, &resp, sizeof(resp)); 97 if (ret < 0) 98 return ret; 99 100 *speed = resp.rpm; 101 return 0; 102 } 103 104 static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp) 105 { 106 unsigned int offset; 107 int ret; 108 109 if (index < EC_TEMP_SENSOR_ENTRIES) 110 offset = EC_MEMMAP_TEMP_SENSOR + index; 111 else 112 offset = EC_MEMMAP_TEMP_SENSOR_B + index - EC_TEMP_SENSOR_ENTRIES; 113 114 ret = cros_ec_cmd_readmem(cros_ec, offset, 1, temp); 115 if (ret < 0) 116 return ret; 117 return 0; 118 } 119 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 137 static bool cros_ec_hwmon_is_error_fan(u16 speed) 138 { 139 return speed == EC_FAN_SPEED_NOT_PRESENT || speed == EC_FAN_SPEED_STALLED; 140 } 141 142 static bool cros_ec_hwmon_is_error_temp(u8 temp) 143 { 144 return temp == EC_TEMP_SENSOR_NOT_PRESENT || 145 temp == EC_TEMP_SENSOR_ERROR || 146 temp == EC_TEMP_SENSOR_NOT_POWERED || 147 temp == EC_TEMP_SENSOR_NOT_CALIBRATED; 148 } 149 150 static long cros_ec_hwmon_temp_to_millicelsius(u8 temp) 151 { 152 return kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSOR_OFFSET)); 153 } 154 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 171 static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 172 u32 attr, int channel, long *val) 173 { 174 struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev); 175 int ret = -EOPNOTSUPP; 176 u8 control_method; 177 u32 threshold; 178 u8 pwm_value; 179 u16 speed; 180 u8 temp; 181 182 if (type == hwmon_fan) { 183 if (attr == hwmon_fan_input) { 184 ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed); 185 if (ret == 0) { 186 if (cros_ec_hwmon_is_error_fan(speed)) 187 ret = -ENODATA; 188 else 189 *val = speed; 190 } 191 } else if (attr == hwmon_fan_fault) { 192 ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed); 193 if (ret == 0) 194 *val = cros_ec_hwmon_is_error_fan(speed); 195 196 } else if (attr == hwmon_fan_target) { 197 ret = cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed); 198 if (ret == 0) 199 *val = speed; 200 } 201 } else if (type == hwmon_pwm) { 202 if (attr == hwmon_pwm_enable) { 203 ret = cros_ec_hwmon_read_pwm_enable(priv->cros_ec, channel, 204 &control_method); 205 if (ret == 0) 206 *val = control_method; 207 } else if (attr == hwmon_pwm_input) { 208 ret = cros_ec_hwmon_read_pwm_value(priv->cros_ec, channel, &pwm_value); 209 if (ret == 0) 210 *val = pwm_value; 211 } 212 } else if (type == hwmon_temp) { 213 if (attr == hwmon_temp_input) { 214 ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp); 215 if (ret == 0) { 216 if (cros_ec_hwmon_is_error_temp(temp)) 217 ret = -ENODATA; 218 else 219 *val = cros_ec_hwmon_temp_to_millicelsius(temp); 220 } 221 } else if (attr == hwmon_temp_fault) { 222 ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp); 223 if (ret == 0) 224 *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); 232 } 233 } 234 235 return ret; 236 } 237 238 static int cros_ec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, 239 u32 attr, int channel, const char **str) 240 { 241 struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev); 242 243 if (type == hwmon_temp && attr == hwmon_temp_label) { 244 *str = priv->temp_sensor_names[channel]; 245 return 0; 246 } 247 248 return -EOPNOTSUPP; 249 } 250 251 static int cros_ec_hwmon_set_fan_pwm_val(struct cros_ec_device *cros_ec, u8 index, u8 val) 252 { 253 struct ec_params_pwm_set_fan_duty_v1 req = { 254 .fan_idx = index, 255 .percent = DIV_ROUND_CLOSEST((uint32_t)val * 100, 255), 256 }; 257 int ret; 258 259 ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_PWM_SET_FAN_DUTY_CMD_VERSION, 260 EC_CMD_PWM_SET_FAN_DUTY, &req, sizeof(req), NULL, 0); 261 if (ret < 0) 262 return ret; 263 return 0; 264 } 265 266 static int cros_ec_hwmon_write_pwm_input(struct cros_ec_device *cros_ec, u8 index, u8 val) 267 { 268 u8 control_method; 269 int ret; 270 271 ret = cros_ec_hwmon_read_pwm_enable(cros_ec, index, &control_method); 272 if (ret) 273 return ret; 274 if (control_method != 1) 275 return -EOPNOTSUPP; 276 277 return cros_ec_hwmon_set_fan_pwm_val(cros_ec, index, val); 278 } 279 280 static int cros_ec_hwmon_write_pwm_enable(struct cros_ec_device *cros_ec, u8 index, u8 val) 281 { 282 struct ec_params_auto_fan_ctrl_v2 req = { 283 .fan_idx = index, 284 .cmd = EC_AUTO_FAN_CONTROL_CMD_SET, 285 }; 286 int ret; 287 288 /* No CrOS EC supports no fan speed control */ 289 if (val == 0) 290 return -EOPNOTSUPP; 291 292 req.set_auto = (val != 1) ? true : false; 293 ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION, 294 EC_CMD_THERMAL_AUTO_FAN_CTRL, &req, sizeof(req), NULL, 0); 295 if (ret < 0) 296 return ret; 297 return 0; 298 } 299 300 static int cros_ec_hwmon_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, 301 int channel, long val) 302 { 303 struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev); 304 305 if (type == hwmon_pwm) { 306 switch (attr) { 307 case hwmon_pwm_input: 308 return cros_ec_hwmon_write_pwm_input(priv->cros_ec, channel, val); 309 case hwmon_pwm_enable: 310 return cros_ec_hwmon_write_pwm_enable(priv->cros_ec, channel, val); 311 default: 312 return -EOPNOTSUPP; 313 } 314 } 315 316 return -EOPNOTSUPP; 317 } 318 319 static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, 320 u32 attr, int channel) 321 { 322 const struct cros_ec_hwmon_priv *priv = data; 323 u16 speed; 324 325 if (type == hwmon_fan) { 326 if (attr == hwmon_fan_target && 327 cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed) == -EOPNOTSUPP) 328 return 0; 329 330 if (priv->usable_fans & BIT(channel)) 331 return 0444; 332 } else if (type == hwmon_pwm) { 333 if (priv->fan_control_supported && priv->usable_fans & BIT(channel)) 334 return 0644; 335 } else if (type == hwmon_temp) { 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 } 344 } 345 346 return 0; 347 } 348 349 static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { 350 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 351 HWMON_CHANNEL_INFO(fan, 352 HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_TARGET, 353 HWMON_F_INPUT | HWMON_F_FAULT, 354 HWMON_F_INPUT | HWMON_F_FAULT, 355 HWMON_F_INPUT | HWMON_F_FAULT), 356 HWMON_CHANNEL_INFO(pwm, 357 HWMON_PWM_INPUT | HWMON_PWM_ENABLE, 358 HWMON_PWM_INPUT | HWMON_PWM_ENABLE, 359 HWMON_PWM_INPUT | HWMON_PWM_ENABLE, 360 HWMON_PWM_INPUT | HWMON_PWM_ENABLE), 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) 363 HWMON_CHANNEL_INFO(temp, 364 CROS_EC_HWMON_TEMP_PARAMS, 365 CROS_EC_HWMON_TEMP_PARAMS, 366 CROS_EC_HWMON_TEMP_PARAMS, 367 CROS_EC_HWMON_TEMP_PARAMS, 368 CROS_EC_HWMON_TEMP_PARAMS, 369 CROS_EC_HWMON_TEMP_PARAMS, 370 CROS_EC_HWMON_TEMP_PARAMS, 371 CROS_EC_HWMON_TEMP_PARAMS, 372 CROS_EC_HWMON_TEMP_PARAMS, 373 CROS_EC_HWMON_TEMP_PARAMS, 374 CROS_EC_HWMON_TEMP_PARAMS, 375 CROS_EC_HWMON_TEMP_PARAMS, 376 CROS_EC_HWMON_TEMP_PARAMS, 377 CROS_EC_HWMON_TEMP_PARAMS, 378 CROS_EC_HWMON_TEMP_PARAMS, 379 CROS_EC_HWMON_TEMP_PARAMS, 380 CROS_EC_HWMON_TEMP_PARAMS, 381 CROS_EC_HWMON_TEMP_PARAMS, 382 CROS_EC_HWMON_TEMP_PARAMS, 383 CROS_EC_HWMON_TEMP_PARAMS, 384 CROS_EC_HWMON_TEMP_PARAMS, 385 CROS_EC_HWMON_TEMP_PARAMS, 386 CROS_EC_HWMON_TEMP_PARAMS, 387 CROS_EC_HWMON_TEMP_PARAMS), 388 NULL 389 }; 390 391 static int cros_ec_hwmon_cooling_get_max_state(struct thermal_cooling_device *cdev, 392 unsigned long *val) 393 { 394 *val = 255; 395 return 0; 396 } 397 398 static int cros_ec_hwmon_cooling_get_cur_state(struct thermal_cooling_device *cdev, 399 unsigned long *val) 400 { 401 const struct cros_ec_hwmon_cooling_priv *priv = cdev->devdata; 402 u8 read_val; 403 int ret; 404 405 ret = cros_ec_hwmon_read_pwm_value(priv->hwmon_priv->cros_ec, priv->index, &read_val); 406 if (ret) 407 return ret; 408 409 *val = read_val; 410 return 0; 411 } 412 413 static int cros_ec_hwmon_cooling_set_cur_state(struct thermal_cooling_device *cdev, 414 unsigned long val) 415 { 416 const struct cros_ec_hwmon_cooling_priv *priv = cdev->devdata; 417 418 return cros_ec_hwmon_write_pwm_input(priv->hwmon_priv->cros_ec, priv->index, val); 419 } 420 421 static const struct thermal_cooling_device_ops cros_ec_thermal_cooling_ops = { 422 .get_max_state = cros_ec_hwmon_cooling_get_max_state, 423 .get_cur_state = cros_ec_hwmon_cooling_get_cur_state, 424 .set_cur_state = cros_ec_hwmon_cooling_set_cur_state, 425 }; 426 427 static const struct hwmon_ops cros_ec_hwmon_ops = { 428 .read = cros_ec_hwmon_read, 429 .read_string = cros_ec_hwmon_read_string, 430 .write = cros_ec_hwmon_write, 431 .is_visible = cros_ec_hwmon_is_visible, 432 }; 433 434 static const struct hwmon_chip_info cros_ec_hwmon_chip_info = { 435 .ops = &cros_ec_hwmon_ops, 436 .info = cros_ec_hwmon_info, 437 }; 438 439 static void cros_ec_hwmon_probe_temp_sensors(struct device *dev, struct cros_ec_hwmon_priv *priv, 440 u8 thermal_version) 441 { 442 struct ec_params_temp_sensor_get_info req = {}; 443 struct ec_response_temp_sensor_get_info resp; 444 size_t candidates, i, sensor_name_size; 445 int ret; 446 u8 temp; 447 448 if (thermal_version < 2) 449 candidates = EC_TEMP_SENSOR_ENTRIES; 450 else 451 candidates = ARRAY_SIZE(priv->temp_sensor_names); 452 453 for (i = 0; i < candidates; i++) { 454 if (cros_ec_hwmon_read_temp(priv->cros_ec, i, &temp) < 0) 455 continue; 456 457 if (temp == EC_TEMP_SENSOR_NOT_PRESENT) 458 continue; 459 460 req.id = i; 461 ret = cros_ec_cmd(priv->cros_ec, 0, EC_CMD_TEMP_SENSOR_GET_INFO, 462 &req, sizeof(req), &resp, sizeof(resp)); 463 if (ret < 0) 464 continue; 465 466 sensor_name_size = strnlen(resp.sensor_name, sizeof(resp.sensor_name)); 467 priv->temp_sensor_names[i] = devm_kasprintf(dev, GFP_KERNEL, "%.*s", 468 (int)sensor_name_size, 469 resp.sensor_name); 470 } 471 } 472 473 static void cros_ec_hwmon_probe_fans(struct cros_ec_hwmon_priv *priv) 474 { 475 u16 speed; 476 size_t i; 477 int ret; 478 479 for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) { 480 ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, i, &speed); 481 if (ret == 0 && speed != EC_FAN_SPEED_NOT_PRESENT) 482 priv->usable_fans |= BIT(i); 483 } 484 } 485 486 static inline bool is_cros_ec_cmd_available(struct cros_ec_device *cros_ec, 487 u16 cmd, u8 version) 488 { 489 int ret; 490 491 ret = cros_ec_get_cmd_versions(cros_ec, cmd); 492 return ret >= 0 && (ret & EC_VER_MASK(version)); 493 } 494 495 static bool cros_ec_hwmon_probe_fan_control_supported(struct cros_ec_device *cros_ec) 496 { 497 return is_cros_ec_cmd_available(cros_ec, EC_CMD_PWM_GET_FAN_DUTY, 498 CROS_EC_HWMON_PWM_GET_FAN_DUTY_CMD_VERSION) && 499 is_cros_ec_cmd_available(cros_ec, EC_CMD_PWM_SET_FAN_DUTY, 500 CROS_EC_HWMON_PWM_SET_FAN_DUTY_CMD_VERSION) && 501 is_cros_ec_cmd_available(cros_ec, EC_CMD_THERMAL_AUTO_FAN_CTRL, 502 CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION); 503 } 504 505 static void cros_ec_hwmon_register_fan_cooling_devices(struct device *dev, 506 struct cros_ec_hwmon_priv *priv) 507 { 508 struct cros_ec_hwmon_cooling_priv *cpriv; 509 struct thermal_cooling_device *cdev; 510 const char *type; 511 size_t i; 512 513 if (!IS_ENABLED(CONFIG_THERMAL)) 514 return; 515 516 if (!priv->fan_control_supported) 517 return; 518 519 for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) { 520 if (!(priv->usable_fans & BIT(i))) 521 continue; 522 523 cpriv = devm_kzalloc(dev, sizeof(*cpriv), GFP_KERNEL); 524 if (!cpriv) 525 continue; 526 527 type = devm_kasprintf(dev, GFP_KERNEL, "%s-fan%zu", dev_name(dev), i); 528 if (!type) { 529 dev_warn(dev, "no memory to compose cooling device type for fan %zu\n", i); 530 continue; 531 } 532 533 cpriv->hwmon_priv = priv; 534 cpriv->index = i; 535 cdev = devm_thermal_of_cooling_device_register(dev, NULL, type, cpriv, 536 &cros_ec_thermal_cooling_ops); 537 if (IS_ERR(cdev)) { 538 dev_warn(dev, "failed to register fan %zu as a cooling device: %pe\n", i, 539 cdev); 540 continue; 541 } 542 } 543 } 544 545 static int cros_ec_hwmon_probe(struct platform_device *pdev) 546 { 547 struct device *dev = &pdev->dev; 548 struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); 549 struct cros_ec_device *cros_ec = ec_dev->ec_dev; 550 struct cros_ec_hwmon_priv *priv; 551 struct device *hwmon_dev; 552 u8 thermal_version; 553 int ret; 554 555 ret = cros_ec_cmd_readmem(cros_ec, EC_MEMMAP_THERMAL_VERSION, 1, &thermal_version); 556 if (ret < 0) 557 return ret; 558 559 /* Covers both fan and temp sensors */ 560 if (thermal_version == 0) 561 return -ENODEV; 562 563 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 564 if (!priv) 565 return -ENOMEM; 566 567 priv->cros_ec = cros_ec; 568 569 cros_ec_hwmon_probe_temp_sensors(dev, priv, thermal_version); 570 cros_ec_hwmon_probe_fans(priv); 571 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); 574 cros_ec_hwmon_register_fan_cooling_devices(dev, priv); 575 576 hwmon_dev = devm_hwmon_device_register_with_info(dev, "cros_ec", priv, 577 &cros_ec_hwmon_chip_info, NULL); 578 platform_set_drvdata(pdev, priv); 579 580 return PTR_ERR_OR_ZERO(hwmon_dev); 581 } 582 583 static int cros_ec_hwmon_suspend(struct platform_device *pdev, pm_message_t state) 584 { 585 struct cros_ec_hwmon_priv *priv = platform_get_drvdata(pdev); 586 u8 control_method; 587 size_t i; 588 int ret; 589 590 if (!priv->fan_control_supported) 591 return 0; 592 593 /* EC sets fan control to auto after suspended, store settings before suspending. */ 594 for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) { 595 if (!(priv->usable_fans & BIT(i))) 596 continue; 597 598 ret = cros_ec_hwmon_read_pwm_enable(priv->cros_ec, i, &control_method); 599 if (ret) { 600 dev_warn(&pdev->dev, "failed to get mode setting for fan %zu: %d\n", i, 601 ret); 602 continue; 603 } 604 605 if (control_method != 1) { 606 priv->manual_fans &= ~BIT(i); 607 continue; 608 } else { 609 priv->manual_fans |= BIT(i); 610 } 611 612 ret = cros_ec_hwmon_read_pwm_value(priv->cros_ec, i, &priv->manual_fan_pwm[i]); 613 /* 614 * If storing the value failed, invalidate the stored mode value by setting it 615 * to auto control. EC will automatically switch to auto mode for that fan after 616 * suspended. 617 */ 618 if (ret) { 619 dev_warn(&pdev->dev, "failed to get PWM setting for fan %zu: %pe\n", i, 620 ERR_PTR(ret)); 621 priv->manual_fans &= ~BIT(i); 622 continue; 623 } 624 } 625 626 return 0; 627 } 628 629 static int cros_ec_hwmon_resume(struct platform_device *pdev) 630 { 631 const struct cros_ec_hwmon_priv *priv = platform_get_drvdata(pdev); 632 size_t i; 633 int ret; 634 635 if (!priv->fan_control_supported) 636 return 0; 637 638 /* EC sets fan control to auto after suspend, restore to settings before suspend. */ 639 for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) { 640 if (!(priv->manual_fans & BIT(i))) 641 continue; 642 643 /* 644 * Setting fan PWM value to EC will change the mode to manual for that fan in EC as 645 * well, so we do not need to issue a separate fan mode to manual call. 646 */ 647 ret = cros_ec_hwmon_set_fan_pwm_val(priv->cros_ec, i, priv->manual_fan_pwm[i]); 648 if (ret) 649 dev_warn(&pdev->dev, "failed to restore settings for fan %zu: %pe\n", i, 650 ERR_PTR(ret)); 651 } 652 653 return 0; 654 } 655 656 static const struct platform_device_id cros_ec_hwmon_id[] = { 657 { DRV_NAME, 0 }, 658 {} 659 }; 660 661 static struct platform_driver cros_ec_hwmon_driver = { 662 .driver.name = DRV_NAME, 663 .probe = cros_ec_hwmon_probe, 664 .suspend = pm_ptr(cros_ec_hwmon_suspend), 665 .resume = pm_ptr(cros_ec_hwmon_resume), 666 .id_table = cros_ec_hwmon_id, 667 }; 668 module_platform_driver(cros_ec_hwmon_driver); 669 670 MODULE_DEVICE_TABLE(platform, cros_ec_hwmon_id); 671 MODULE_DESCRIPTION("ChromeOS EC Hardware Monitoring Driver"); 672 MODULE_AUTHOR("Thomas Weißschuh <linux@weissschuh.net"); 673 MODULE_LICENSE("GPL"); 674