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

浙公网安备 33010602011771号