CPU根据温度降频

第一步:常温验证“限制生效”
在 

lowtemp_limiter.sh (line 20) 临时改成:
sh

LOWTEMP_THRESHOLD=50
LOWTEMP_RESTORE_THRESHOLD=55
这样:
• 电池 42°C < 50°C,early-init 就会按低温逻辑限频。
• 开机完成后 42°C < 55°C,不会自动恢复,限制保持住,方便你检查。
刷机开机后确认这些值:
sh

getprop vendor.lowtemp.limit
# 期望: 1

cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
cat /sys/devices/system/cpu/cpufreq/policy4/scaling_governor
cat /sys/devices/system/cpu/cpufreq/policy6/scaling_governor
# 期望: schedutil

cat /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq
cat /sys/devices/system/cpu/cpufreq/policy4/scaling_max_freq
cat /sys/devices/system/cpu/cpufreq/policy6/scaling_max_freq
# 期望: 1200000

cat /sys/class/devfreq/fb000000.gpu/max_freq
# 期望: 500000000

cat /sys/class/devfreq/dmc/governor
# 期望: dmc_ondemand

cat /sys/class/backlight/backlight/brightness
cat /sys/class/backlight/backlight/max_brightness
# 期望: brightness 约为 max_brightness 的 25%
还可以确认原始值有没有存好:
sh

getprop vendor.lowtemp.policy0.max
getprop vendor.lowtemp.policy4.max
getprop vendor.lowtemp.policy6.max
getprop vendor.lowtemp.gpu.max
第二步:验证“恢复”逻辑
把恢复阈值临时改成低于当前温度,例如:
sh

LOWTEMP_RESTORE_THRESHOLD=40
然后手动跑一次恢复,不用重启:
sh

sh /vendor/bin/lowtemp_limiter.sh restore
再确认:
sh

getprop vendor.lowtemp.limit
# 期望: 0

cat /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq
cat /sys/class/devfreq/fb000000.gpu/max_freq
# 期望: 恢复成之前保存的原始值
第三步:正式低温测试前改回去
sh

LOWTEMP_THRESHOLD=0
LOWTEMP_RESTORE_THRESHOLD=5
参数单位说明:脚本里写的都是摄氏度,LOWTEMP_GPU_MAX=500000000 是 500MHz,温度节点虽然底层是 0.1°C,但脚本已经自动除 10,不需要你换算。

 

 

流程现在是:
text
低温开机
  -> early-init 限频
  -> boot_completed 检查一次,仍低温就继续压着
  -> lowtemp_monitor 每 30s 查温度
  -> 温度回到 5°C 以上,自动恢复 CPU/GPU 频率并清掉 limit=1

 

验证:

# 低温开机后回温,等 30 秒内
getprop vendor.lowtemp.limit
# 期望变成 0

cat /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq
cat /sys/devices/system/cpu/cpufreq/policy4/scaling_max_freq
cat /sys/devices/system/cpu/cpufreq/policy6/scaling_max_freq
cat /sys/class/devfreq/fb000000.gpu/max_freq
# 期望恢复成原始最大值

cat /sys/class/backlight/backlight/brightness

 

 

代码实现:

diff --git a/device/rockchip/rk3588/device.mk b/device/rockchip/rk3588/device.mk
index de8d76ca8d7..9d7ec320e2e 100644
--- a/device/rockchip/rk3588/device.mk
+++ b/device/rockchip/rk3588/device.mk
@@ -30,6 +30,7 @@ PRODUCT_COPY_FILES += \
 
 PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/rk3588s_xzy_u/init.usb.controller.sh:system/bin/init.usb.controller.sh \
+    $(LOCAL_PATH)/lowtemp_limiter.sh:$(TARGET_COPY_OUT_VENDOR)/bin/lowtemp_limiter.sh \
 
 PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/init.rk3588.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.rk3588.rc \
diff --git a/device/rockchip/rk3588/init.rk3588.rc b/device/rockchip/rk3588/init.rk3588.rc
index 14f3cd11362..c81365e8b57 100644
--- a/device/rockchip/rk3588/init.rk3588.rc
+++ b/device/rockchip/rk3588/init.rk3588.rc
@@ -21,6 +21,8 @@ on property:sys.boot_completed=1
     write /sys/class/devfreq/dmc/governor dmc_ondemand
 
     write /dev/vehicle 88
+    exec_start lowtemp_restore
+    start lowtemp_monitor
 
 on charger
     chown system system /sys/class/devfreq/fb000000.gpu/governor
@@ -83,11 +85,36 @@ on init
     chmod 0666 /sys/class/devfreq/dmc/system_status
 
 on early-init
-    write /sys/devices/system/cpu/cpufreq/policy0/scaling_governor performance
-    write /sys/devices/system/cpu/cpufreq/policy4/scaling_governor performance
-    write /sys/devices/system/cpu/cpufreq/policy6/scaling_governor performance
-    write /sys/class/devfreq/dmc/governor performance
+    # Start from a low-power governor. The limiter switches to performance
+    # only when the battery temperature is normal, so a cold boot never
+    # enters performance mode before the frequency limits are applied.
+    write /sys/devices/system/cpu/cpufreq/policy0/scaling_governor schedutil
+    write /sys/devices/system/cpu/cpufreq/policy4/scaling_governor schedutil
+    write /sys/devices/system/cpu/cpufreq/policy6/scaling_governor schedutil
+    write /sys/class/devfreq/dmc/governor dmc_ondemand
+    exec_start lowtemp_limiter
 
      # usb controller
      setprop sys.usb.controller "fc000000.usb"
-     
\ No newline at end of file
+
+# Low-temperature boot current limiter
+service lowtemp_limiter /vendor/bin/lowtemp_limiter.sh limit
+    class main
+    user root
+    group root system
+    disabled
+    oneshot
+
+service lowtemp_restore /vendor/bin/lowtemp_limiter.sh restore
+    class late_start
+    user root
+    group root system
+    disabled
+    oneshot
+
+service lowtemp_monitor /vendor/bin/lowtemp_limiter.sh monitor
+    class late_start
+    user root
+    group root system
+    disabled
+    oneshot
diff --git a/device/rockchip/rk3588/lowtemp_limiter.sh b/device/rockchip/rk3588/lowtemp_limiter.sh
new file mode 100755
index 00000000000..7fdb1a3d7fe
--- /dev/null
+++ b/device/rockchip/rk3588/lowtemp_limiter.sh
@@ -0,0 +1,237 @@
+#!/vendor/bin/sh
+#
+# Low-temperature boot current limiter for RK3588.
+#
+# Usage: lowtemp_limiter.sh [limit|restore|monitor]
+#
+# limit:
+#   Read the battery temperature during early-init. When the temperature is
+#   below 0 C (or the battery node is not ready yet), cap CPU/GPU frequency,
+#   lower the backlight and switch the DMC governor to ondemand so that the
+#   inrush current at cold boot stays below the battery's low-temperature
+#   limit. The original max frequencies are saved as vendor.lowtemp.* props.
+#
+# restore:
+#   Called when sys.boot_completed is set. If the battery is still cold the
+#   caps are kept and the backlight is re-applied; once it warms up above the
+#   restore threshold the saved frequencies are written back.
+#
+# monitor:
+#   Keeps polling the battery temperature after boot and performs the same
+#   restore when the battery warms up later, so the frequency caps do not
+#   stay active for the whole session.
+
+LOWTEMP_LIMIT_PROP=vendor.lowtemp.limit
+LOWTEMP_THRESHOLD=0
+LOWTEMP_RESTORE_THRESHOLD=5
+LOWTEMP_A55_MAX=1200000
+LOWTEMP_A76_MAX=1200000
+LOWTEMP_GPU_MAX=500000000
+LOWTEMP_BACKLIGHT_PERCENT=10
+
+CPU_BASE=/sys/devices/system/cpu/cpufreq
+GPU_DEV=/sys/class/devfreq/fb000000.gpu
+DMC_DEV=/sys/class/devfreq/dmc
+
+is_int() {
+    case "$1" in
+        ''|*[!0-9-]*|-) return 1 ;;
+    esac
+    return 0
+}
+
+read_value() {
+    _v=""
+    read -r _v < "$1" 2>/dev/null
+}
+
+pick_freq() {
+    _f=""
+    [ -r "$1" ] || return 0
+    for f in $(cat "$1" 2>/dev/null); do
+        if is_int "$f" && [ "$f" -le "$2" ]; then
+            _f="$f"
+        fi
+    done
+    if [ -z "$_f" ]; then
+        for f in $(cat "$1" 2>/dev/null); do
+            if is_int "$f"; then
+                _f="$f"
+                break
+            fi
+        done
+    fi
+}
+
+save_policy_orig() {
+    name="$1"
+    dir="$2"
+    read_value "$dir/scaling_max_freq"
+    if is_int "$_v"; then
+        setprop "vendor.lowtemp.$name.max" "$_v"
+    fi
+}
+
+save_gpu_orig() {
+    [ -d "$GPU_DEV" ] || return 0
+    read_value "$GPU_DEV/max_freq"
+    if is_int "$_v"; then
+        setprop vendor.lowtemp.gpu.max "$_v"
+    fi
+}
+
+limit_policy() {
+    dir="$1"
+    cap="$2"
+    [ -d "$dir" ] || return 0
+    [ -w "$dir/scaling_governor" ] && echo schedutil > "$dir/scaling_governor" 2>/dev/null
+    pick_freq "$dir/scaling_available_frequencies" "$cap"
+    if [ -n "$_f" ] && [ -w "$dir/scaling_max_freq" ]; then
+        echo "$_f" > "$dir/scaling_max_freq" 2>/dev/null
+    fi
+    [ -w "$dir/scaling_min_freq" ] && echo 0 > "$dir/scaling_min_freq" 2>/dev/null
+}
+
+restore_policy() {
+    name="$1"
+    dir="$2"
+    orig=$(getprop "vendor.lowtemp.$name.max")
+    if ! is_int "$orig"; then
+        pick_freq "$dir/scaling_available_frequencies" 999999999
+        orig="$_f"
+    fi
+    if is_int "$orig" && [ -w "$dir/scaling_max_freq" ]; then
+        echo "$orig" > "$dir/scaling_max_freq" 2>/dev/null
+    fi
+    [ -w "$dir/scaling_min_freq" ] && echo 0 > "$dir/scaling_min_freq" 2>/dev/null
+}
+
+limit_gpu() {
+    [ -d "$GPU_DEV" ] || return 0
+    pick_freq "$GPU_DEV/available_frequencies" 200000000
+    if [ -n "$_f" ] && [ -w "$GPU_DEV/min_freq" ]; then
+        echo "$_f" > "$GPU_DEV/min_freq" 2>/dev/null
+    fi
+    pick_freq "$GPU_DEV/available_frequencies" "$LOWTEMP_GPU_MAX"
+    if [ -n "$_f" ] && [ -w "$GPU_DEV/max_freq" ]; then
+        echo "$_f" > "$GPU_DEV/max_freq" 2>/dev/null
+    fi
+}
+
+restore_gpu() {
+    [ -d "$GPU_DEV" ] || return 0
+    orig=$(getprop vendor.lowtemp.gpu.max)
+    if ! is_int "$orig"; then
+        pick_freq "$GPU_DEV/available_frequencies" 999999999
+        orig="$_f"
+    fi
+    if is_int "$orig" && [ -w "$GPU_DEV/max_freq" ]; then
+        echo "$orig" > "$GPU_DEV/max_freq" 2>/dev/null
+    fi
+}
+
+limit_dmc() {
+    [ -w "$DMC_DEV/governor" ] && echo dmc_ondemand > "$DMC_DEV/governor" 2>/dev/null
+}
+
+apply_limits() {
+    limit_policy "$CPU_BASE/policy0" "$LOWTEMP_A55_MAX"
+    limit_policy "$CPU_BASE/policy4" "$LOWTEMP_A76_MAX"
+    limit_policy "$CPU_BASE/policy6" "$LOWTEMP_A76_MAX"
+    limit_gpu
+    limit_dmc
+    limit_backlight
+}
+
+limit_backlight() {
+    for b in /sys/class/backlight/*/brightness /sys/class/leds/lcd-backlight/brightness; do
+        [ -w "$b" ] || continue
+        level=32
+        read_value "${b%/brightness}/max_brightness"
+        if is_int "$_v" && [ "$_v" -gt 0 ]; then
+            level=$((_v * LOWTEMP_BACKLIGHT_PERCENT / 100))
+            [ "$level" -lt 1 ] && level=1
+        fi
+        echo "$level" > "$b" 2>/dev/null
+    done
+}
+
+read_battery_temp() {
+    _temp=""
+    for name in sh366100-battery battery cw2015-battery; do
+        f="/sys/class/power_supply/$name/temp"
+        [ -r "$f" ] || continue
+        read_value "$f"
+        if is_int "$_v"; then
+            if [ "$_v" -ge 100 ] || [ "$_v" -le -100 ]; then
+                _v=$((_v / 10))
+            fi
+            _temp="$_v"
+            return 0
+        fi
+    done
+    for f in /sys/class/power_supply/*/temp; do
+        [ -r "$f" ] || continue
+        read_value "$f"
+        if is_int "$_v"; then
+            if [ "$_v" -ge 100 ] || [ "$_v" -le -100 ]; then
+                _v=$((_v / 10))
+            fi
+            _temp="$_v"
+            return 0
+        fi
+    done
+    return 1
+}
+
+restore_if_warm() {
+    read_battery_temp
+    if [ -n "$_temp" ] && [ "$_temp" -ge "$LOWTEMP_RESTORE_THRESHOLD" ]; then
+        restore_policy policy0 "$CPU_BASE/policy0"
+        restore_policy policy4 "$CPU_BASE/policy4"
+        restore_policy policy6 "$CPU_BASE/policy6"
+        restore_gpu
+        setprop "$LOWTEMP_LIMIT_PROP" 0
+        return 0
+    fi
+    return 1
+}
+
+case "$1" in
+    monitor)
+        while [ "$(getprop "$LOWTEMP_LIMIT_PROP")" = "1" ]; do
+            if restore_if_warm; then
+                exit 0
+            fi
+            sleep 30
+        done
+        exit 0
+        ;;
+    restore)
+        if [ "$(getprop "$LOWTEMP_LIMIT_PROP")" != "1" ]; then
+            exit 0
+        fi
+        if ! restore_if_warm; then
+            apply_limits
+        fi
+        ;;
+    *)
+        read_battery_temp
+        if [ -z "$_temp" ] || [ "$_temp" -lt "$LOWTEMP_THRESHOLD" ]; then
+            save_policy_orig policy0 "$CPU_BASE/policy0"
+            save_policy_orig policy4 "$CPU_BASE/policy4"
+            save_policy_orig policy6 "$CPU_BASE/policy6"
+            save_gpu_orig
+            apply_limits
+            setprop "$LOWTEMP_LIMIT_PROP" 1
+        else
+            [ -w "$CPU_BASE/policy0/scaling_governor" ] && echo performance > "$CPU_BASE/policy0/scaling_gove
rnor" 2>/dev/null
+            [ -w "$CPU_BASE/policy4/scaling_governor" ] && echo performance > "$CPU_BASE/policy4/scaling_gove
rnor" 2>/dev/null
+            [ -w "$CPU_BASE/policy6/scaling_governor" ] && echo performance > "$CPU_BASE/policy6/scaling_gove
rnor" 2>/dev/null
+            [ -w "$DMC_DEV/governor" ] && echo performance > "$DMC_DEV/governor" 2>/dev/null
+            setprop "$LOWTEMP_LIMIT_PROP" 0
+        fi
+        ;;
+esac
+
+exit 0
diff --git a/device/rockchip/rk3588/sepolicy_vendor/file_contexts b/device/rockchip/rk3588/sepolicy_vendor/fil
e_contexts
index 7e0f888dc4e..68abfe09b6f 100644
--- a/device/rockchip/rk3588/sepolicy_vendor/file_contexts
+++ b/device/rockchip/rk3588/sepolicy_vendor/file_contexts
@@ -4,3 +4,4 @@
 /dev/spidev0.1   u:object_r:audio_spi_device:s0
 
 /sys/devices/platform/fecc0000.otp/rockchip-otp0/nvmem u:object_r:sysfs_nvmem:s0
+/vendor/bin/lowtemp_limiter\.sh               u:object_r:lowtemp-limiter_exec:s0
diff --git a/device/rockchip/rk3588/sepolicy_vendor/lowtemp-limiter.te b/device/rockchip/rk3588/sepolicy_vendo
r/lowtemp-limiter.te
new file mode 100755
index 00000000000..a90ddf4594c
--- /dev/null
+++ b/device/rockchip/rk3588/sepolicy_vendor/lowtemp-limiter.te
@@ -0,0 +1,29 @@
+type lowtemp-limiter, domain;
+type lowtemp-limiter_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(lowtemp-limiter)
+
+allow lowtemp-limiter vendor_shell_exec:file rx_file_perms;
+allow lowtemp-limiter vendor_toolbox_exec:file rx_file_perms;
+
+allow lowtemp-limiter sysfs:dir r_dir_perms;
+allow lowtemp-limiter sysfs:file rw_file_perms;
+allow lowtemp-limiter sysfs:lnk_file r_file_perms;
+
+allow lowtemp-limiter sysfs_devices_system_cpu:file rw_file_perms;
+allow lowtemp-limiter sysfs_batteryinfo:file r_file_perms;
+allow lowtemp-limiter sysfs_batteryinfo:dir r_dir_perms;
+allow lowtemp-limiter sysfs_batteryinfo:lnk_file r_file_perms;
+allow lowtemp-limiter sysfs_leds:file rw_file_perms;
+allow lowtemp-limiter sysfs_leds:dir r_dir_perms;
+allow lowtemp-limiter sysfs_leds:lnk_file r_file_perms;
+allow lowtemp-limiter sysfs_devfreq_dir:dir r_dir_perms;
+allow lowtemp-limiter sysfs_devfreq_dir:file rw_file_perms;
+allow lowtemp-limiter sysfs_dmc:dir r_dir_perms;
+allow lowtemp-limiter sysfs_dmc:file w_file_perms;
+allow lowtemp-limiter sysfs_dmc:lnk_file r_file_perms;
+allow lowtemp-limiter sysfs_hdmi:lnk_file r_file_perms;
+allow lowtemp-limiter sysfs_gpu:file rw_file_perms;
+
+get_prop(lowtemp-limiter, vendor_system_public_prop)
+set_prop(lowtemp-limiter, vendor_system_public_prop)
diff --git a/device/rockchip/rk3588/sepolicy_vendor/property_contexts b/device/rockchip/rk3588/sepolicy_vendor
/property_contexts
new file mode 100755
index 00000000000..8d9b263220f
--- /dev/null
+++ b/device/rockchip/rk3588/sepolicy_vendor/property_contexts
@@ -0,0 +1 @@
+vendor.lowtemp.                          u:object_r:vendor_system_public_prop:s0

 

posted @ 2026-08-08 15:56  M-kobe  阅读(15)  评论(0)    收藏  举报