Banana pi BPI-R3 can not control pwm fan

Have tried it? With original openwrt clock it was not working for me on mainline kernel…

edit: booted again 6.5-rc on my r3 and looked for the top-clock-error…do not have it

root@bpi-r3:~# uname -a
Linux bpi-r3 6.5.0-rc1-bpi-r3 #3 SMP Sat Aug 19 16:00:16 CEST 2023 aarch64 GNU/Linux
root@bpi-r3:~# dmesg | grep pwm
root@bpi-r3:~# cd /sys/class/pwm/pwmchip0
root@bpi-r3:/sys/class/pwm/pwmchip0# echo 1 > export                                                                                               
root@bpi-r3:/sys/class/pwm/pwmchip0# ls -l
total 0
lrwxrwxrwx 1 root root    0 Feb 28 11:17 device -> ../../../10048000.pwm
--w------- 1 root root 4096 Feb 28 11:17 export
-r--r--r-- 1 root root 4096 Feb 28 11:17 npwm
drwxr-xr-x 2 root root    0 Feb 28 11:17 power
drwxr-xr-x 3 root root    0 Feb 28 11:17 pwm1
lrwxrwxrwx 1 root root    0 Feb 28 11:15 subsystem -> ../../../../../../class/pwm
-rw-r--r-- 1 root root 4096 Feb 28 11:15 uevent
--w------- 1 root root 4096 Feb 28 11:17 unexport
root@bpi-r3:/sys/class/pwm/pwmchip0# 

i can se the same problem in 23.05.0 RC3

root@OpenWrt:/# dmesg |grep “pwm”

[ 0.049827] pwm-mediatek 10048000.pwm: clock: top fail: -517

root@OpenWrt:/#

quote and code tags are broken in this forum or what ? all the text is in sequence

Kernel 6.1 or 5.15?

I guess something is different between openwrt and mainline as pwm was not working in mainline for me with openwrt top clock

Kernel 5.15.127

OpenWrt 23.05.0-rc3 r23389-5deed175a5 / LuCI openwrt-23.05 branch git-23.219.80063-bece581

5.15 is known not working

I guess because backported pwm/clock support is different to mainline

The pwm node i upstreamed works for me in mainline kernel without openwrt. So we need someone who can test pwm with openwrt with kernel 6.1 which (hopefully) does not have any openwrt-specific backports for r3

1 Like

Sorry Frank, I had no time but I finally checked with oscilloscope and it works with 6.1. And I don’t have that error on boot. But that error was always there and people always had the PWM interface working for them. I know for a fact that PWM works for some people using openwrt 5.15

5.15 mainline does not support bpi-r3/mt7986

Openwrt recently switched to mainline devicetree and so some settings changed to mainline state (like the missing milliwatt setting for sfp and the pwm top clock). The top clock was different in older openwrt devicetree so it worked till the switch to mainline dts.

Thats why older snapshots worked but with this setting it was not working in mainline code,so i had changed the clock before posting to mainline…seems like something is different in clockdriver in backported patches compared to mainline…so openwrt team could add a patch for changing the topclock of pwm for 5.15 if this is enough…so we need somebody who can change the clock in his 5.15 dts and report that it works after that. If 6.1 works (like i guess because clock driver is not backported - if this is the cause) than no change is needed here and users can switch to 6.1 as alternative

1 Like

Can you try

echo 2 > /sys/class/thermal/cooling_device0/cur_state

Does it turn the fan on?

Yes, during 5s and it stop.

echo 1 > /sys/class/thermal/cooling_device0/cur_state

makes it runing continuously

You can try this tree as daniel added the missing parts

https://git.openwrt.org/openwrt/staging/dangole.git

@dangowrt can you please change the first clock for pwm in openwrt for 5.15 only to

&infracfg CLK_INFRA_PWM_HCK

? 5.15 seems to have problems with the clock i use in higher kernel versions. 6.1 should be ok with the new clock…maybe some backporting issue for clock driver.

  • 5.15 works after clock change confirmed here
  • 6.1 confirmed here

Well, it does not work now, Fan & nvme doesnot work. kernel-boot-log.txt (70.5 KB) Please helo me.Kernel ver: 5.15.136.

And I wonder which the PCIE LINK mode of the m2 works. Is RC? Or EP?

Dears, I am using this arch linux with kernel 6.7 https://www.woudstra.mywire.org/images/

The fan is not working after first boot up. I have configured as mentioned above conversation . It doesn’t work well. Please advice Sirs.

I actually do not have a fan. But perhaps the temperature needs to rise first, before the fan will start.

Update linux-bpir64-git package as temperature was not configured correctly until recently.

echo 0 > export    <-Is correct.

I got the fan working on the BPI-R4, I don’t have a fan on my BPI-R3 so not tested there.

I needed on the BPI-R4:

CONFIG_PWM_MEDIATEK=m
CONFIG_HWMON=m
CONFIG_SENSORS_PWM_FAN=m

System boots up with no fan, after about 15 seconds on boot time, the fan comes on slow.

I think it would be better if the fan was a 4 pin one, as currently it is missing the speed sensor pin.

Maybe we should try to get an adapter for 4 pin fan to 3 pin + GPIO pin, and measure the speed via GPIO.

Without the sensor pin, one has no way of knowing if the fan has failed or not.

I cannot find any COTS cables that convert 4 pin to 3 pin fans with the extra pin for the GPIO speed sensor pin.

I have a different board that uses the same chips as the BPI-R4 and that uses a 4 pin connector with the speed sensor pin just connected to a GPIO, and configured for the GPIO to cause an interrupt.

The mainline linux kernel is already set up to work with it configured that way.

Fan is pwm0 so 0 is right

Chiming in in this as I face the same kernel log entries on my BPI-R3 running OpenWrt 23.05.03. Though, I recall that support for the used kernel in that aversion wasn’t quite ready if operational et all.

Did anyone by chance made some progress about this subject?

Hi

After a few weeks of use, this script no longer works (located in /etc/init.d). The script won’t start at boot, shows always as “deactivated” by luci

# BpiR3 Fancontrol-Script
#
# chmod +x /etc/init.d/fancontrol
# /etc/init.d/fancontrol enable
# /etc/init.d/fancontrol start


#!/bin/sh /etc/rc.common

START=99
PIDFILE="/var/run/fan_control.pid"
TEMP_PATH="/sys/class/thermal/thermal_zone0/temp"
PWM_PATH="/sys/class/hwmon/hwmon2/pwm1"

# Settings
HYST=2000        # 2°C Hysteresis
LOW_TEMP=50000   # 50°C (Threshold to start fan)
HIGH_TEMP=70000  # 70°C (Threshold for max speed)
MIN_RUN_PWM=90   # Slowest active speed
MAX_RUN_PWM=10   # Fastest active speed
STOP_PWM=255     # PWM value for OFF

fan_loop() {
    # Initialize state
    CURRENT_PWM=$(cat "$PWM_PATH" 2>/dev/null || echo "$STOP_PWM")
    
    while true; do
        [ -f "$TEMP_PATH" ] || { sleep 10; continue; }
        TEMP=$(cat "$TEMP_PATH")

        # 1. Logic for Stopped Fan
        if [ "$CURRENT_PWM" -eq "$STOP_PWM" ]; then
            if [ "$TEMP" -ge "$LOW_TEMP" ]; then
                # Start fan at minimum speed once 50°C is reached
                NEW_PWM=$MIN_RUN_PWM
            else
                NEW_PWM=$STOP_PWM
            fi

        # 2. Logic for Over-temperature (Max Speed)
        elif [ "$TEMP" -ge "$HIGH_TEMP" ]; then
            NEW_PWM=$MAX_RUN_PWM

        # 3. Logic for Cooldown (Stop Fan)
        elif [ "$TEMP" -le $((LOW_TEMP - HYST)) ]; then
            # Only stop if we drop below 48°C (Hysteresis)
            NEW_PWM=$STOP_PWM

        # 4. Linear Interpolation Range (50°C - 70°C)
        else
            # Calculate PWM between 90 (at 50°C) and 10 (at 70°C)
            NEW_PWM=$((MIN_RUN_PWM - (TEMP - LOW_TEMP) * (MIN_RUN_PWM - MAX_RUN_PWM) / (HIGH_TEMP - LOW_TEMP)))
            
            # Ensure we don't accidentally send STOP_PWM (255) during interpolation
            [ "$NEW_PWM" -gt "$MIN_RUN_PWM" ] && NEW_PWM=$MIN_RUN_PWM
            [ "$NEW_PWM" -lt "$MAX_RUN_PWM" ] && NEW_PWM=$MAX_RUN_PWM
        fi

        # Apply change only if value changed to save I/O
        if [ "$NEW_PWM" -ne "$CURRENT_PWM" ]; then
            echo "$NEW_PWM" > "$PWM_PATH" 2>/dev/null
            CURRENT_PWM=$NEW_PWM
        fi

        sleep 10
    done
}

start() {
    [ -f "$PIDFILE" ] && return
    echo "Starting dynamic fan control (Stop < 50°C, Hysteresis enabled)..."
    fan_loop &
    echo $! > "$PIDFILE"
}

stop() {
    if [ -f "$PIDFILE" ]; then
        kill $(cat "$PIDFILE")
        rm "$PIDFILE"
        # Optional: Set fan to a safe speed on service stop
        echo "$MIN_RUN_PWM" > "$PWM_PATH" 2>/dev/null
    fi
}

Manual test was succesful:

echo 95 > /sys/class/hwmon/hwmon2/pwm1

Do you guys have any idea what’s going wrong? Thanks

I think you should use cat /sys/class/thermal/thermal_zone0/temp to check the actual temperature to determine which temperature the script is running at.