shell script to undervolt AMD Ryzen laptops
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
amd_laptop_undervolt/undervolt.sh

87 lines
2.3 KiB

#!/bin/sh -e
# TODO: check for root privileges
# TODO: check if all the required tools are available
CPUS="$(nproc)"
GOVERNOR='ondemand'
# Out your wanted values here
CORE_SPEED_HZ_P0=2300000 # 2.30GHz slightly over the base (2.10GHz)
CORE_SPEED_HZ_P1=1450000 # 1.45GHz
CORE_SPEED_HZ_P2=1000000 # 1.00GHz
# wanted voltage in millivolts
VOLTAGE_MV_P0=1125 # this should be stable
VOLTAGE_MV_P1=900
VOLTAGE_MV_P2=850
# Power limits
SUSTAINED_LIMIT_MW=10000
SLOW_LIMIT_MW=20000
# Temperature limits
MAX_TEMP_C=85
# set cpu frequency scaling driver, use acpi_cpufreq since the ryzen 5 3500u
# does not support the amd_pstate driver
# acpi_cpufreq is already the default
# enable cpu frequency boost if available
echo 1 > /sys/devices/system/cpu/cpufreq/boost
# set governor
for c in $(seq 0 $((CPUS-1)))
do
echo $GOVERNOR > /sys/devices/system/cpu/"cpu$c"/cpufreq/scaling_governor
done
#
# set voltage
# ===========
VID_P0="$(amdctl -u $VOLTAGE_MV_P0 | grep vid | awk '{print $3}')"
VID_P1="$(amdctl -u $VOLTAGE_MV_P1 | grep vid | awk '{print $3}')"
VID_P2="$(amdctl -u $VOLTAGE_MV_P2 | grep vid | awk '{print $3}')"
for c in 0 .. $((CPUS-1))
do
amdctl -s -m -c $c -p 0 -v "$VID_P0"
amdctl -s -m -c $c -p 1 -v "$VID_P1"
amdctl -s -m -c $c -p 2 -v "$VID_P2"
done
#
# set frequency
# =============
# TODO: get this from amdctl
REFERENCE_CLOCK=100000
DID_P0="$(amdctl -c 0 -p 0 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')"
DID_P1="$(amdctl -c 0 -p 1 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')"
DID_P2="$(amdctl -c 0 -p 2 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')"
# FIXME: this is taken from https://github.com/kevinlekiller/amdctl/blob/master/amdctl.c#L988
# it would be better to submint a pull request and add an option to
# this automatically for each processor family
FID_P0="$(((CORE_SPEED_HZ_P0*DID_P0)/(REFERENCE_CLOCK*2)))"
FID_P1="$(((CORE_SPEED_HZ_P1*DID_P1)/(REFERENCE_CLOCK*2)))"
FID_P2="$(((CORE_SPEED_HZ_P2*DID_P2)/(REFERENCE_CLOCK*2)))"
for c in 0 .. $((CPUS-1))
do
amdctl -s -m -c $c -p 0 -f $FID_P0
amdctl -s -m -c $c -p 1 -f $FID_P1
amdctl -s -m -c $c -p 2 -f $FID_P2
done
#
# Power Limits
# ============
ryzenadj --stapm-limit=$SUSTAINED_LIMIT_MW \
--tctl-temp=$MAX_TEMP_C \
--slow-limit=$SLOW_LIMIT_MW
# TODO: undervolt and overclock slightly the GPU