|
@@ -16,7 +16,6 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
#include <linux/cpufreq.h>
|
|
|
-#include <linux/suspend.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
|
|
|
#include <plat/cpu.h>
|
|
@@ -24,12 +23,8 @@
|
|
|
#include "exynos-cpufreq.h"
|
|
|
|
|
|
static struct exynos_dvfs_info *exynos_info;
|
|
|
-
|
|
|
static struct regulator *arm_regulator;
|
|
|
-
|
|
|
static unsigned int locking_frequency;
|
|
|
-static bool frequency_locked;
|
|
|
-static DEFINE_MUTEX(cpufreq_lock);
|
|
|
|
|
|
static int exynos_cpufreq_get_index(unsigned int freq)
|
|
|
{
|
|
@@ -134,83 +129,13 @@ out:
|
|
|
|
|
|
static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
|
|
|
{
|
|
|
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- mutex_lock(&cpufreq_lock);
|
|
|
-
|
|
|
- if (frequency_locked)
|
|
|
- goto out;
|
|
|
-
|
|
|
- ret = exynos_cpufreq_scale(freq_table[index].frequency);
|
|
|
-
|
|
|
-out:
|
|
|
- mutex_unlock(&cpufreq_lock);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CONFIG_PM
|
|
|
-static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
|
|
|
-{
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
|
|
|
-{
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-/**
|
|
|
- * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
|
|
|
- * context
|
|
|
- * @notifier
|
|
|
- * @pm_event
|
|
|
- * @v
|
|
|
- *
|
|
|
- * While frequency_locked == true, target() ignores every frequency but
|
|
|
- * locking_frequency. The locking_frequency value is the initial frequency,
|
|
|
- * which is set by the bootloader. In order to eliminate possible
|
|
|
- * inconsistency in clock values, we save and restore frequencies during
|
|
|
- * suspend and resume and block CPUFREQ activities. Note that the standard
|
|
|
- * suspend/resume cannot be used as they are too deep (syscore_ops) for
|
|
|
- * regulator actions.
|
|
|
- */
|
|
|
-static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
|
|
|
- unsigned long pm_event, void *v)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- switch (pm_event) {
|
|
|
- case PM_SUSPEND_PREPARE:
|
|
|
- mutex_lock(&cpufreq_lock);
|
|
|
- frequency_locked = true;
|
|
|
- mutex_unlock(&cpufreq_lock);
|
|
|
-
|
|
|
- ret = exynos_cpufreq_scale(locking_frequency);
|
|
|
- if (ret < 0)
|
|
|
- return NOTIFY_BAD;
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case PM_POST_SUSPEND:
|
|
|
- mutex_lock(&cpufreq_lock);
|
|
|
- frequency_locked = false;
|
|
|
- mutex_unlock(&cpufreq_lock);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return NOTIFY_OK;
|
|
|
+ return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
|
|
|
}
|
|
|
|
|
|
-static struct notifier_block exynos_cpufreq_nb = {
|
|
|
- .notifier_call = exynos_cpufreq_pm_notifier,
|
|
|
-};
|
|
|
-
|
|
|
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|
|
{
|
|
|
policy->clk = exynos_info->cpu_clk;
|
|
|
+ policy->suspend_freq = locking_frequency;
|
|
|
return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
|
|
|
}
|
|
|
|
|
@@ -227,8 +152,7 @@ static struct cpufreq_driver exynos_driver = {
|
|
|
.boost_supported = true,
|
|
|
#endif
|
|
|
#ifdef CONFIG_PM
|
|
|
- .suspend = exynos_cpufreq_suspend,
|
|
|
- .resume = exynos_cpufreq_resume,
|
|
|
+ .suspend = cpufreq_generic_suspend,
|
|
|
#endif
|
|
|
};
|
|
|
|
|
@@ -263,19 +187,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
|
|
|
goto err_vdd_arm;
|
|
|
}
|
|
|
|
|
|
+ /* Done here as we want to capture boot frequency */
|
|
|
locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
|
|
|
|
|
|
- register_pm_notifier(&exynos_cpufreq_nb);
|
|
|
-
|
|
|
- if (cpufreq_register_driver(&exynos_driver)) {
|
|
|
- pr_err("%s: failed to register cpufreq driver\n", __func__);
|
|
|
- goto err_cpufreq;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-err_cpufreq:
|
|
|
- unregister_pm_notifier(&exynos_cpufreq_nb);
|
|
|
+ if (!cpufreq_register_driver(&exynos_driver))
|
|
|
+ return 0;
|
|
|
|
|
|
+ pr_err("%s: failed to register cpufreq driver\n", __func__);
|
|
|
regulator_put(arm_regulator);
|
|
|
err_vdd_arm:
|
|
|
kfree(exynos_info);
|