#!/bin/bash

cd /sys/devices/system/cpu
myself=$( basename $0 )

function usage() {
	echo "$0: (normal|full|max|min|<frequency>) [turbo|noturbo] [show]"
	echo "wrapper to force enable or disable pstates as well as"
	echo "CPU frequencies."
	echo "<frequency> is given in MHz. The CPU may set the frequency"
	echo "to a slightly smaller value that fits its capabilities."
	echo ""; echo "Multiple arguments can be given. Example:"
	echo "$myself max full turbo"
	echo "    sets the CPU frequency ceiling to maximum"
	echo "    disables the CPU's pstates"
	echo "    unconditionally enables turbo mode"
	echo ""; echo "$myself normal turbo"
	echo "    leaves frequencies as they are"
	echo "    enables all pstates"
	echo "    enables turbo mode"
	echo ""; echo "$myself min normal noturbo"
	echo "    sets the CPU frequency ceiling to minimum"
	echo "    enables all pstates"
	echo "    disables turbo mode"
	exit 0
}

if [ -z "$1" ]; then
  usage
fi

num=$(grep processor /proc/cpuinfo | wc -l)

while [ ! -z "$1" ]; do

case "$1" in
  full)

	# CPU at pedal to the metal:
	i=$num
	while [ $i -gt 0 ]; do
	  i=$(( $i - 1 ))
	  for j in 0 1 2 3 4; do
	    echo 1 > cpu$i/cpuidle/state$j/disable
	  done
	done
  ;;

  normal)
	i=$num
	while [ $i -gt 0 ]; do
	  i=$(( $i - 1 ))
	  for j in 0 1 2 3 4; do
	    echo 0 > cpu$i/cpuidle/state$j/disable
          done
        done
  ;;

  turbo)
  	# this is the default already:
	echo 0 > intel_pstate/no_turbo
  ;;

  noturbo)
	echo 1 > intel_pstate/no_turbo
  ;;

  [0-9]*)
	# this sets the maximum only, the minimum frequency setting
	# remains untouched. Disabling the pstates (see above) maintains
	# the higher base level, if desired.
	f=$1
	min=$( cat cpu0/cpufreq/cpuinfo_min_freq )
	max=$( cat cpu0/cpufreq/cpuinfo_max_freq )
	wants=$(( $f * 1000 ))
	if [ "$wants" -gt "$max" ]; then
	    echo "warning: setting frequency to maximum of $(( $max / 1000 )) MHz"
	    $0 max
	    break
	fi
	if [ "$wants" -lt "$min" ]; then
	    echo "warning: setting frequency to minimum of $(( $min / 1000 )) MHz"
	    $0 min
	    break
	fi
	i=$num
	while [ $i -gt 0 ]; do
	    i=$(( $i - 1 ))
	    echo "$wants" > cpu$i/cpufreq/scaling_max_freq
	done

  ;;

  max)
	max=$( cat cpu0/cpufreq/cpuinfo_max_freq )
	i=$num
	while [ $i -gt 0 ]; do
	    i=$(( $i - 1 ))
	    echo "$max" > cpu$i/cpufreq/scaling_max_freq
	done
  ;;

  min)
	min=$( cat cpu0/cpufreq/cpuinfo_min_freq )
	i=$num
	while [ $i -gt 0 ]; do
	    i=$(( $i - 1 ))
	    echo "$min" > cpu$i/cpufreq/scaling_max_freq
	done
  ;;
  show)
	sleep 0.3
	cat /sys/devices/system/cpu/cpu{0..3}/cpufreq/cpuinfo_cur_freq
	;;

  *)
	usage
	;;
esac

shift

done
