The struct cpufreq_driver has been extended to embrace the information
related to boost support.

When "boost_mode" device tree attribute is defined for a platform, the
low_level_boost pointer is filled with proper address. The
.low_level_boost field filled to NULL, indicates that boost is not
supported.

Operations of exynos_cpufreq_boost_trigger() function are protected with
"local" mutex.

Signed-off-by: Lukasz Majewski <[email protected]>
Signed-off-by: Myungjoo Ham <[email protected]>

---
Changes for v2:
- Removal of struct cpufreq_boost
- Removal of the CONFIG_CPU_FREQ_BOOST flag
- low_level_boost with valid address when boost is supported
---
 drivers/cpufreq/exynos-cpufreq.c |   49 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 3197d88..8cf5636 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -33,6 +33,7 @@ static struct cpufreq_freqs freqs;
 static unsigned int locking_frequency;
 static bool frequency_locked;
 static DEFINE_MUTEX(cpufreq_lock);
+static struct cpufreq_cpuinfo *cpufreq_cpu_info;
 
 static int exynos_verify_speed(struct cpufreq_policy *policy)
 {
@@ -154,6 +155,7 @@ out:
        return ret;
 }
 
+static struct cpufreq_driver exynos_driver;
 static int exynos_target(struct cpufreq_policy *policy,
                          unsigned int target_freq,
                          unsigned int relation)
@@ -244,6 +246,9 @@ static struct notifier_block exynos_cpufreq_nb = {
 
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
+       unsigned int max_freq;
+       int ret;
+
        policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
 
        cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
@@ -253,7 +258,19 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy 
*policy)
 
        cpumask_setall(policy->cpus);
 
-       return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+       ret = cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+       if (ret)
+               return ret;
+
+       if (exynos_driver.low_level_boost) {
+               /* disable boost by default */
+               max_freq = cpufreq_frequency_table_max(exynos_info->freq_table,
+                                                      0);
+               policy->cpuinfo.max_freq = policy->max = max_freq;
+               cpufreq_cpu_info = &policy->cpuinfo;
+       }
+
+       return 0;
 }
 
 static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
@@ -264,9 +281,32 @@ static int exynos_cpufreq_cpu_exit(struct cpufreq_policy 
*policy)
 
 static struct freq_attr *exynos_cpufreq_attr[] = {
        &cpufreq_freq_attr_scaling_available_freqs,
+       &cpufreq_freq_attr_boost_available_freqs,
        NULL,
 };
 
+static int exynos_cpufreq_boost_trigger(int state)
+{
+       struct cpufreq_policy *policy = container_of(cpufreq_cpu_info,
+                                                    struct cpufreq_policy,
+                                                    cpuinfo);
+       unsigned int max_freq;
+
+       mutex_lock(&cpufreq_lock);
+       exynos_driver.boost_en = state;
+
+       /* Recalculate maximal frequency */
+       max_freq = cpufreq_frequency_table_max(exynos_info->freq_table,
+                                              exynos_driver.boost_en);
+
+       if (policy->max != max_freq)
+               policy->cpuinfo.max_freq = policy->max = max_freq;
+
+       mutex_unlock(&cpufreq_lock);
+
+       return 0;
+}
+
 static struct cpufreq_driver exynos_driver = {
        .flags          = CPUFREQ_STICKY,
        .verify         = exynos_verify_speed,
@@ -275,7 +315,7 @@ static struct cpufreq_driver exynos_driver = {
        .init           = exynos_cpufreq_cpu_init,
        .exit           = exynos_cpufreq_cpu_exit,
        .name           = "exynos_cpufreq",
-       .attr           = exynos_cpufreq_attr,
+       .attr   = exynos_cpufreq_attr,
 #ifdef CONFIG_PM
        .suspend        = exynos_cpufreq_suspend,
        .resume         = exynos_cpufreq_resume,
@@ -359,6 +399,8 @@ static struct of_device_id exynos_cpufreq_of_match[] 
__initconst = {
 
 static int __init exynos_cpufreq_probe(struct platform_device *pdev)
 {
+       struct device_node *node = pdev->dev.of_node;
+
        int ret = -EINVAL;
 
        exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -391,6 +433,9 @@ static int __init exynos_cpufreq_probe(struct 
platform_device *pdev)
        }
 
        locking_frequency = exynos_getspeed(0);
+       if (of_property_read_bool(node, "boost_mode"))
+               exynos_driver.low_level_boost =
+                       &exynos_cpufreq_boost_trigger;
 
        register_pm_notifier(&exynos_cpufreq_nb);
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to