Do you own a nForce2 based mainboards? Than that is maybe for you
if you want to dynamically change you CPU speed and voltage (power
saving when idle).
Frequency changing is available on all nForce2-based mainboards with
all CPUs which run on that board. However for dynamic CPU core voltage
changing there must a ATXP1 chip on the board.
On this boards VCore changing is supported (more are possible):
- Abit NF7
Aopen AK79D-400VN
Chaintech CT-7NJ(S,L1)
DFI Infinity NFII Ultra
DFI Lanparty NFII Ultra
Epox 8RDA+
Epox 8(R,G)DA(3,6,+,I,E)
Shuttle AN35N Ultra V1.1
Shuttle SN45G (not V3)
Soltek 75FRN2-L
Soltek NV400-L64
Some maybe think why not change the FID (multiplier) like the Athlon Mobile (there are L-bridge mods to change a XP to a Mobile [1]). With some chipsets this is possible and there
are patches for powernow-k7 to work on desktop boards. Unfortunately I've not heard yet that this works with the nForce2 chipset.
So now lets begin:
1. Get the cpufreq/atxp1 module working :
Kernel 2.6.10 includes cpufreq-nforce2, but you can also
get it from http://www.hasw.net/linux
Kernel patches are available here: http://www.hasw.net/linux/atxp1-0.6.tar.bz2
Now in the kernel-config:
Code: Select all
Power management options (ACPI, APM) --->
CPU Frequency scaling --->
[*] CPU Frequency scaling
Default CPUFreq governor (userspace)
<M> nVidia nForce2 FSB changing (only 2.6.10)
Device Drivers --->
I2C support --->
<*> I2C support
<M> I2C device interface
I2C Hardware Bus support --->
<M> ISA Bus support (for hardware-monitoring chips)
<M> Nvidia Nforce2
Hardware Sensors Chip support --->
<M> ITE IT87xx and compatibles
<M> Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F
<M> Winbond W83627HF, W83627THF, W83637HF, W83697HF (depending which chip your board uses)
Other I2C Chip support --->
<M> Attansic ATXP1 VID controller
2. Test the cpufreq module:
Code: Select all
root@hasw root # modprobe cpufreq-nforce2
root@hasw root # dmesg
......
cpufreq: Detected nForce2 chipset revision A2
cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.
cpufreq: FSB currently at 200 MHz, FID 9.0
If the detected FSB isn't correct, stop here and contact me (hasw@hasw.net).
The FID can be set with:
Code: Select all
root@hasw cpufreq # modprobe cpufreq-nforce2 fid=95
Otherwise you have now the cpufreq control-files in /sys:
Code: Select all
root@hasw root # cd /sys/devices/system/cpu/cpu0/cpufreq/
root@hasw cpufreq # cat scaling_max_freq
1800000
root@hasw cpufreq # cat scaling_min_freq
1278000
The frequency is in kHz. If you have compiled in multiple cpufreq governors, you have to switch it
first, before you can do changes via userspace:
Code: Select all
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Now you can try to set a new frequency, for example:
Code: Select all
root@hasw cpufreq # echo 1700000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
root@hasw cpufreq # cat /proc/cpuinfo
....
cpu MHz : 1696.509
....
Because of some internal chipset timings, the FSB is limited downwards. If no module
option is given, the minimum FSB defaults to FSB at boot time - 50 MHz which should
work in the most cases.
If you want to set a lower FSB limit, use the min_fsb module option:
Code: Select all
root@hasw cpufreq # modprobe cpufreq-nforce2 min_fsb=140
On the most boards, the limit is between 130 and 140 MHz. To be on the save side, use 140 instead of 133.
For the Shuttle AN35N you can try to lower it < 100 MHz, they've the greatest working FSB range (some 60-240 MHz).
Get prime95 from http://www.mersenne.org/freesoft.htm for stress testing. It works good for me because the torture test stops when the CPU produces calculation errors. It detects
errors even if it seems that all is working.
Stop X and all uneeded services, so that there's no/small impact if the computer crashes (you have backups, of course
Now run the prime95 torture test and lower the CPU speed every 30s approx. 100 MHz:
Code: Select all
root@hasw cpufreq # echo 1700000 > scaling_setspeed
root@hasw cpufreq # echo 1600000 > scaling_setspeed
...
If prime95 reports hardware failure stop and add 50-100 MHz. Let prime95 run about one or two hours. If it crashes immediately, you also know where to stop
Now you have your minimum FSB and can add it as module-option:
Code: Select all
root@hasw root # echo "options cpufreq-nforce2 min_fsb=142" > /etc/modules.d/cpufreq-nforce2
root@hasw root # modules-update
4. Get the atxp1 module working:
Code: Select all
root@hasw root # modprobe i2c_nforce2
root@hasw root # modprobe atxp1
root@hasw root # dmesg
.... atxp1: Detected on SMBus nForce2 adapter at 5000, address 0x37
....
To control the changes, also get hardware monitoring working:
Code: Select all
root@hasw root # modprobe i2c_isa
root@hasw root # modprobe w83781d
root@hasw root # cat /sys/bus/i2c/devices/2-0290/in1_input
1648
This is for my 8RDA+ and shows 1648 mV CPU core voltage. You may have another monitoring chip and/or VCore input.
Now first lower your CPU frequency and then the voltage:
Code: Select all
root@hasw root # echo 1400000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
root@hasw root # echo 1500 > /sys/bus/i2c/devices/0-0037/cpu_vid
root@hasw root # dmesg
....
atxp1: Setting VCore to 1500 mV (0x0e)
root@hasw root # cat /sys/bus/i2c/devices/2-0290/in1_input
1520
There's often a small positive offset, so that's normal if it shows a little bit more.
5. Find lowest core voltage for different frequencys
You can use the same mechism used to find the minimum FSB. The smallest possible steps are 25mV. Decrease the voltage until it reports errors, add 50mV and you should be on the safe (stable) side.
6. Save changes
You now have the control over your CPU speed and core voltage. Happy power-saving
Add the modules to your /etc/modules.autoload.d/kernel-2.6 file to load the at startup, mine shows:
Code: Select all
...
cpufreq-nforce2
i2c-nforce2
i2c-isa
atxp1
w83781d
This does not work because the permissions are reset after some time.
---------------------------------------------------------------------
Because the /sys files are only writeable by root, you may want to write them as user. If your user is the the group wheel you can add to your /etc/conf.d/local.start:
Code: Select all
# Change cpufreq permission
CPUDIR="/sys/devices/system/cpu/cpu0/cpufreq"
if [ -d $CPUDIR ]
then
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
chgrp wheel $CPUDIR/scaling_setspeed
chmod 664 $CPUDIR/scaling_setspeed
fi
# Change ATXP1 permission
ATXP1="/sys/bus/i2c/devices/0-0037/cpu_vid"
if [ -f $ATXP1 ]
then
chgrp wheel $ATXP1
chmod 664 $ATXP1
fi
Also important is that the most BIOSes only reset the voltages when the power was totally off (pull plug).
So you have to reset your VCore before reboot!
You can put this in your /etc/conf.d/local.stop
Code: Select all
# Reset CPU core voltage
ATXP1="/sys/bus/i2c/devices/0-0037/cpu_vid"
if [ -f $ATXP1 ]
then
echo 1600 > $ATXP1
fi
7. Some example scripts
Here are some example scripts to set CPU speed and core voltage:
set_cpuspeed.sh
Code: Select all
#!/bin/sh
CPUDIR="/sys/devices/system/cpu/cpu0/cpufreq"
VCORE="/sys/bus/i2c/devices/0-0037/cpu_vid"
# Check if cpufreq driver and ATXP1 s available
test -w $CPUDIR/scaling_setspeed || exit 0
test -w $ATXP1 || exit 0
if [ -z "$1" -o -z "$2" ]
then
echo "Usage: $0 (CPU speed in MHz) (Core voltage in mV)"
exit 0
fi
CFREQ="`cat $CPUDIR/scaling_cur_freq`"
CVCORE="`cat $VCORE`"
NFREQ="$(($1*1000))"
NVCORE="$2"
if [ $NFREQ -gt $CFREQ ]
then
# First apply new Vcore
echo $NVCORE > $VCORE
# ...then new frequency
echo $NFREQ > $CPUDIR/scaling_setspeed
elif [ $NFREQ -lt $CFREQ ]
then
# First frequency
echo $NFREQ > $CPUDIR/scaling_setspeed
echo $NVCORE > $VCORE
fi
I'm using fluxbox and using a small script to generate a menu with CPU speed presets:
cpuspeed:
Code: Select all
1800@1625
1400@1450
1278@1150
create_cpumenu.sh:
Code: Select all
#!/bin/sh
FBDIR="$HOME/.fluxbox"
if [ ! -f $FBDIR/cpuspeed ]
then
exit 0
fiecho "[submenu] (cpufreq) {CPU speed}" > $FBDIR/cpumenu
for SPEED in `cat $FBDIR/cpuspeed`
do
FREQ="`echo $SPEED | cut -d'@' -f1`"
VCORE="`echo $SPEED | cut -d'@' -f2`"
echo "[exec] ($FREQ MHz @ $VCORE mV) {$FBDIR/set_cpuspeed.sh $FREQ $VCORE}" >> $FBDIR/cpumenu
done
echo "[end]" >> $FBDIR/cpumenu
Also my .torsmorc (system monitor) gets updated:
Code: Select all
${color grey}Sensor:
CPU:$color ${execi 15 ~/.sensor-cpu.sh}${color grey}
sensor-cpu.sh:
Code: Select all
CPUDIR="/sys/devices/system/cpu/cpu0/cpufreq"
SENSOR="/sys/bus/i2c/devices/2-0290"
test -d $CPUDIR || exit 0
test -d $SENSOR || exit 0
FREQ="$((`cat $CPUDIR/scaling_cur_freq`/1000)) MHz"
#FREQ="`awk '/MHz/ {print $4}' /proc/cpuinfo | sed -e 's/\..*$//'` MHz"
VCORE="`cat $SENSOR/in1_input` mV"
TEMP="$((`cat $SENSOR/temp2_input` / 1000)) <B0>C"
echo -n "$FREQ @ $VCORE ($TEMP)"
There are many other possibilities, including dynamic changing depending on the CPU load, etc.
Here is a nice Python-script which changes frequency and voltage on demand: http://www.lextech.net/work/autoFreq/



