Linux's cros_ec Driver Gains Custom Fan Curve Support, and Framework Laptop Owners Should Care
#Dev

Linux's cros_ec Driver Gains Custom Fan Curve Support, and Framework Laptop Owners Should Care

Hardware Reporter
5 min read

A pending patch series for the cros_ec kernel driver adds read and write access to fan curves on ChromeOS Embedded Controller hardware. The safety-first design only lets you make cooling more aggressive than the factory default, which is exactly what a homelab tinkerer wants for a Framework Laptop pulling double duty as a quiet compile box.

The cros_ec driver is one of those quiet pieces of the Linux kernel that most people never think about until it does something useful. It speaks to the ChromeOS Embedded Controller, the small dedicated microcontroller that handles power sequencing, keyboard scanning, battery management, and thermals. Chromebooks ship with it, but so do Framework Laptops, which adopted the ChromeOS EC firmware stack for their mainboards. That shared lineage is why a patch aimed at Chromebook plumbing ends up mattering to a very different crowd: the people who run Framework 13 and Framework 16 machines as always-on home servers, build nodes, and lab boxes.

The news, reported by Phoronix, is that Thomas Weißschuh has posted patches to add custom fan curve support to cros_ec. Weißschuh has a long track record of hardware monitoring (hwmon) and platform driver work in the kernel, so this is not a drive-by contribution. The patches allow both reading the fan curve currently programmed into the EC and writing a new one.

Framework Laptop 16

What a fan curve actually is

A fan curve is a lookup table that maps temperature to fan speed. The EC samples a thermal sensor, finds where that reading falls on the curve, and drives the fan PWM duty cycle accordingly. Most laptops bury this table in firmware and never expose it. You get whatever the vendor decided, which is almost always tuned for the median buyer: keep the chassis quiet at idle, ramp late, and accept higher sustained temperatures to avoid fan noise complaints.

That default tuning is a reasonable compromise for someone typing in a coffee shop. It is a bad compromise for a machine sitting on a shelf running make -j16 for forty minutes straight, or hosting a few containers and a Postgres instance around the clock. In those workloads you do not care about noise. You care about keeping the silicon out of thermal throttle and shaving a few degrees off the long-term average to protect the VRMs and battery sitting next to a hot SoC.

The safety rail: aggressive only

The design decision worth highlighting is the constraint on writes. The patches will not let you program a curve that is less aggressive than the factory default. You can tell the EC to spin the fan harder at a given temperature, but you cannot tell it to spin slower or hold off longer than the vendor intended.

This is the right call. A user-writable fan table is a foot-gun if it lets you under-cool the machine. Someone could set a silent profile, walk away from a sustained load, and cook the hardware before the EC's hard thermal limits kick in. By clamping writes to "at least as aggressive as default," the kernel keeps the vendor's thermal safety floor intact while still letting power users front-load cooling. The worst case becomes a slightly louder laptop, not a damaged one.

In practice this maps cleanly onto how the feature gets used:

Use case Desired behavior Allowed under the patch?
Quiet idle laptop on a desk Slower fan, later ramp No (less aggressive than default)
Sustained compile / homelab node Earlier ramp, higher floor Yes
Gaming or transcoding burst load Pre-spin fan before temp spikes Yes
Silence at any thermal cost Fan off under load No

If you genuinely want a quieter-than-stock profile, this interface is not the tool for that, and intentionally so.

Why the homelab crowd benefits

A Framework 16 with a Ryzen AI 300 series part is a capable little server. The CPU will hold higher sustained clocks if it stays off its thermal ceiling, and the difference between a late-ramping default curve and an aggressive one can be the difference between a steady all-core boost and a sawtooth pattern of throttle-and-recover. Pre-spinning the fan before a load lands also flattens temperature spikes, which matters for component longevity when the box never gets a break.

Twitter image

Because the interface lands in cros_ec and exposes through the standard hwmon path, the expectation is that you will be able to read and adjust curves through normal sysfs entries rather than vendor tooling. That means scripting it is trivial: a systemd unit that writes an aggressive curve on boot, or a profile that swaps based on whether the machine is on AC and running headless versus on battery in someone's lap. For people who already graph every sensor they own, having the fan table as a first-class, readable kernel interface is the part that closes the loop. You can finally see what the EC is doing and change it from the same place you read it.

Status and what to watch

The patches are out for review on the kernel mailing list and are not merged yet. Reviewers have flagged that more changes are needed before the series is ready, which is normal for any new userspace-facing interface. Anything that lets userspace poke an embedded controller's thermal behavior gets careful scrutiny, both for the sysfs ABI design and for making sure the aggressive-only clamp is enforced correctly across the different EC firmware variants in the wild.

The realistic timeline is a revised series landing in a future mainline kernel rather than an imminent one, so this is a watch-the-list item rather than something to flash today. If you run a Framework as a lab workhorse, this is a feature worth tracking, and worth testing once it hits a release kernel so the thermal headroom you are paying for in silicon actually shows up in your sustained clocks.

{{IMAGE:2}}

Comments

Loading comments...