Guide on how to customize you pwm fan curve

Now the new kernel has used pwm-fan kernel driver to deal with the fan control, so the old pwm fan scripts won’t work. Here is a guide on how to customize your onw pwm fan curve since different cases/environment/fans need different fan curve.
I will take armbian’s kernel as example because I use armbian as my daily use os. But it will be similar if you’re using official radxa’s kernel, radxa’s kernel uses different cooling levels.

If you take a look at the devicetree of rock5b, there is a node fan0 with this property:

cooling-levels = <72 94 117 139 162 184 207 229 255>;

This property works togather with property trips defined in node soc_thermal
Here is the default pwm fan curve defined in armbian’s kernel devicetree:

cooling level value trip temp defined in device tree working temperature
72 temp < 45
94 45 45-50
117 50 50-55
139 55 55-60
162 60 60-65
184 65 65-70
207 70 70-75
229 75 75-80
255 80 temp > 80

Cooling level vaule ranges from 0 to 255, which is the pwm value of the fan. It doesn’t start from 0 in the devicetree because I want the fan keeps spinning at its lowest speed so that I can get a stable temperature when it’s idle.
So we need another 9 pwm values like 72 94 117 139 162 184 207 229 255 for our own fan. Here is how to do it:

  • Login to root, and set the thermal policy to user_space:
echo user_space > /sys/class/thermal/thermal_zone0/policy
  • Then you can set the fan speed by setting pwm value, for example, if you want to set the speed to max, just set it to 255:
echo 255 > /sys/devices/platform/pwm-fan/hwmon/hwmon8/pwm1
  • Find the miminal pwm value that makes the fan spinning. I set the default value to 72 because it’s the minimal value of my fan.
  • After you get your minimal pwm value, let’s make it 120 as an example, we just have to fill the other 7 values between 120 and 255, like 120 135 150 165 180 195 210 235 255
  • Then create a devicetree overlay to set the new pwm fan curve:
/dts-v1/;
/plugin/;
/ {
        fragment@0 {
                target = <&fan0>;
                __overlay__ {
                        cooling-levels = <120 135 150 165 180 195 210 235 255>;
                };
        };
};
  • If you save the devicetree overlay as filename pwm-fan.dts, then use the following command to apply it:
sudo armbian-add-overlay pwm-fan.dts
  • Then reboot to see if it is applied. Make sure you’re using step_wise for your thermal_zone0:
$ cat /sys/class/thermal/thermal_zone0/policy
step_wise
  • And check if your pwm value changes with temperature:
watch -n1 cat /sys/devices/platform/pwm-fan/hwmon/hwmon8/pwm1 /sys/class/thermal/thermal_zone0/temp
7 Likes

Thank you very much!

Thanks for the guide. I noticed the fan spinning up due to the old fan control now working anymore.

I tried following your guide but i get this error:

echo 255 > /sys/devices/platform/pwm-fan/hwmon/hwmon8/pwm1

-bash: /sys/devices/platform/pwm-fan/hwmon/hwmon8/pwm1: No such file or directory

running: Armbian 23.02.2 Jammy with Linux 5.10.110-rockchip-rk3588

You have to update the kernel to latest:
http://fi.mirror.armbian.de/beta/pool/main/l/linux-5.10.160/
http://fi.mirror.armbian.de/beta/pool/main/l/linux-dtb-legacy-rk35xx/

For some reason my WiFi on rock5b (Radxa A8) doesn’t work on this kernel. Where should I report this?

You can create an issue at https://github.com/armbian/linux-rockchip

2 Likes

on my 5a it’s /sys/devices/platform/pwm-fan/hwmon/hwmon7/pwm1

Yes, the number on 5A is different.

As far as I know the 2pin fans are still brushless with an internal controller and why I just get gpio fans and diy.
I have both Opi5 & Rock5b but there are 20, 30, 40mm 3 pin pwm fans from Pihut to aliexpress and assign pwm to gpio.
https://github.com/StuartIanNaylor/Opi5PWM-fan
I thought I would ask /sys/class/pwm/pwmchip2/pwm0/period is that milliseconds? Or is the 25000000 period 25kHz wrong.