Skip to content

Laptop 13 AMD Ryzen AI 300 (lilac): backport EC_CMD_PWM_GET_FAN_DUTY and EC_CMD_THERMAL_AUTO_FAN_CTRL v2 so Linux exposes fan PWM control #98

Open

Description

@mitar

Summary

The EC on the Framework Laptop 13 (AMD Ryzen AI 300 Series) does not implement EC_CMD_PWM_GET_FAN_DUTY (0x0027), and it implements EC_CMD_THERMAL_AUTO_FAN_CTRL (0x0052) only up to version 1. Because of this, the Linux cros_ec_hwmon driver does not register pwm1, pwm1_enable or the fan's thermal cooling device. The fan duty cannot be read at all, and controlling the fan from Linux requires raw EC access as root (framework_tool --fansetduty) instead of the standard hwmon interface.

Both commands are implemented upstream in Chromium EC and are already on this repository's main, fwk-sakura-20260429 and fwk-sunflower-dahlia-2026-09-30 branches, but not on fwk-lilac-27116.

System

  • Framework Laptop 13 (AMD Ryzen AI 300 Series), AMD Ryzen AI 9 HX 370
  • BIOS 04.02 (06/09/2026)
  • EC lilac-4.0.2-fdbf549 (2026-06-08)
  • Linux 7.0.0-42-generic (Ubuntu), framework_tool 0.6.2

What the EC reports

Asking the EC which versions of each command it supports (EC_CMD_GET_CMD_VERSIONS, 0x0008):

$ sudo framework_tool --host-command 0x08 0 0x27
EC command failed: Response(InvalidParameter)
$ sudo framework_tool --host-command 0x08 0 0x24
Response (4 bytes):
00000000: 0300 0000                                ....
$ sudo framework_tool --host-command 0x08 0 0x52
Response (4 bytes):
00000000: 0300 0000                                ....

So EC_CMD_PWM_SET_FAN_DUTY supports versions 0 and 1, EC_CMD_THERMAL_AUTO_FAN_CTRL supports versions 0 and 1, and EC_CMD_PWM_GET_FAN_DUTY is not implemented. This matches common/fan.c on fwk-lilac-27116.

The cros_ec hwmon device accordingly has only fan1_input, fan1_target and fan1_fault for the fan.

Why this matters

Since Linux 6.18 (commits fb8e659309f7 "hwmon: (cros_ec) add PWM control over fans" and 5798b62867b4 "hwmon: (cros_ec) register fans into thermal framework cooling devices"), cros_ec_hwmon exposes pwmN (duty, readable and writable) and pwmN_enable (manual or automatic control), and registers each fan as a thermal cooling device. It does so only when the EC supports all three of these (cros_ec_hwmon_probe_fan_control_supported() in drivers/hwmon/cros_ec_hwmon.c):

  • EC_CMD_PWM_GET_FAN_DUTY version 0
  • EC_CMD_PWM_SET_FAN_DUTY version 1
  • EC_CMD_THERMAL_AUTO_FAN_CTRL version 2

With them:

  • The fan duty is readable without root. The EC holds the fan at a target RPM by adjusting the duty, so the duty it needs for a given RPM is a useful fan health signal over time (bearing wear, dust).
  • Userspace fan control tools can use the standard hwmon interface instead of raw EC access as root.
  • Whether the EC is in automatic fan control can be queried (pwm1_enable), so a tool which exited without restoring automatic control can be detected.

Proposed fix

Cherry-pick these upstream commits (Sung-Chi Li, April 2025, already on main here) onto fwk-lilac-27116:

  1. efe67f7 ec_commands: add EC_CMD_PWM_GET_FAN_DUTY for getting fan duty cycle (https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/6466952)
  2. 9b34398 fan: implement host command of getting fan duty cycle (https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/6466953)
  3. e7e322c ec_commands: add v2 structs for EC_CMD_THERMAL_AUTO_FAN_CTRL (https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/6466954)
  4. 6b9702f fan: extend handling of command EC_CMD_THERMAL_AUTO_FAN_CTRL for v2 (https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/6466955)
  5. 1e6bccc fan: fix host command response size (https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/6475850)

They apply cleanly to fwk-lilac-27116 (common/fan.c, include/ec_commands.h, zephyr/test/drivers/fan/src/fan.c, 160 insertions and 7 deletions). I have not built or tested the result. The change adds one read-only command and a new version of an existing one. Versions 0 and 1 of EC_CMD_THERMAL_AUTO_FAN_CTRL keep their behavior, except that an out-of-range fan index returns EC_RES_INVALID_PARAM instead of EC_RES_ERROR.

The same commits are also missing on fwk-tulip-29169, fwk-dogwood-27111, fwk-lotus-azalea-19573 and fwk-sunflower-26784, so the same backport would help the boards built from those branches too.

Related: #69 (the EC stops reading its temperature sensors and the fan stays off) is a separate problem, but the workarounds posted there run framework_tool --fansetduty in a loop as root. With these commands they could use the standard hwmon pwm1 interface instead.

I can open a pull request against fwk-lilac-27116 with these cherry-picks if that is the preferred way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions