]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/cpufreq/exynos-cpufreq.c
cpufreq: exynos: Fix hang in pm handler due to frequency mismatch
[karo-tx-linux.git] / drivers / cpufreq / exynos-cpufreq.c
index 232208cf6c0369e355bc7def71dfb32f9ffe0d68..67e89ef55168159f03e665902ca1ffa3b94c6882 100644 (file)
@@ -65,13 +65,14 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
        struct cpufreq_policy *policy = cpufreq_cpu_get(0);
        unsigned int arm_volt, safe_arm_volt = 0;
        unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
-       unsigned int index, old_index;
+       int index, old_index;
        int ret = 0;
 
        freqs.old = policy->cur;
+       freqs.new = target_freq;
        freqs.cpu = policy->cpu;
 
-       if (target_freq == freqs.old)
+       if (freqs.new == freqs.old)
                goto out;
 
        /*
@@ -159,7 +160,8 @@ static int exynos_target(struct cpufreq_policy *policy,
 {
        struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
        unsigned int index;
-       int ret;
+       unsigned int new_freq;
+       int ret = 0;
 
        mutex_lock(&cpufreq_lock);
 
@@ -172,9 +174,9 @@ static int exynos_target(struct cpufreq_policy *policy,
                goto out;
        }
 
-       freqs.new = freq_table[index].frequency;
+       new_freq = freq_table[index].frequency;
 
-       ret = exynos_cpufreq_scale(freqs.new);
+       ret = exynos_cpufreq_scale(new_freq);
 
 out:
        mutex_unlock(&cpufreq_lock);
@@ -246,8 +248,6 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
 
-       locking_frequency = exynos_getspeed(0);
-
        /* set the transition latency value */
        policy->cpuinfo.transition_latency = 100000;
 
@@ -268,13 +268,26 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
        return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
 }
 
+static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
+
+static struct freq_attr *exynos_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
 static struct cpufreq_driver exynos_driver = {
        .flags          = CPUFREQ_STICKY,
        .verify         = exynos_verify_speed,
        .target         = exynos_target,
        .get            = exynos_getspeed,
        .init           = exynos_cpufreq_cpu_init,
+       .exit           = exynos_cpufreq_cpu_exit,
        .name           = "exynos_cpufreq",
+       .attr           = exynos_cpufreq_attr,
 #ifdef CONFIG_PM
        .suspend        = exynos_cpufreq_suspend,
        .resume         = exynos_cpufreq_resume,
@@ -312,6 +325,8 @@ static int __init exynos_cpufreq_init(void)
                goto err_vdd_arm;
        }
 
+       locking_frequency = exynos_getspeed(0);
+
        register_pm_notifier(&exynos_cpufreq_nb);
 
        if (cpufreq_register_driver(&exynos_driver)) {