diff options
author | Jinyoung Park <jinyoungp@nvidia.com> | 2013-09-02 15:02:05 +0900 |
---|---|---|
committer | Gabby Lee <galee@nvidia.com> | 2013-09-02 06:38:11 -0700 |
commit | 9c8338e70cddd6c4518f75944d20611c90e33ad5 (patch) | |
tree | 11e224e107f27c1f32f0704168271bb84d16e2a8 | |
parent | 57de2dbf25c025834fa7fbcd1d440b9e05179ce1 (diff) |
ARM: tegra: cpu: Ensure CPU freq with suspend freq during pre/post suspend
Tegra CPU driver fixes CPU freq with a selected suspend freq between
pre-suspend and post-suspend. In this pre/post suspend period, the Tegra
CPU driver ignores CPU freq scaling requests from the CPU freq governor.
But the CPU freq governor keep working until the system suspended.
So the CPU freq governor updates its status even if the system is in
the pre/post suspend period.
This makes unexpected CPU freq setting issue on post-suspend.
To ensure CPU freq with the selected suspend freq in the pre/post
suspend period, set a policy max freq on CPU freq governor to the
selected suspend freq via PM QoS at pre-suspend and release the setting
via PM QoS at post-suspend.
Bug 1354391
Change-Id: I8efa6dd438a37adc7cadfb1d36eb7340a4e85c79
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/268955
Reviewed-by: Gabby Lee <galee@nvidia.com>
Tested-by: Gabby Lee <galee@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 092da7e7c02b..6f90c1c4852f 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -33,6 +33,7 @@ #include <linux/suspend.h> #include <linux/debugfs.h> #include <linux/cpu.h> +#include <linux/pm_qos.h> #include <mach/clk.h> @@ -55,6 +56,7 @@ static DEFINE_MUTEX(tegra_cpu_lock); static bool is_suspended; static int suspend_index; static unsigned int volt_capped_speed; +static struct pm_qos_request cpufreq_max_req; static bool force_policy_max; @@ -695,15 +697,18 @@ static int tegra_target(struct cpufreq_policy *policy, mutex_lock(&tegra_cpu_lock); - ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &idx); - if (ret) - goto _out; + if (!is_suspended) { + ret = cpufreq_frequency_table_target(policy, freq_table, + target_freq, relation, &idx); + if (ret) + goto _out; + + freq = freq_table[idx].frequency; - freq = freq_table[idx].frequency; + target_cpu_speed[policy->cpu] = freq; - target_cpu_speed[policy->cpu] = freq; - ret = tegra_cpu_set_speed_cap_locked(&new_speed); + ret = tegra_cpu_set_speed_cap_locked(&new_speed); + } _out: mutex_unlock(&tegra_cpu_lock); @@ -714,23 +719,40 @@ _out: static int tegra_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { - mutex_lock(&tegra_cpu_lock); if (event == PM_SUSPEND_PREPARE) { + int i; + + pm_qos_update_request(&cpufreq_max_req, + freq_table[suspend_index].frequency); + + mutex_lock(&tegra_cpu_lock); is_suspended = true; + for_each_possible_cpu(i) { + if (target_cpu_speed[i] > + freq_table[suspend_index].frequency) + target_cpu_speed[i] = + freq_table[suspend_index].frequency; + } pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n", freq_table[suspend_index].frequency); tegra_update_cpu_speed(freq_table[suspend_index].frequency); tegra_auto_hotplug_governor( freq_table[suspend_index].frequency, true); + mutex_unlock(&tegra_cpu_lock); } else if (event == PM_POST_SUSPEND) { unsigned int freq; + + mutex_lock(&tegra_cpu_lock); is_suspended = false; tegra_cpu_edp_init(true); tegra_cpu_set_speed_cap_locked(&freq); pr_info("Tegra cpufreq resume: restoring frequency to %d kHz\n", freq); + mutex_unlock(&tegra_cpu_lock); + + pm_qos_update_request(&cpufreq_max_req, + PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE); } - mutex_unlock(&tegra_cpu_lock); return NOTIFY_OK; } @@ -863,6 +885,9 @@ static int __init tegra_cpufreq_init(void) tegra_cpu_edp_init(false); mutex_unlock(&tegra_cpu_lock); + pm_qos_add_request(&cpufreq_max_req, PM_QOS_CPU_FREQ_MAX, + PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE); + ret = register_pm_notifier(&tegra_cpu_pm_notifier); if (ret) |