Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: arm_big_little_dt: Instantiate as platform_driver cpufreq: arm_big_little_dt: Register driver only if DT has valid data cpufreq / e_powersaver: Fix linker error when ACPI processor is a module cpufreq / intel_pstate: Add additional supported CPU ID cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT
This commit is contained in:
commit
5a2bff8d7c
@ -272,7 +272,7 @@ config X86_LONGHAUL
|
|||||||
config X86_E_POWERSAVER
|
config X86_E_POWERSAVER
|
||||||
tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
|
tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
|
||||||
select CPU_FREQ_TABLE
|
select CPU_FREQ_TABLE
|
||||||
depends on X86_32
|
depends on X86_32 && ACPI_PROCESSOR
|
||||||
help
|
help
|
||||||
This adds the CPUFreq driver for VIA C7 processors. However, this driver
|
This adds the CPUFreq driver for VIA C7 processors. However, this driver
|
||||||
does not have any safeguards to prevent operating the CPU out of spec
|
does not have any safeguards to prevent operating the CPU out of spec
|
||||||
|
@ -19,70 +19,75 @@
|
|||||||
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/cpu.h>
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/opp.h>
|
#include <linux/opp.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include "arm_big_little.h"
|
#include "arm_big_little.h"
|
||||||
|
|
||||||
static int dt_init_opp_table(struct device *cpu_dev)
|
/* get cpu node with valid operating-points */
|
||||||
|
static struct device_node *get_cpu_node_with_valid_op(int cpu)
|
||||||
{
|
{
|
||||||
struct device_node *np, *parent;
|
struct device_node *np = NULL, *parent;
|
||||||
int count = 0, ret;
|
|
||||||
|
|
||||||
parent = of_find_node_by_path("/cpus");
|
|
||||||
if (!parent) {
|
|
||||||
pr_err("failed to find OF /cpus\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_each_child_of_node(parent, np) {
|
|
||||||
if (count++ != cpu_dev->id)
|
|
||||||
continue;
|
|
||||||
if (!of_get_property(np, "operating-points", NULL)) {
|
|
||||||
ret = -ENODATA;
|
|
||||||
} else {
|
|
||||||
cpu_dev->of_node = np;
|
|
||||||
ret = of_init_opp_table(cpu_dev);
|
|
||||||
}
|
|
||||||
of_node_put(np);
|
|
||||||
of_node_put(parent);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dt_get_transition_latency(struct device *cpu_dev)
|
|
||||||
{
|
|
||||||
struct device_node *np, *parent;
|
|
||||||
u32 transition_latency = CPUFREQ_ETERNAL;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
parent = of_find_node_by_path("/cpus");
|
parent = of_find_node_by_path("/cpus");
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
pr_info("Failed to find OF /cpus. Use CPUFREQ_ETERNAL transition latency\n");
|
pr_err("failed to find OF /cpus\n");
|
||||||
return CPUFREQ_ETERNAL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child_of_node(parent, np) {
|
for_each_child_of_node(parent, np) {
|
||||||
if (count++ != cpu_dev->id)
|
if (count++ != cpu)
|
||||||
continue;
|
continue;
|
||||||
|
if (!of_get_property(np, "operating-points", NULL)) {
|
||||||
|
of_node_put(np);
|
||||||
|
np = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
of_node_put(parent);
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dt_init_opp_table(struct device *cpu_dev)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
np = get_cpu_node_with_valid_op(cpu_dev->id);
|
||||||
|
if (!np)
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
|
cpu_dev->of_node = np;
|
||||||
|
ret = of_init_opp_table(cpu_dev);
|
||||||
|
of_node_put(np);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dt_get_transition_latency(struct device *cpu_dev)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
u32 transition_latency = CPUFREQ_ETERNAL;
|
||||||
|
|
||||||
|
np = get_cpu_node_with_valid_op(cpu_dev->id);
|
||||||
|
if (!np)
|
||||||
|
return CPUFREQ_ETERNAL;
|
||||||
|
|
||||||
of_property_read_u32(np, "clock-latency", &transition_latency);
|
of_property_read_u32(np, "clock-latency", &transition_latency);
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
of_node_put(parent);
|
|
||||||
|
|
||||||
|
pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
|
||||||
return transition_latency;
|
return transition_latency;
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
|
|
||||||
return CPUFREQ_ETERNAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_arm_bL_ops dt_bL_ops = {
|
static struct cpufreq_arm_bL_ops dt_bL_ops = {
|
||||||
@ -91,17 +96,33 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
|
|||||||
.init_opp_table = dt_init_opp_table,
|
.init_opp_table = dt_init_opp_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int generic_bL_init(void)
|
static int generic_bL_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
np = get_cpu_node_with_valid_op(0);
|
||||||
|
if (!np)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
of_node_put(np);
|
||||||
return bL_cpufreq_register(&dt_bL_ops);
|
return bL_cpufreq_register(&dt_bL_ops);
|
||||||
}
|
}
|
||||||
module_init(generic_bL_init);
|
|
||||||
|
|
||||||
static void generic_bL_exit(void)
|
static int generic_bL_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
return bL_cpufreq_unregister(&dt_bL_ops);
|
bL_cpufreq_unregister(&dt_bL_ops);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
module_exit(generic_bL_exit);
|
|
||||||
|
static struct platform_driver generic_bL_platdrv = {
|
||||||
|
.driver = {
|
||||||
|
.name = "arm-bL-cpufreq-dt",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = generic_bL_probe,
|
||||||
|
.remove = generic_bL_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(generic_bL_platdrv);
|
||||||
|
|
||||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
||||||
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
|
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
|
||||||
|
@ -1729,18 +1729,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
|
|||||||
/* end old governor */
|
/* end old governor */
|
||||||
if (data->governor) {
|
if (data->governor) {
|
||||||
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
|
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
|
||||||
|
unlock_policy_rwsem_write(policy->cpu);
|
||||||
__cpufreq_governor(data,
|
__cpufreq_governor(data,
|
||||||
CPUFREQ_GOV_POLICY_EXIT);
|
CPUFREQ_GOV_POLICY_EXIT);
|
||||||
|
lock_policy_rwsem_write(policy->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start new governor */
|
/* start new governor */
|
||||||
data->governor = policy->governor;
|
data->governor = policy->governor;
|
||||||
if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
|
if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
|
||||||
if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
|
if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
|
||||||
failed = 0;
|
failed = 0;
|
||||||
else
|
} else {
|
||||||
|
unlock_policy_rwsem_write(policy->cpu);
|
||||||
__cpufreq_governor(data,
|
__cpufreq_governor(data,
|
||||||
CPUFREQ_GOV_POLICY_EXIT);
|
CPUFREQ_GOV_POLICY_EXIT);
|
||||||
|
lock_policy_rwsem_write(policy->cpu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
|
@ -521,6 +521,7 @@ static void intel_pstate_timer_func(unsigned long __data)
|
|||||||
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
||||||
ICPU(0x2a, default_policy),
|
ICPU(0x2a, default_policy),
|
||||||
ICPU(0x2d, default_policy),
|
ICPU(0x2d, default_policy),
|
||||||
|
ICPU(0x3a, default_policy),
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
|
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
|
||||||
|
Loading…
Reference in New Issue
Block a user