diff options
author | Xiao Bo Zhao <xiaoboz@nvidia.com> | 2012-06-29 12:46:11 -0700 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-01 17:39:25 -0700 |
commit | 9046d52e1aeec6bb5f133426733bf77b71f10118 (patch) | |
tree | 95cf5ddf4512c2755862e0c1d12904996b363df6 /drivers/cpufreq | |
parent | 50008402a6f093e48dee05fc88bc54750b97ae25 (diff) |
ARM: Tegra: Added support to run at two frequency modes
CPU clock is now capped at an normal frequency that is below
its maximum and allowed to run at a high frequency
only once within a period of time. By default the delay is set to
5*DOWN_DELAY, allowing a maximum of 20% high frequency time.
Sysfs knobs were also added that allows userspace tuning
Bug 1003531
Change-Id: Ie4a0e565630187bdacd6f31b1f35778eb31bfc81
Signed-off-by: Xiao Bo Zhao <xiaoboz@nvidia.com>
Reviewed-on: http://git-master/r/118163
Reviewed-by: Peter Boonstoppel <pboonstoppel@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/cpufreq_interactive.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 798930ffe1f4..20a9b6d22156 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -43,6 +43,7 @@ struct cpufreq_interactive_cpuinfo { u64 freq_change_time; u64 freq_change_time_in_idle; u64 freq_change_time_in_iowait; + u64 last_high_freq_time; struct cpufreq_policy *policy; struct cpufreq_frequency_table *freq_table; unsigned int target_freq; @@ -92,6 +93,24 @@ static unsigned long min_sample_time; #define DEFAULT_TIMER_RATE 20000; static unsigned long timer_rate; +/* + * The minimum delay before frequency is allowed to raise over normal rate. + * Since it must remain at high frequency for a minimum of MIN_SAMPLE_TIME + * once it rises, setting this delay to a multiple of MIN_SAMPLE_TIME + * becomes the best way to enforce a square wave. + * e.g. 5*MIN_SAMPLE_TIME = 20% high freq duty cycle + */ +#define DEFAULT_HIGH_FREQ_MIN_DELAY 5*DEFAULT_MIN_SAMPLE_TIME +static unsigned long high_freq_min_delay; + +/* + * The maximum frequency CPUs are allowed to run normally + * 0 if disabled + */ +#define DEFAULT_MAX_NORMAL_FREQ 0 +static unsigned long max_normal_freq; + + /* Defines to control mid-range frequencies */ #define DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD 95 @@ -274,6 +293,20 @@ static void cpufreq_interactive_timer(unsigned long data) goto rearm; } + /* + * Can only overclock if the delay is satisfy. Otherwise, cap it to + * maximum allowed normal frequency + */ + if (max_normal_freq && (new_freq > max_normal_freq)) { + if (cputime64_sub(pcpu->timer_run_time, pcpu->last_high_freq_time) + < high_freq_min_delay) { + new_freq = max_normal_freq; + } + else { + pcpu->last_high_freq_time = pcpu->timer_run_time; + } + } + if (new_freq < pcpu->target_freq) { pcpu->target_freq = new_freq; spin_lock_irqsave(&down_cpumask_lock, flags); @@ -552,7 +585,9 @@ DECL_CPUFREQ_INTERACTIVE_ATTR(max_boost) DECL_CPUFREQ_INTERACTIVE_ATTR(midrange_max_boost) DECL_CPUFREQ_INTERACTIVE_ATTR(sustain_load) DECL_CPUFREQ_INTERACTIVE_ATTR(min_sample_time) -DECL_CPUFREQ_INTERACTIVE_ATTR(timer_rate); +DECL_CPUFREQ_INTERACTIVE_ATTR(timer_rate) +DECL_CPUFREQ_INTERACTIVE_ATTR(high_freq_min_delay) +DECL_CPUFREQ_INTERACTIVE_ATTR(max_normal_freq) #undef DECL_CPUFREQ_INTERACTIVE_ATTR @@ -567,6 +602,8 @@ static struct attribute *interactive_attributes[] = { &sustain_load_attr.attr, &min_sample_time_attr.attr, &timer_rate_attr.attr, + &high_freq_min_delay_attr.attr, + &max_normal_freq_attr.attr, NULL, }; @@ -604,7 +641,8 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, pcpu->freq_change_time_in_iowait = get_cpu_iowait_time(j, NULL); pcpu->time_in_iowait = pcpu->freq_change_time_in_iowait; - + if (!pcpu->last_high_freq_time) + pcpu->last_high_freq_time = pcpu->freq_change_time; pcpu->timer_idlecancel = 1; pcpu->governor_enabled = 1; smp_wmb(); @@ -694,6 +732,8 @@ static int __init cpufreq_interactive_init(void) midrange_go_maxspeed_load = DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD; min_sample_time = DEFAULT_MIN_SAMPLE_TIME; timer_rate = DEFAULT_TIMER_RATE; + high_freq_min_delay = DEFAULT_HIGH_FREQ_MIN_DELAY; + max_normal_freq = DEFAULT_MAX_NORMAL_FREQ; /* Initalize per-cpu timers */ for_each_possible_cpu(i) { |