Merge branch 'pm-opp' into pm-cpufreq

This commit is contained in:
Rafael J. Wysocki 2015-09-03 02:46:01 +02:00
commit 0ed537b5fd
301 changed files with 5454 additions and 2298 deletions

View file

@ -36,6 +36,12 @@ struct private_data {
unsigned int voltage_tolerance; /* in percentage */
};
static struct freq_attr *cpufreq_dt_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL, /* Extra space for boost-attr if required */
NULL,
};
static int set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct dev_pm_opp *opp;
@ -184,7 +190,6 @@ try_again:
static int cpufreq_init(struct cpufreq_policy *policy)
{
struct cpufreq_dt_platform_data *pd;
struct cpufreq_frequency_table *freq_table;
struct device_node *np;
struct private_data *priv;
@ -193,6 +198,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
struct clk *cpu_clk;
unsigned long min_uV = ~0, max_uV = 0;
unsigned int transition_latency;
bool need_update = false;
int ret;
ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
@ -208,8 +214,47 @@ static int cpufreq_init(struct cpufreq_policy *policy)
goto out_put_reg_clk;
}
/* OPPs might be populated at runtime, don't check for error here */
of_init_opp_table(cpu_dev);
/* Get OPP-sharing information from "operating-points-v2" bindings */
ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
if (ret) {
/*
* operating-points-v2 not supported, fallback to old method of
* finding shared-OPPs for backward compatibility.
*/
if (ret == -ENOENT)
need_update = true;
else
goto out_node_put;
}
/*
* Initialize OPP tables for all policy->cpus. They will be shared by
* all CPUs which have marked their CPUs shared with OPP bindings.
*
* For platforms not using operating-points-v2 bindings, we do this
* before updating policy->cpus. Otherwise, we will end up creating
* duplicate OPPs for policy->cpus.
*
* OPPs might be populated at runtime, don't check for error here
*/
of_cpumask_init_opp_table(policy->cpus);
if (need_update) {
struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
if (!pd || !pd->independent_clocks)
cpumask_setall(policy->cpus);
/*
* OPP tables are initialized only for policy->cpu, do it for
* others as well.
*/
set_cpus_sharing_opps(cpu_dev, policy->cpus);
of_property_read_u32(np, "clock-latency", &transition_latency);
} else {
transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
}
/*
* But we need OPP table to function so if it is not there let's
@ -230,7 +275,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
if (of_property_read_u32(np, "clock-latency", &transition_latency))
if (!transition_latency)
transition_latency = CPUFREQ_ETERNAL;
if (!IS_ERR(cpu_reg)) {
@ -291,11 +336,16 @@ static int cpufreq_init(struct cpufreq_policy *policy)
goto out_free_cpufreq_table;
}
policy->cpuinfo.transition_latency = transition_latency;
/* Support turbo/boost mode */
if (policy_has_boost_freq(policy)) {
/* This gets disabled by core on driver unregister */
ret = cpufreq_enable_boost_support();
if (ret)
goto out_free_cpufreq_table;
cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
}
pd = cpufreq_get_driver_data();
if (!pd || !pd->independent_clocks)
cpumask_setall(policy->cpus);
policy->cpuinfo.transition_latency = transition_latency;
of_node_put(np);
@ -306,7 +356,8 @@ out_free_cpufreq_table:
out_free_priv:
kfree(priv);
out_free_opp:
of_free_opp_table(cpu_dev);
of_cpumask_free_opp_table(policy->cpus);
out_node_put:
of_node_put(np);
out_put_reg_clk:
clk_put(cpu_clk);
@ -322,7 +373,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
of_free_opp_table(priv->cpu_dev);
of_cpumask_free_opp_table(policy->related_cpus);
clk_put(policy->clk);
if (!IS_ERR(priv->cpu_reg))
regulator_put(priv->cpu_reg);
@ -367,7 +418,7 @@ static struct cpufreq_driver dt_cpufreq_driver = {
.exit = cpufreq_exit,
.ready = cpufreq_ready,
.name = "cpufreq-dt",
.attr = cpufreq_generic_attr,
.attr = cpufreq_dt_attr,
};
static int dt_cpufreq_probe(struct platform_device *pdev)

View file

@ -2412,6 +2412,49 @@ int cpufreq_boost_supported(void)
}
EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
static int create_boost_sysfs_file(void)
{
int ret;
if (!cpufreq_boost_supported())
return 0;
/*
* Check if driver provides function to enable boost -
* if not, use cpufreq_boost_set_sw as default
*/
if (!cpufreq_driver->set_boost)
cpufreq_driver->set_boost = cpufreq_boost_set_sw;
ret = cpufreq_sysfs_create_file(&boost.attr);
if (ret)
pr_err("%s: cannot register global BOOST sysfs file\n",
__func__);
return ret;
}
static void remove_boost_sysfs_file(void)
{
if (cpufreq_boost_supported())
cpufreq_sysfs_remove_file(&boost.attr);
}
int cpufreq_enable_boost_support(void)
{
if (!cpufreq_driver)
return -EINVAL;
if (cpufreq_boost_supported())
return 0;
cpufreq_driver->boost_supported = true;
/* This will get removed on driver unregister */
return create_boost_sysfs_file();
}
EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
int cpufreq_boost_enabled(void)
{
return cpufreq_driver->boost_enabled;
@ -2465,21 +2508,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
if (driver_data->setpolicy)
driver_data->flags |= CPUFREQ_CONST_LOOPS;
if (cpufreq_boost_supported()) {
/*
* Check if driver provides function to enable boost -
* if not, use cpufreq_boost_set_sw as default
*/
if (!cpufreq_driver->set_boost)
cpufreq_driver->set_boost = cpufreq_boost_set_sw;
ret = cpufreq_sysfs_create_file(&boost.attr);
if (ret) {
pr_err("%s: cannot register global BOOST sysfs file\n",
__func__);
goto err_null_driver;
}
}
ret = create_boost_sysfs_file();
if (ret)
goto err_null_driver;
ret = subsys_interface_register(&cpufreq_interface);
if (ret)
@ -2503,8 +2534,7 @@ out:
err_if_unreg:
subsys_interface_unregister(&cpufreq_interface);
err_boost_unreg:
if (cpufreq_boost_supported())
cpufreq_sysfs_remove_file(&boost.attr);
remove_boost_sysfs_file();
err_null_driver:
write_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
@ -2533,9 +2563,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
/* Protect against concurrent cpu hotplug */
get_online_cpus();
subsys_interface_unregister(&cpufreq_interface);
if (cpufreq_boost_supported())
cpufreq_sysfs_remove_file(&boost.attr);
remove_boost_sysfs_file();
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
write_lock_irqsave(&cpufreq_driver_lock, flags);

View file

@ -75,6 +75,10 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
}
freq_table[i].driver_data = i;
freq_table[i].frequency = rate / 1000;
/* Is Boost/turbo opp ? */
if (dev_pm_opp_is_turbo(opp))
freq_table[i].flags = CPUFREQ_BOOST_FREQ;
}
freq_table[i].driver_data = i;

View file

@ -18,6 +18,21 @@
* FREQUENCY TABLE HELPERS *
*********************************************************************/
bool policy_has_boost_freq(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *pos, *table = policy->freq_table;
if (!table)
return false;
cpufreq_for_each_valid_entry(pos, table)
if (pos->flags & CPUFREQ_BOOST_FREQ)
return true;
return false;
}
EXPORT_SYMBOL_GPL(policy_has_boost_freq);
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{