Commit 5a2d853f authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-cpufreq'

* pm-cpufreq: (30 commits)
  intel_pstate: Set core to min P state during core offline
  cpufreq: Add stop CPU callback to cpufreq_driver interface
  cpufreq: Remove unnecessary braces
  cpufreq: Fix checkpatch errors and warnings
  cpufreq: powerpc: add cpufreq transition latency for FSL e500mc SoCs
  cpufreq: remove unused notifier: CPUFREQ_{SUSPENDCHANGE|RESUMECHANGE}
  cpufreq: Do not allow ->setpolicy drivers to provide ->target
  cpufreq: arm_big_little: set 'physical_cluster' for each CPU
  cpufreq: arm_big_little: make vexpress driver depend on bL core driver
  cpufreq: SPEAr: Instantiate as platform_driver
  cpufreq: Remove unnecessary variable/parameter 'frozen'
  cpufreq: Remove cpufreq_generic_exit()
  cpufreq: add 'freq_table' in struct cpufreq_policy
  cpufreq: Reformat printk() statements
  cpufreq: Tegra: Use cpufreq_generic_suspend()
  cpufreq: s5pv210: Use cpufreq_generic_suspend()
  cpufreq: exynos: Use cpufreq_generic_suspend()
  cpufreq: Implement cpufreq_generic_suspend()
  cpufreq: suspend governors on system suspend/hibernate
  cpufreq: move call to __find_governor() to cpufreq_init_policy()
  ...
parents f71a822f bb18008f
...@@ -92,7 +92,3 @@ values: ...@@ -92,7 +92,3 @@ values:
cpu - number of the affected CPU cpu - number of the affected CPU
old - old frequency old - old frequency
new - new frequency new - new frequency
If the cpufreq core detects the frequency has changed while the system
was suspended, these notifiers are called with CPUFREQ_RESUMECHANGE as
second argument.
...@@ -61,7 +61,13 @@ target_index - See below on the differences. ...@@ -61,7 +61,13 @@ target_index - See below on the differences.
And optionally And optionally
cpufreq_driver.exit - A pointer to a per-CPU cleanup function. cpufreq_driver.exit - A pointer to a per-CPU cleanup
function called during CPU_POST_DEAD
phase of cpu hotplug process.
cpufreq_driver.stop_cpu - A pointer to a per-CPU stop function
called during CPU_DOWN_PREPARE phase of
cpu hotplug process.
cpufreq_driver.resume - A pointer to a per-CPU resume function cpufreq_driver.resume - A pointer to a per-CPU resume function
which is called with interrupts disabled which is called with interrupts disabled
......
...@@ -674,8 +674,7 @@ static int cpufreq_callback(struct notifier_block *nb, ...@@ -674,8 +674,7 @@ static int cpufreq_callback(struct notifier_block *nb,
} }
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
loops_per_jiffy = cpufreq_scale(global_l_p_j_ref, loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
global_l_p_j_ref_freq, global_l_p_j_ref_freq,
freq->new); freq->new);
......
...@@ -166,7 +166,7 @@ static int twd_cpufreq_transition(struct notifier_block *nb, ...@@ -166,7 +166,7 @@ static int twd_cpufreq_transition(struct notifier_block *nb,
* frequency. The timer is local to a cpu, so cross-call to the * frequency. The timer is local to a cpu, so cross-call to the
* changing cpu. * changing cpu.
*/ */
if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) if (state == CPUFREQ_POSTCHANGE)
smp_call_function_single(freqs->cpu, twd_update_frequency, smp_call_function_single(freqs->cpu, twd_update_frequency,
NULL, 1); NULL, 1);
......
...@@ -885,9 +885,6 @@ static int viper_cpufreq_notifier(struct notifier_block *nb, ...@@ -885,9 +885,6 @@ static int viper_cpufreq_notifier(struct notifier_block *nb,
viper_set_core_cpu_voltage(freq->new, 0); viper_set_core_cpu_voltage(freq->new, 0);
} }
break; break;
case CPUFREQ_RESUMECHANGE:
viper_set_core_cpu_voltage(freq->new, 0);
break;
default: default:
/* ignore */ /* ignore */
break; break;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
static void __init spear1310_dt_init(void) static void __init spear1310_dt_init(void)
{ {
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
} }
static const char * const spear1310_dt_board_compat[] = { static const char * const spear1310_dt_board_compat[] = {
......
...@@ -143,6 +143,7 @@ static void __init spear1340_dt_init(void) ...@@ -143,6 +143,7 @@ static void __init spear1340_dt_init(void)
{ {
of_platform_populate(NULL, of_default_bus_match_table, of_platform_populate(NULL, of_default_bus_match_table,
spear1340_auxdata_lookup, NULL); spear1340_auxdata_lookup, NULL);
platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
} }
static const char * const spear1340_dt_board_compat[] = { static const char * const spear1340_dt_board_compat[] = {
......
...@@ -303,6 +303,14 @@ source "drivers/cpuidle/Kconfig" ...@@ -303,6 +303,14 @@ source "drivers/cpuidle/Kconfig"
endmenu endmenu
menu "Power management options"
source "kernel/power/Kconfig"
source "drivers/cpufreq/Kconfig"
endmenu
source "net/Kconfig" source "net/Kconfig"
source "drivers/Kconfig" source "drivers/Kconfig"
......
...@@ -1121,8 +1121,7 @@ oprof_cpufreq_notify(struct notifier_block *nb, unsigned long val, void *data) ...@@ -1121,8 +1121,7 @@ oprof_cpufreq_notify(struct notifier_block *nb, unsigned long val, void *data)
int ret = 0; int ret = 0;
struct cpufreq_freqs *frq = data; struct cpufreq_freqs *frq = data;
if ((val == CPUFREQ_PRECHANGE && frq->old < frq->new) || if ((val == CPUFREQ_PRECHANGE && frq->old < frq->new) ||
(val == CPUFREQ_POSTCHANGE && frq->old > frq->new) || (val == CPUFREQ_POSTCHANGE && frq->old > frq->new))
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE))
set_spu_profiling_frequency(frq->new, spu_cycle_reset); set_spu_profiling_frequency(frq->new, spu_cycle_reset);
return ret; return ret;
} }
......
...@@ -659,8 +659,7 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val ...@@ -659,8 +659,7 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
ft->clock_tick_ref = cpu_data(cpu).clock_tick; ft->clock_tick_ref = cpu_data(cpu).clock_tick;
} }
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
(val == CPUFREQ_RESUMECHANGE)) {
cpu_data(cpu).clock_tick = cpu_data(cpu).clock_tick =
cpufreq_scale(ft->clock_tick_ref, cpufreq_scale(ft->clock_tick_ref,
ft->ref_freq, ft->ref_freq,
......
...@@ -914,8 +914,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -914,8 +914,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
tsc_khz_ref = tsc_khz; tsc_khz_ref = tsc_khz;
} }
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
(val == CPUFREQ_RESUMECHANGE)) {
*lpj = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); *lpj = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
tsc_khz = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new); tsc_khz = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/async.h> #include <linux/async.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <trace/events/power.h> #include <trace/events/power.h>
#include <linux/cpufreq.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -866,6 +867,8 @@ void dpm_resume(pm_message_t state) ...@@ -866,6 +867,8 @@ void dpm_resume(pm_message_t state)
mutex_unlock(&dpm_list_mtx); mutex_unlock(&dpm_list_mtx);
async_synchronize_full(); async_synchronize_full();
dpm_show_time(starttime, state, NULL); dpm_show_time(starttime, state, NULL);
cpufreq_resume();
} }
/** /**
...@@ -1434,6 +1437,8 @@ int dpm_suspend(pm_message_t state) ...@@ -1434,6 +1437,8 @@ int dpm_suspend(pm_message_t state)
might_sleep(); might_sleep();
cpufreq_suspend();
mutex_lock(&dpm_list_mtx); mutex_lock(&dpm_list_mtx);
pm_transition = state; pm_transition = state;
async_error = 0; async_error = 0;
......
...@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86" ...@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86"
endmenu endmenu
menu "ARM CPU frequency scaling drivers" menu "ARM CPU frequency scaling drivers"
depends on ARM depends on ARM || ARM64
source "drivers/cpufreq/Kconfig.arm" source "drivers/cpufreq/Kconfig.arm"
endmenu endmenu
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# ARM CPU Frequency scaling drivers # ARM CPU Frequency scaling drivers
# #
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver" tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK
...@@ -16,6 +17,14 @@ config ARM_DT_BL_CPUFREQ ...@@ -16,6 +17,14 @@ config ARM_DT_BL_CPUFREQ
This enables probing via DT for Generic CPUfreq driver for ARM This enables probing via DT for Generic CPUfreq driver for ARM
big.LITTLE platform. This gets frequency tables from DT. big.LITTLE platform. This gets frequency tables from DT.
config ARM_VEXPRESS_SPC_CPUFREQ
tristate "Versatile Express SPC based CPUfreq driver"
depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
help
This add the CPUfreq driver support for Versatile Express
big.LITTLE platforms using SPC for power management.
config ARM_EXYNOS_CPUFREQ config ARM_EXYNOS_CPUFREQ
bool bool
...@@ -241,11 +250,3 @@ config ARM_TEGRA_CPUFREQ ...@@ -241,11 +250,3 @@ config ARM_TEGRA_CPUFREQ
default y default y
help help
This adds the CPUFreq driver support for TEGRA SOCs. This adds the CPUFreq driver support for TEGRA SOCs.
config ARM_VEXPRESS_SPC_CPUFREQ
tristate "Versatile Express SPC based CPUfreq driver"
select ARM_BIG_LITTLE_CPUFREQ
depends on ARCH_VEXPRESS_SPC
help
This add the CPUfreq driver support for Versatile Express
big.LITTLE platforms using SPC for power management.
...@@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
pr_debug("acpi_cpufreq_cpu_exit\n"); pr_debug("acpi_cpufreq_cpu_exit\n");
if (data) { if (data) {
cpufreq_frequency_table_put_attr(policy->cpu);
per_cpu(acfreq_data, policy->cpu) = NULL; per_cpu(acfreq_data, policy->cpu) = NULL;
acpi_processor_unregister_performance(data->acpi_data, acpi_processor_unregister_performance(data->acpi_data,
policy->cpu); policy->cpu);
......
...@@ -446,9 +446,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) ...@@ -446,9 +446,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
} }
if (cur_cluster < MAX_CLUSTERS) { if (cur_cluster < MAX_CLUSTERS) {
int cpu;
cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
per_cpu(physical_cluster, policy->cpu) = cur_cluster; for_each_cpu(cpu, policy->cpus)
per_cpu(physical_cluster, cpu) = cur_cluster;
} else { } else {
/* Assumption: during init, we are always running on A15 */ /* Assumption: during init, we are always running on A15 */
per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER; per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER;
...@@ -478,7 +481,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) ...@@ -478,7 +481,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
return -ENODEV; return -ENODEV;
} }
cpufreq_frequency_table_put_attr(policy->cpu);
put_cluster_clk_and_freq_table(cpu_dev); put_cluster_clk_and_freq_table(cpu_dev);
dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu); dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
......
...@@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = { ...@@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = {
.target_index = bfin_target, .target_index = bfin_target,
.get = bfin_getfreq_khz, .get = bfin_getfreq_khz,
.init = __bfin_cpu_init, .init = __bfin_cpu_init,
.exit = cpufreq_generic_exit,
.name = "bfin cpufreq", .name = "bfin cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = { ...@@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
.target_index = cpu0_set_target, .target_index = cpu0_set_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = cpu0_cpufreq_init, .init = cpu0_cpufreq_init,
.exit = cpufreq_generic_exit,
.name = "generic_cpu0", .name = "generic_cpu0",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/syscore_ops.h> #include <linux/suspend.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <trace/events/power.h> #include <trace/events/power.h>
...@@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock); ...@@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock);
DEFINE_MUTEX(cpufreq_governor_lock); DEFINE_MUTEX(cpufreq_governor_lock);
static LIST_HEAD(cpufreq_policy_list); static LIST_HEAD(cpufreq_policy_list);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */ /* This one keeps track of the previously set governor of a removed CPU */
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
#endif
/* Flag to suspend/resume CPUFreq governors */
static bool cpufreq_suspended;
static inline bool has_target(void) static inline bool has_target(void)
{ {
...@@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu) ...@@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
if (!policy || IS_ERR(policy->clk)) { if (!policy || IS_ERR(policy->clk)) {
pr_err("%s: No %s associated to cpu: %d\n", __func__, pr_err("%s: No %s associated to cpu: %d\n",
policy ? "clk" : "policy", cpu); __func__, policy ? "clk" : "policy", cpu);
return 0; return 0;
} }
...@@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu) ...@@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
} }
EXPORT_SYMBOL_GPL(cpufreq_generic_get); EXPORT_SYMBOL_GPL(cpufreq_generic_get);
/* Only for cpufreq core internal use */
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
{
return per_cpu(cpufreq_cpu_data, cpu);
}
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{ {
struct cpufreq_policy *policy = NULL; struct cpufreq_policy *policy = NULL;
...@@ -254,15 +261,14 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) ...@@ -254,15 +261,14 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
if (!l_p_j_ref_freq) { if (!l_p_j_ref_freq) {
l_p_j_ref = loops_per_jiffy; l_p_j_ref = loops_per_jiffy;
l_p_j_ref_freq = ci->old; l_p_j_ref_freq = ci->old;
pr_debug("saving %lu as reference value for loops_per_jiffy; " pr_debug("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n",
"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); l_p_j_ref, l_p_j_ref_freq);
} }
if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) || if (val == CPUFREQ_POSTCHANGE && ci->old != ci->new) {
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
ci->new); ci->new);
pr_debug("scaling loops_per_jiffy to %lu " pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n",
"for frequency %u kHz\n", loops_per_jiffy, ci->new); loops_per_jiffy, ci->new);
} }
} }
#else #else
...@@ -282,7 +288,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -282,7 +288,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
freqs->flags = cpufreq_driver->flags; freqs->flags = cpufreq_driver->flags;
pr_debug("notification %u of frequency transition to %u kHz\n", pr_debug("notification %u of frequency transition to %u kHz\n",
state, freqs->new); state, freqs->new);
switch (state) { switch (state) {
...@@ -294,9 +300,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -294,9 +300,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((policy) && (policy->cpu == freqs->cpu) && if ((policy) && (policy->cpu == freqs->cpu) &&
(policy->cur) && (policy->cur != freqs->old)) { (policy->cur) && (policy->cur != freqs->old)) {
pr_debug("Warning: CPU frequency is" pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
" %u, cpufreq assumed %u kHz.\n", freqs->old, policy->cur);
freqs->old, policy->cur);
freqs->old = policy->cur; freqs->old = policy->cur;
} }
} }
...@@ -307,8 +312,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -307,8 +312,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, pr_debug("FREQ: %lu - CPU: %lu\n",
(unsigned long)freqs->cpu); (unsigned long)freqs->new, (unsigned long)freqs->cpu);
trace_cpu_frequency(freqs->new, freqs->cpu); trace_cpu_frequency(freqs->new, freqs->cpu);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list, srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs); CPUFREQ_POSTCHANGE, freqs);
...@@ -352,7 +357,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); ...@@ -352,7 +357,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
/********************************************************************* /*********************************************************************
* SYSFS INTERFACE * * SYSFS INTERFACE *
*********************************************************************/ *********************************************************************/
ssize_t show_boost(struct kobject *kobj, static ssize_t show_boost(struct kobject *kobj,
struct attribute *attr, char *buf) struct attribute *attr, char *buf)
{ {
return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
...@@ -368,13 +373,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, ...@@ -368,13 +373,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
return -EINVAL; return -EINVAL;
if (cpufreq_boost_trigger_state(enable)) { if (cpufreq_boost_trigger_state(enable)) {
pr_err("%s: Cannot %s BOOST!\n", __func__, pr_err("%s: Cannot %s BOOST!\n",
enable ? "enable" : "disable"); __func__, enable ? "enable" : "disable");
return -EINVAL; return -EINVAL;
} }
pr_debug("%s: cpufreq BOOST %s\n", __func__, pr_debug("%s: cpufreq BOOST %s\n",
enable ? "enabled" : "disabled"); __func__, enable ? "enabled" : "disabled");
return count; return count;
} }
...@@ -879,18 +884,25 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, ...@@ -879,18 +884,25 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
static void cpufreq_init_policy(struct cpufreq_policy *policy) static void cpufreq_init_policy(struct cpufreq_policy *policy)
{ {
struct cpufreq_governor *gov = NULL;
struct cpufreq_policy new_policy; struct cpufreq_policy new_policy;
int ret = 0; int ret = 0;
memcpy(&new_policy, policy, sizeof(*policy)); memcpy(&new_policy, policy, sizeof(*policy));
/* Update governor of new_policy to the governor used before hotplug */
gov = __find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu));
if (gov)
pr_debug("Restoring governor %s for cpu %d\n",
policy->governor->name, policy->cpu);
else
gov = CPUFREQ_DEFAULT_GOVERNOR;
new_policy.governor = gov;
/* Use the default policy if its valid. */ /* Use the default policy if its valid. */
if (cpufreq_driver->setpolicy) if (cpufreq_driver->setpolicy)
cpufreq_parse_governor(policy->governor->name, cpufreq_parse_governor(gov->name, &new_policy.policy, NULL);
&new_policy.policy, NULL);
/* assure that the starting sequence is run in cpufreq_set_policy */
policy->governor = NULL;
/* set default policy */ /* set default policy */
ret = cpufreq_set_policy(policy, &new_policy); ret = cpufreq_set_policy(policy, &new_policy);
...@@ -927,8 +939,11 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, ...@@ -927,8 +939,11 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
up_write(&policy->rwsem); up_write(&policy->rwsem);
if (has_target()) { if (has_target()) {
if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { if (!ret)
ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
if (ret) {
pr_err("%s: Failed to start governor\n", __func__); pr_err("%s: Failed to start governor\n", __func__);
return ret; return ret;
} }
...@@ -949,6 +964,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) ...@@ -949,6 +964,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
read_unlock_irqrestore(&cpufreq_driver_lock, flags); read_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL;
return policy; return policy;
} }
...@@ -1022,21 +1039,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) ...@@ -1022,21 +1039,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
up_write(&policy->rwsem); up_write(&policy->rwsem);
cpufreq_frequency_table_update_policy_cpu(policy);
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_UPDATE_POLICY_CPU, policy); CPUFREQ_UPDATE_POLICY_CPU, policy);
} }
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int j, cpu = dev->id; unsigned int j, cpu = dev->id;
int ret = -ENOMEM; int ret = -ENOMEM;
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
unsigned long flags; unsigned long flags;
bool recover_policy = cpufreq_suspended;
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
struct cpufreq_policy *tpolicy; struct cpufreq_policy *tpolicy;
struct cpufreq_governor *gov;
#endif #endif
if (cpu_is_offline(cpu)) if (cpu_is_offline(cpu))
...@@ -1075,9 +1090,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1075,9 +1090,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
* Restore the saved policy when doing light-weight init and fall back * Restore the saved policy when doing light-weight init and fall back
* to the full init if that fails. * to the full init if that fails.
*/ */
policy = frozen ? cpufreq_policy_restore(cpu) : NULL; policy = recover_policy ? cpufreq_policy_restore(cpu) : NULL;
if (!policy) { if (!policy) {
frozen = false; recover_policy = false;
policy = cpufreq_policy_alloc(); policy = cpufreq_policy_alloc();
if (!policy) if (!policy)
goto nomem_out; goto nomem_out;
...@@ -1089,12 +1104,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1089,12 +1104,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
* the creation of a brand new one. So we need to perform this update * the creation of a brand new one. So we need to perform this update
* by invoking update_policy_cpu(). * by invoking update_policy_cpu().
*/ */
if (frozen && cpu != policy->cpu) if (recover_policy && cpu != policy->cpu)
update_policy_cpu(policy, cpu); update_policy_cpu(policy, cpu);
else else
policy->cpu = cpu; policy->cpu = cpu;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
cpumask_copy(policy->cpus, cpumask_of(cpu)); cpumask_copy(policy->cpus, cpumask_of(cpu));
init_completion(&policy->kobj_unregister); init_completion(&policy->kobj_unregister);
...@@ -1118,7 +1132,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1118,7 +1132,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
*/ */
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
if (!frozen) { if (!recover_policy) {
policy->user_policy.min = policy->min; policy->user_policy.min = policy->min;
policy->user_policy.max = policy->max; policy->user_policy.max = policy->max;
} }
...@@ -1180,16 +1194,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1180,16 +1194,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy); CPUFREQ_START, policy);
#ifdef CONFIG_HOTPLUG_CPU if (!recover_policy) {
gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
if (gov) {
policy->governor = gov;
pr_debug("Restoring governor %s for cpu %d\n",
policy->governor->name, cpu);
}
#endif
if (!frozen) {
ret = cpufreq_add_dev_interface(policy, dev); ret = cpufreq_add_dev_interface(policy, dev);
if (ret) if (ret)
goto err_out_unregister; goto err_out_unregister;
...@@ -1203,7 +1208,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1203,7 +1208,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
cpufreq_init_policy(policy); cpufreq_init_policy(policy);
if (!frozen) { if (!recover_policy) {
policy->user_policy.policy = policy->policy; policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor; policy->user_policy.governor = policy->governor;
} }
...@@ -1226,7 +1231,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1226,7 +1231,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
if (cpufreq_driver->exit) if (cpufreq_driver->exit)
cpufreq_driver->exit(policy); cpufreq_driver->exit(policy);
err_set_policy_cpu: err_set_policy_cpu:
if (frozen) { if (recover_policy) {
/* Do not leave stale fallback data behind. */ /* Do not leave stale fallback data behind. */
per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL; per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
cpufreq_policy_put_kobj(policy); cpufreq_policy_put_kobj(policy);
...@@ -1250,7 +1255,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1250,7 +1255,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
*/ */
static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
{ {
return __cpufreq_add_dev(dev, sif, false); return __cpufreq_add_dev(dev, sif);
} }
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
...@@ -1265,7 +1270,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, ...@@ -1265,7 +1270,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
ret = kobject_move(&policy->kobj, &cpu_dev->kobj); ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
if (ret) { if (ret) {
pr_err("%s: Failed to move kobj: %d", __func__, ret); pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
down_write(&policy->rwsem); down_write(&policy->rwsem);
cpumask_set_cpu(old_cpu, policy->cpus); cpumask_set_cpu(old_cpu, policy->cpus);
...@@ -1281,8 +1286,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, ...@@ -1281,8 +1286,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
} }
static int __cpufreq_remove_dev_prepare(struct device *dev, static int __cpufreq_remove_dev_prepare(struct device *dev,
struct subsys_interface *sif, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int cpu = dev->id, cpus; unsigned int cpu = dev->id, cpus;
int new_cpu, ret; int new_cpu, ret;
...@@ -1296,7 +1300,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1296,7 +1300,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
policy = per_cpu(cpufreq_cpu_data, cpu); policy = per_cpu(cpufreq_cpu_data, cpu);
/* Save the policy somewhere when doing a light-weight tear-down */ /* Save the policy somewhere when doing a light-weight tear-down */
if (frozen) if (cpufreq_suspended)
per_cpu(cpufreq_cpu_data_fallback, cpu) = policy; per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
...@@ -1314,11 +1318,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1314,11 +1318,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
} }
} }
#ifdef CONFIG_HOTPLUG_CPU
if (!cpufreq_driver->setpolicy) if (!cpufreq_driver->setpolicy)
strncpy(per_cpu(cpufreq_cpu_governor, cpu), strncpy(per_cpu(cpufreq_cpu_governor, cpu),
policy->governor->name, CPUFREQ_NAME_LEN); policy->governor->name, CPUFREQ_NAME_LEN);
#endif
down_read(&policy->rwsem); down_read(&policy->rwsem);
cpus = cpumask_weight(policy->cpus); cpus = cpumask_weight(policy->cpus);
...@@ -1331,19 +1333,19 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1331,19 +1333,19 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
if (new_cpu >= 0) { if (new_cpu >= 0) {
update_policy_cpu(policy, new_cpu); update_policy_cpu(policy, new_cpu);
if (!frozen) { if (!cpufreq_suspended)
pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
__func__, new_cpu, cpu); __func__, new_cpu, cpu);
}
} }
} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
cpufreq_driver->stop_cpu(policy);
} }
return 0; return 0;
} }
static int __cpufreq_remove_dev_finish(struct device *dev, static int __cpufreq_remove_dev_finish(struct device *dev,
struct subsys_interface *sif, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int cpu = dev->id, cpus; unsigned int cpu = dev->id, cpus;
int ret; int ret;
...@@ -1373,12 +1375,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev, ...@@ -1373,12 +1375,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
CPUFREQ_GOV_POLICY_EXIT); CPUFREQ_GOV_POLICY_EXIT);
if (ret) { if (ret) {
pr_err("%s: Failed to exit governor\n", pr_err("%s: Failed to exit governor\n",
__func__); __func__);
return ret; return ret;
} }
} }
if (!frozen) if (!cpufreq_suspended)
cpufreq_policy_put_kobj(policy); cpufreq_policy_put_kobj(policy);
/* /*
...@@ -1394,16 +1396,16 @@ static int __cpufreq_remove_dev_finish(struct device *dev, ...@@ -1394,16 +1396,16 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
list_del(&policy->policy_list); list_del(&policy->policy_list);
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (!frozen) if (!cpufreq_suspended)
cpufreq_policy_free(policy); cpufreq_policy_free(policy);
} else { } else if (has_target()) {
if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || if (!ret)
(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
pr_err("%s: Failed to start governor\n",
__func__); if (ret) {
return ret; pr_err("%s: Failed to start governor\n", __func__);
} return ret;
} }
} }
...@@ -1424,10 +1426,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) ...@@ -1424,10 +1426,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
if (cpu_is_offline(cpu)) if (cpu_is_offline(cpu))
return 0; return 0;
ret = __cpufreq_remove_dev_prepare(dev, sif, false); ret = __cpufreq_remove_dev_prepare(dev, sif);
if (!ret) if (!ret)
ret = __cpufreq_remove_dev_finish(dev, sif, false); ret = __cpufreq_remove_dev_finish(dev, sif);
return ret; return ret;
} }
...@@ -1458,8 +1460,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, ...@@ -1458,8 +1460,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
unsigned long flags; unsigned long flags;
pr_debug("Warning: CPU frequency out of sync: cpufreq and timing " pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n",
"core thinks of %u, is %u kHz.\n", old_freq, new_freq); old_freq, new_freq);
freqs.old = old_freq; freqs.old = old_freq;
freqs.new = new_freq; freqs.new = new_freq;
...@@ -1570,83 +1572,104 @@ static struct subsys_interface cpufreq_interface = { ...@@ -1570,83 +1572,104 @@ static struct subsys_interface cpufreq_interface = {
.remove_dev = cpufreq_remove_dev, .remove_dev = cpufreq_remove_dev,
}; };
/*
* In case platform wants some specific frequency to be configured
* during suspend..
*/
int cpufreq_generic_suspend(struct cpufreq_policy *policy)
{
int ret;
if (!policy->suspend_freq) {
pr_err("%s: suspend_freq can't be zero\n", __func__);
return -EINVAL;
}
pr_debug("%s: Setting suspend-freq: %u\n", __func__,
policy->suspend_freq);
ret = __cpufreq_driver_target(policy, policy->suspend_freq,
CPUFREQ_RELATION_H);
if (ret)
pr_err("%s: unable to set suspend-freq: %u. err: %d\n",
__func__, policy->suspend_freq, ret);
return ret;
}
EXPORT_SYMBOL(cpufreq_generic_suspend);
/** /**
* cpufreq_bp_suspend - Prepare the boot CPU for system suspend. * cpufreq_suspend() - Suspend CPUFreq governors
* *
* This function is only executed for the boot processor. The other CPUs * Called during system wide Suspend/Hibernate cycles for suspending governors
* have been put offline by means of CPU hotplug. * as some platforms can't change frequency after this point in suspend cycle.
* Because some of the devices (like: i2c, regulators, etc) they use for
* changing frequency are suspended quickly after this point.
*/ */
static int cpufreq_bp_suspend(void) void cpufreq_suspend(void)
{ {
int ret = 0;
int cpu = smp_processor_id();
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
pr_debug("suspending cpu %u\n", cpu); if (!cpufreq_driver)
return;
/* If there's no policy for the boot CPU, we have nothing to do. */ if (!has_target())
policy = cpufreq_cpu_get(cpu); return;
if (!policy)
return 0;
if (cpufreq_driver->suspend) { pr_debug("%s: Suspending Governors\n", __func__);
ret = cpufreq_driver->suspend(policy);
if (ret) list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
printk(KERN_ERR "cpufreq: suspend failed in ->suspend " if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
"step on CPU %u\n", policy->cpu); pr_err("%s: Failed to stop governor for policy: %p\n",
__func__, policy);
else if (cpufreq_driver->suspend
&& cpufreq_driver->suspend(policy))
pr_err("%s: Failed to suspend driver: %p\n", __func__,
policy);
} }
cpufreq_cpu_put(policy); cpufreq_suspended = true;
return ret;
} }
/** /**
* cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. * cpufreq_resume() - Resume CPUFreq governors
* *
* 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) * Called during system wide Suspend/Hibernate cycle for resuming governors that
* 2.) schedule call cpufreq_update_policy() ASAP as interrupts are * are suspended with cpufreq_suspend().
* restored. It will verify that the current freq is in sync with
* what we believe it to be. This is a bit later than when it
* should be, but nonethteless it's better than calling
* cpufreq_driver->get() here which might re-enable interrupts...
*
* This function is only executed for the boot CPU. The other CPUs have not
* been turned on yet.
*/ */
static void cpufreq_bp_resume(void) void cpufreq_resume(void)
{ {
int ret = 0;
int cpu = smp_processor_id();
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
pr_debug("resuming cpu %u\n", cpu); if (!cpufreq_driver)
return;
/* If there's no policy for the boot CPU, we have nothing to do. */ if (!has_target())
policy = cpufreq_cpu_get(cpu);
if (!policy)
return; return;
if (cpufreq_driver->resume) { pr_debug("%s: Resuming Governors\n", __func__);
ret = cpufreq_driver->resume(policy);
if (ret) {
printk(KERN_ERR "cpufreq: resume failed in ->resume "
"step on CPU %u\n", policy->cpu);
goto fail;
}
}
schedule_work(&policy->update); cpufreq_suspended = false;
fail: list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
cpufreq_cpu_put(policy); if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
} || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
pr_err("%s: Failed to start governor for policy: %p\n",
__func__, policy);
else if (cpufreq_driver->resume
&& cpufreq_driver->resume(policy))
pr_err("%s: Failed to resume driver: %p\n", __func__,
policy);
static struct syscore_ops cpufreq_syscore_ops = { /*
.suspend = cpufreq_bp_suspend, * schedule call cpufreq_update_policy() for boot CPU, i.e. last
.resume = cpufreq_bp_resume, * policy in list. It will verify that the current freq is in
}; * sync with what we believe it to be.
*/
if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
schedule_work(&policy->update);
}
}
/** /**
* cpufreq_get_current_driver - return current driver's name * cpufreq_get_current_driver - return current driver's name
...@@ -1762,7 +1785,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1762,7 +1785,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
target_freq = policy->min; target_freq = policy->min;
pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
policy->cpu, target_freq, relation, old_target_freq); policy->cpu, target_freq, relation, old_target_freq);
/* /*
* This might look like a redundant call as we are checking it again * This might look like a redundant call as we are checking it again
...@@ -1807,8 +1830,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1807,8 +1830,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
freqs.flags = 0; freqs.flags = 0;
pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
__func__, policy->cpu, freqs.old, __func__, policy->cpu, freqs.old, freqs.new);
freqs.new);
cpufreq_notify_transition(policy, &freqs, cpufreq_notify_transition(policy, &freqs,
CPUFREQ_PRECHANGE); CPUFREQ_PRECHANGE);
...@@ -1817,7 +1839,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1817,7 +1839,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
retval = cpufreq_driver->target_index(policy, index); retval = cpufreq_driver->target_index(policy, index);
if (retval) if (retval)
pr_err("%s: Failed to change cpu frequency: %d\n", pr_err("%s: Failed to change cpu frequency: %d\n",
__func__, retval); __func__, retval);
if (notify) if (notify)
cpufreq_notify_post_transition(policy, &freqs, retval); cpufreq_notify_post_transition(policy, &freqs, retval);
...@@ -1863,17 +1885,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, ...@@ -1863,17 +1885,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
struct cpufreq_governor *gov = NULL; struct cpufreq_governor *gov = NULL;
#endif #endif
/* Don't start any governor operations if we are entering suspend */
if (cpufreq_suspended)
return 0;
if (policy->governor->max_transition_latency && if (policy->governor->max_transition_latency &&
policy->cpuinfo.transition_latency > policy->cpuinfo.transition_latency >
policy->governor->max_transition_latency) { policy->governor->max_transition_latency) {
if (!gov) if (!gov)
return -EINVAL; return -EINVAL;
else { else {
printk(KERN_WARNING "%s governor failed, too long" pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
" transition latency of HW, fallback" policy->governor->name, gov->name);
" to %s governor\n",
policy->governor->name,
gov->name);
policy->governor = gov; policy->governor = gov;
} }
} }
...@@ -1883,7 +1906,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, ...@@ -1883,7 +1906,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
return -EINVAL; return -EINVAL;
pr_debug("__cpufreq_governor for CPU %u, event %u\n", pr_debug("__cpufreq_governor for CPU %u, event %u\n",
policy->cpu, event); policy->cpu, event);
mutex_lock(&cpufreq_governor_lock); mutex_lock(&cpufreq_governor_lock);
if ((policy->governor_enabled && event == CPUFREQ_GOV_START) if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
...@@ -1950,9 +1973,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor); ...@@ -1950,9 +1973,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor) void cpufreq_unregister_governor(struct cpufreq_governor *governor)
{ {
#ifdef CONFIG_HOTPLUG_CPU
int cpu; int cpu;
#endif
if (!governor) if (!governor)
return; return;
...@@ -1960,14 +1981,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor) ...@@ -1960,14 +1981,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
if (cpufreq_disabled()) if (cpufreq_disabled())
return; return;
#ifdef CONFIG_HOTPLUG_CPU
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
if (cpu_online(cpu)) if (cpu_online(cpu))
continue; continue;
if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name)) if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0"); strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
} }
#endif
mutex_lock(&cpufreq_governor_mutex); mutex_lock(&cpufreq_governor_mutex);
list_del(&governor->governor_list); list_del(&governor->governor_list);
...@@ -2012,22 +2031,21 @@ EXPORT_SYMBOL(cpufreq_get_policy); ...@@ -2012,22 +2031,21 @@ EXPORT_SYMBOL(cpufreq_get_policy);
static int cpufreq_set_policy(struct cpufreq_policy *policy, static int cpufreq_set_policy(struct cpufreq_policy *policy,
struct cpufreq_policy *new_policy) struct cpufreq_policy *new_policy)
{ {
int ret = 0, failed = 1; struct cpufreq_governor *old_gov;
int ret;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
new_policy->min, new_policy->max); new_policy->cpu, new_policy->min, new_policy->max);
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
if (new_policy->min > policy->max || new_policy->max < policy->min) { if (new_policy->min > policy->max || new_policy->max < policy->min)
ret = -EINVAL; return -EINVAL;
goto error_out;
}
/* verify the cpu speed can be set within this limit */ /* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(new_policy); ret = cpufreq_driver->verify(new_policy);
if (ret) if (ret)
goto error_out; return ret;
/* adjust if necessary - all reasons */ /* adjust if necessary - all reasons */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
...@@ -2043,7 +2061,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2043,7 +2061,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
*/ */
ret = cpufreq_driver->verify(new_policy); ret = cpufreq_driver->verify(new_policy);
if (ret) if (ret)
goto error_out; return ret;
/* notification of the new policy */ /* notification of the new policy */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
...@@ -2053,63 +2071,53 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2053,63 +2071,53 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
policy->max = new_policy->max; policy->max = new_policy->max;
pr_debug("new min and max freqs are %u - %u kHz\n", pr_debug("new min and max freqs are %u - %u kHz\n",
policy->min, policy->max); policy->min, policy->max);
if (cpufreq_driver->setpolicy) { if (cpufreq_driver->setpolicy) {
policy->policy = new_policy->policy; policy->policy = new_policy->policy;
pr_debug("setting range\n"); pr_debug("setting range\n");
ret = cpufreq_driver->setpolicy(new_policy); return cpufreq_driver->setpolicy(new_policy);
} else { }
if (new_policy->governor != policy->governor) {
/* save old, working values */
struct cpufreq_governor *old_gov = policy->governor;
pr_debug("governor switch\n");
/* end old governor */
if (policy->governor) {
__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
up_write(&policy->rwsem);
__cpufreq_governor(policy,
CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem);
}
/* start new governor */ if (new_policy->governor == policy->governor)
policy->governor = new_policy->governor; goto out;
if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
failed = 0;
} else {
up_write(&policy->rwsem);
__cpufreq_governor(policy,
CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem);
}
}
if (failed) { pr_debug("governor switch\n");
/* new governor failed, so re-start old one */
pr_debug("starting governor %s failed\n", /* save old, working values */
policy->governor->name); old_gov = policy->governor;
if (old_gov) { /* end old governor */
policy->governor = old_gov; if (old_gov) {
__cpufreq_governor(policy, __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
CPUFREQ_GOV_POLICY_INIT); up_write(&policy->rwsem);
__cpufreq_governor(policy, __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
CPUFREQ_GOV_START); down_write(&policy->rwsem);
}
ret = -EINVAL;
goto error_out;
}
/* might be a policy change, too, so fall through */
}
pr_debug("governor: change or update limits\n");
ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
} }
error_out: /* start new governor */
return ret; policy->governor = new_policy->governor;
if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
if (!__cpufreq_governor(policy, CPUFREQ_GOV_START))
goto out;
up_write(&policy->rwsem);
__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem);
}
/* new governor failed, so re-start old one */
pr_debug("starting governor %s failed\n", policy->governor->name);
if (old_gov) {
policy->governor = old_gov;
__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
__cpufreq_governor(policy, CPUFREQ_GOV_START);
}
return -EINVAL;
out:
pr_debug("governor: change or update limits\n");
return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
} }
/** /**
...@@ -2145,8 +2153,13 @@ int cpufreq_update_policy(unsigned int cpu) ...@@ -2145,8 +2153,13 @@ int cpufreq_update_policy(unsigned int cpu)
*/ */
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
new_policy.cur = cpufreq_driver->get(cpu); new_policy.cur = cpufreq_driver->get(cpu);
if (WARN_ON(!new_policy.cur)) {
ret = -EIO;
goto no_policy;
}
if (!policy->cur) { if (!policy->cur) {
pr_debug("Driver did not initialize current freq"); pr_debug("Driver did not initialize current freq\n");
policy->cur = new_policy.cur; policy->cur = new_policy.cur;
} else { } else {
if (policy->cur != new_policy.cur && has_target()) if (policy->cur != new_policy.cur && has_target())
...@@ -2170,30 +2183,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, ...@@ -2170,30 +2183,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
{ {
unsigned int cpu = (unsigned long)hcpu; unsigned int cpu = (unsigned long)hcpu;
struct device *dev; struct device *dev;
bool frozen = false;
dev = get_cpu_device(cpu); dev = get_cpu_device(cpu);
if (dev) { if (dev) {
if (action & CPU_TASKS_FROZEN)
frozen = true;
switch (action & ~CPU_TASKS_FROZEN) { switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE: case CPU_ONLINE:
__cpufreq_add_dev(dev, NULL, frozen); __cpufreq_add_dev(dev, NULL);
cpufreq_update_policy(cpu);
break; break;
case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE:
__cpufreq_remove_dev_prepare(dev, NULL, frozen); __cpufreq_remove_dev_prepare(dev, NULL);
break; break;
case CPU_POST_DEAD: case CPU_POST_DEAD:
__cpufreq_remove_dev_finish(dev, NULL, frozen); __cpufreq_remove_dev_finish(dev, NULL);
break; break;
case CPU_DOWN_FAILED: case CPU_DOWN_FAILED:
__cpufreq_add_dev(dev, NULL, frozen); __cpufreq_add_dev(dev, NULL);
break; break;
} }
} }
...@@ -2249,8 +2256,8 @@ int cpufreq_boost_trigger_state(int state) ...@@ -2249,8 +2256,8 @@ int cpufreq_boost_trigger_state(int state)
cpufreq_driver->boost_enabled = !state; cpufreq_driver->boost_enabled = !state;
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
pr_err("%s: Cannot %s BOOST\n", __func__, pr_err("%s: Cannot %s BOOST\n",
state ? "enable" : "disable"); __func__, state ? "enable" : "disable");
} }
return ret; return ret;
...@@ -2295,7 +2302,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ...@@ -2295,7 +2302,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
if (!driver_data || !driver_data->verify || !driver_data->init || if (!driver_data || !driver_data->verify || !driver_data->init ||
!(driver_data->setpolicy || driver_data->target_index || !(driver_data->setpolicy || driver_data->target_index ||
driver_data->target)) driver_data->target) ||
(driver_data->setpolicy && (driver_data->target_index ||
driver_data->target)))
return -EINVAL; return -EINVAL;
pr_debug("trying to register driver %s\n", driver_data->name); pr_debug("trying to register driver %s\n", driver_data->name);
...@@ -2322,7 +2331,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ...@@ -2322,7 +2331,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
ret = cpufreq_sysfs_create_file(&boost.attr); ret = cpufreq_sysfs_create_file(&boost.attr);
if (ret) { if (ret) {
pr_err("%s: cannot register global BOOST sysfs file\n", pr_err("%s: cannot register global BOOST sysfs file\n",
__func__); __func__);
goto err_null_driver; goto err_null_driver;
} }
} }
...@@ -2345,7 +2354,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ...@@ -2345,7 +2354,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
/* if all ->init() calls failed, unregister */ /* if all ->init() calls failed, unregister */
if (ret) { if (ret) {
pr_debug("no CPU initialized for driver %s\n", pr_debug("no CPU initialized for driver %s\n",
driver_data->name); driver_data->name);
goto err_if_unreg; goto err_if_unreg;
} }
} }
...@@ -2409,7 +2418,6 @@ static int __init cpufreq_core_init(void) ...@@ -2409,7 +2418,6 @@ static int __init cpufreq_core_init(void)
cpufreq_global_kobject = kobject_create(); cpufreq_global_kobject = kobject_create();
BUG_ON(!cpufreq_global_kobject); BUG_ON(!cpufreq_global_kobject);
register_syscore_ops(&cpufreq_syscore_ops);
return 0; return 0;
} }
......
...@@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu) ...@@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu)
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
} }
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
struct cpufreq_frequency_table *table)
{ {
unsigned int i, j, count = 0, ret = 0; unsigned int i, j, count = 0, ret = 0;
struct cpufreq_stats *stat; struct cpufreq_stats *stat;
struct cpufreq_policy *current_policy;
unsigned int alloc_size; unsigned int alloc_size;
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct cpufreq_frequency_table *table;
table = cpufreq_frequency_get_table(cpu);
if (unlikely(!table))
return 0;
if (per_cpu(cpufreq_stats_table, cpu)) if (per_cpu(cpufreq_stats_table, cpu))
return -EBUSY; return -EBUSY;
stat = kzalloc(sizeof(*stat), GFP_KERNEL); stat = kzalloc(sizeof(*stat), GFP_KERNEL);
if ((stat) == NULL) if ((stat) == NULL)
return -ENOMEM; return -ENOMEM;
current_policy = cpufreq_cpu_get(cpu); ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
if (current_policy == NULL) {
ret = -EINVAL;
goto error_get_fail;
}
ret = sysfs_create_group(&current_policy->kobj, &stats_attr_group);
if (ret) if (ret)
goto error_out; goto error_out;
...@@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
if (!stat->time_in_state) { if (!stat->time_in_state) {
ret = -ENOMEM; ret = -ENOMEM;
goto error_out; goto error_alloc;
} }
stat->freq_table = (unsigned int *)(stat->time_in_state + count); stat->freq_table = (unsigned int *)(stat->time_in_state + count);
...@@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
stat->last_time = get_jiffies_64(); stat->last_time = get_jiffies_64();
stat->last_index = freq_table_get_index(stat, policy->cur); stat->last_index = freq_table_get_index(stat, policy->cur);
spin_unlock(&cpufreq_stats_lock); spin_unlock(&cpufreq_stats_lock);
cpufreq_cpu_put(current_policy);
return 0; return 0;
error_alloc:
sysfs_remove_group(&policy->kobj, &stats_attr_group);
error_out: error_out:
cpufreq_cpu_put(current_policy);
error_get_fail:
kfree(stat); kfree(stat);
per_cpu(cpufreq_stats_table, cpu) = NULL; per_cpu(cpufreq_stats_table, cpu) = NULL;
return ret; return ret;
...@@ -256,7 +253,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -256,7 +253,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
static void cpufreq_stats_create_table(unsigned int cpu) static void cpufreq_stats_create_table(unsigned int cpu)
{ {
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
struct cpufreq_frequency_table *table;
/* /*
* "likely(!policy)" because normally cpufreq_stats will be registered * "likely(!policy)" because normally cpufreq_stats will be registered
...@@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu) ...@@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu)
if (likely(!policy)) if (likely(!policy))
return; return;
table = cpufreq_frequency_get_table(policy->cpu); __cpufreq_stats_create_table(policy);
if (likely(table))
__cpufreq_stats_create_table(policy, table);
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
} }
...@@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, ...@@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
{ {
int ret = 0; int ret = 0;
struct cpufreq_policy *policy = data; struct cpufreq_policy *policy = data;
struct cpufreq_frequency_table *table;
unsigned int cpu = policy->cpu;
if (val == CPUFREQ_UPDATE_POLICY_CPU) { if (val == CPUFREQ_UPDATE_POLICY_CPU) {
cpufreq_stats_update_policy_cpu(policy); cpufreq_stats_update_policy_cpu(policy);
return 0; return 0;
} }
table = cpufreq_frequency_get_table(cpu);
if (!table)
return 0;
if (val == CPUFREQ_CREATE_POLICY) if (val == CPUFREQ_CREATE_POLICY)
ret = __cpufreq_stats_create_table(policy, table); ret = __cpufreq_stats_create_table(policy);
else if (val == CPUFREQ_REMOVE_POLICY) else if (val == CPUFREQ_REMOVE_POLICY)
__cpufreq_stats_free_table(policy); __cpufreq_stats_free_table(policy);
......
...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { ...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cris_freq_target, .target_index = cris_freq_target,
.init = cris_freq_cpu_init, .init = cris_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cris_freq", .name = "cris_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { ...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cris_freq_target, .target_index = cris_freq_target,
.init = cris_freq_cpu_init, .init = cris_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cris_freq", .name = "cris_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = { ...@@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = {
.target_index = davinci_target, .target_index = davinci_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = davinci_cpu_init, .init = davinci_cpu_init,
.exit = cpufreq_generic_exit,
.name = "davinci", .name = "davinci",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy) ...@@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
/* Bye */ /* Bye */
cpufreq_frequency_table_put_attr(policy->cpu);
kfree(eps_cpu[cpu]); kfree(eps_cpu[cpu]);
eps_cpu[cpu] = NULL; eps_cpu[cpu] = NULL;
return 0; return 0;
......
...@@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = { ...@@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = elanfreq_target, .target_index = elanfreq_target,
.init = elanfreq_cpu_init, .init = elanfreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "elanfreq", .name = "elanfreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/suspend.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <plat/cpu.h> #include <plat/cpu.h>
...@@ -24,12 +23,8 @@ ...@@ -24,12 +23,8 @@
#include "exynos-cpufreq.h" #include "exynos-cpufreq.h"
static struct exynos_dvfs_info *exynos_info; static struct exynos_dvfs_info *exynos_info;
static struct regulator *arm_regulator; static struct regulator *arm_regulator;
static unsigned int locking_frequency; static unsigned int locking_frequency;
static bool frequency_locked;
static DEFINE_MUTEX(cpufreq_lock);
static int exynos_cpufreq_get_index(unsigned int freq) static int exynos_cpufreq_get_index(unsigned int freq)
{ {
...@@ -134,83 +129,13 @@ static int exynos_cpufreq_scale(unsigned int target_freq) ...@@ -134,83 +129,13 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
static int exynos_target(struct cpufreq_policy *policy, unsigned int index) static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
{ {
struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
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;
} }
static struct notifier_block exynos_cpufreq_nb = {
.notifier_call = exynos_cpufreq_pm_notifier,
};
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{ {
policy->clk = exynos_info->cpu_clk; policy->clk = exynos_info->cpu_clk;
policy->suspend_freq = locking_frequency;
return cpufreq_generic_init(policy, exynos_info->freq_table, 100000); return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
} }
...@@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = { ...@@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = {
.target_index = exynos_target, .target_index = exynos_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init, .init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "exynos_cpufreq", .name = "exynos_cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
#ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
.boost_supported = true, .boost_supported = true,
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = exynos_cpufreq_suspend, .suspend = cpufreq_generic_suspend,
.resume = exynos_cpufreq_resume,
#endif #endif
}; };
...@@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_vdd_arm; goto err_vdd_arm;
} }
/* Done here as we want to capture boot frequency */
locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000; locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
register_pm_notifier(&exynos_cpufreq_nb); if (!cpufreq_register_driver(&exynos_driver))
return 0;
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);
pr_err("%s: failed to register cpufreq driver\n", __func__);
regulator_put(arm_regulator); regulator_put(arm_regulator);
err_vdd_arm: err_vdd_arm:
kfree(exynos_info); kfree(exynos_info);
......
...@@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = { ...@@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = {
.target_index = exynos_target, .target_index = exynos_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init, .init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = CPUFREQ_NAME, .name = CPUFREQ_NAME,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, ...@@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
/* /*
* Generic routine to verify policy & frequency table, requires driver to call * Generic routine to verify policy & frequency table, requires driver to set
* cpufreq_frequency_table_get_attr() prior to it. * policy->freq_table prior to it.
*/ */
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
{ {
...@@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, ...@@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/** /**
* show_available_freqs - show available frequencies for the specified CPU * show_available_freqs - show available frequencies for the specified CPU
*/ */
...@@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, ...@@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
bool show_boost) bool show_boost)
{ {
unsigned int i = 0; unsigned int i = 0;
unsigned int cpu = policy->cpu;
ssize_t count = 0; ssize_t count = 0;
struct cpufreq_frequency_table *table; struct cpufreq_frequency_table *table = policy->freq_table;
if (!per_cpu(cpufreq_show_table, cpu)) if (!table)
return -ENODEV; return -ENODEV;
table = per_cpu(cpufreq_show_table, cpu);
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID) if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue; continue;
...@@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = { ...@@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = {
}; };
EXPORT_SYMBOL_GPL(cpufreq_generic_attr); EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
*/
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu)
{
pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
per_cpu(cpufreq_show_table, cpu) = table;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
pr_debug("clearing show_table for cpu %u\n", cpu);
per_cpu(cpufreq_show_table, cpu) = NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table) struct cpufreq_frequency_table *table)
{ {
int ret = cpufreq_frequency_table_cpuinfo(policy, table); int ret = cpufreq_frequency_table_cpuinfo(policy, table);
if (!ret) if (!ret)
cpufreq_frequency_table_get_attr(table, policy->cpu); policy->freq_table = table;
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy) struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
{
pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
policy->cpu, policy->last_cpu);
per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table,
policy->last_cpu);
per_cpu(cpufreq_show_table, policy->last_cpu) = NULL;
}
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{ {
return per_cpu(cpufreq_show_table, cpu); struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
return policy ? policy->freq_table : NULL;
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
......
...@@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit ( ...@@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit (
pr_debug("acpi_cpufreq_cpu_exit\n"); pr_debug("acpi_cpufreq_cpu_exit\n");
if (data) { if (data) {
cpufreq_frequency_table_put_attr(policy->cpu);
acpi_io_data[policy->cpu] = NULL; acpi_io_data[policy->cpu] = NULL;
acpi_processor_unregister_performance(&data->acpi_data, acpi_processor_unregister_performance(&data->acpi_data,
policy->cpu); policy->cpu);
......
...@@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { ...@@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
.target_index = imx6q_set_target, .target_index = imx6q_set_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = imx6q_cpufreq_init, .init = imx6q_cpufreq_init,
.exit = cpufreq_generic_exit,
.name = "imx6q-cpufreq", .name = "imx6q-cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -99,8 +99,7 @@ struct cpudata { ...@@ -99,8 +99,7 @@ struct cpudata {
u64 prev_aperf; u64 prev_aperf;
u64 prev_mperf; u64 prev_mperf;
unsigned long long prev_tsc; unsigned long long prev_tsc;
int sample_ptr; struct sample sample;
struct sample samples[SAMPLE_COUNT];
}; };
static struct cpudata **all_cpu_data; static struct cpudata **all_cpu_data;
...@@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy, ...@@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
pid->setpoint = setpoint; pid->setpoint = setpoint;
pid->deadband = deadband; pid->deadband = deadband;
pid->integral = int_tofp(integral); pid->integral = int_tofp(integral);
pid->last_err = setpoint - busy; pid->last_err = int_tofp(setpoint) - int_tofp(busy);
} }
static inline void pid_p_gain_set(struct _pid *pid, int percent) static inline void pid_p_gain_set(struct _pid *pid, int percent)
...@@ -447,7 +446,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate) ...@@ -447,7 +446,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
if (limits.no_turbo) if (limits.no_turbo)
val |= (u64)1 << 32; val |= (u64)1 << 32;
wrmsrl(MSR_IA32_PERF_CTL, val); wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
} }
static struct cpu_defaults core_params = { static struct cpu_defaults core_params = {
...@@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu) ...@@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
mperf = mperf >> FRAC_BITS; mperf = mperf >> FRAC_BITS;
tsc = tsc >> FRAC_BITS; tsc = tsc >> FRAC_BITS;
cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; cpu->sample.aperf = aperf;
cpu->samples[cpu->sample_ptr].aperf = aperf; cpu->sample.mperf = mperf;
cpu->samples[cpu->sample_ptr].mperf = mperf; cpu->sample.tsc = tsc;
cpu->samples[cpu->sample_ptr].tsc = tsc; cpu->sample.aperf -= cpu->prev_aperf;
cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; cpu->sample.mperf -= cpu->prev_mperf;
cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; cpu->sample.tsc -= cpu->prev_tsc;
cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc;
intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); intel_pstate_calc_busy(cpu, &cpu->sample);
cpu->prev_aperf = aperf; cpu->prev_aperf = aperf;
cpu->prev_mperf = mperf; cpu->prev_mperf = mperf;
...@@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) ...@@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
{ {
int32_t core_busy, max_pstate, current_pstate; int32_t core_busy, max_pstate, current_pstate;
core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; core_busy = cpu->sample.core_pct_busy;
max_pstate = int_tofp(cpu->pstate.max_pstate); max_pstate = int_tofp(cpu->pstate.max_pstate);
current_pstate = int_tofp(cpu->pstate.current_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate);
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
...@@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data) ...@@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data)
intel_pstate_sample(cpu); intel_pstate_sample(cpu);
sample = &cpu->samples[cpu->sample_ptr]; sample = &cpu->sample;
intel_pstate_adjust_busy_pstate(cpu); intel_pstate_adjust_busy_pstate(cpu);
...@@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) ...@@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
cpu = all_cpu_data[cpu_num]; cpu = all_cpu_data[cpu_num];
if (!cpu) if (!cpu)
return 0; return 0;
sample = &cpu->samples[cpu->sample_ptr]; sample = &cpu->sample;
return sample->freq; return sample->freq;
} }
...@@ -773,14 +771,17 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy) ...@@ -773,14 +771,17 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
{ {
int cpu = policy->cpu; int cpu_num = policy->cpu;
struct cpudata *cpu = all_cpu_data[cpu_num];
del_timer(&all_cpu_data[cpu]->timer); pr_info("intel_pstate CPU %d exiting\n", cpu_num);
kfree(all_cpu_data[cpu]);
all_cpu_data[cpu] = NULL; del_timer(&all_cpu_data[cpu_num]->timer);
return 0; intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
kfree(all_cpu_data[cpu_num]);
all_cpu_data[cpu_num] = NULL;
} }
static int intel_pstate_cpu_init(struct cpufreq_policy *policy) static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
...@@ -818,7 +819,7 @@ static struct cpufreq_driver intel_pstate_driver = { ...@@ -818,7 +819,7 @@ static struct cpufreq_driver intel_pstate_driver = {
.setpolicy = intel_pstate_set_policy, .setpolicy = intel_pstate_set_policy,
.get = intel_pstate_get, .get = intel_pstate_get,
.init = intel_pstate_cpu_init, .init = intel_pstate_cpu_init,
.exit = intel_pstate_cpu_exit, .stop_cpu = intel_pstate_stop_cpu,
.name = "intel_pstate", .name = "intel_pstate",
}; };
......
...@@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = { ...@@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = kirkwood_cpufreq_target, .target_index = kirkwood_cpufreq_target,
.init = kirkwood_cpufreq_cpu_init, .init = kirkwood_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "kirkwood-cpufreq", .name = "kirkwood-cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = { ...@@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = {
.target_index = longhaul_target, .target_index = longhaul_target,
.get = longhaul_get, .get = longhaul_get,
.init = longhaul_cpu_init, .init = longhaul_cpu_init,
.exit = cpufreq_generic_exit,
.name = "longhaul", .name = "longhaul",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
clk_put(policy->clk); clk_put(policy->clk);
return 0; return 0;
} }
......
...@@ -143,7 +143,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy) ...@@ -143,7 +143,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
static int omap_cpu_exit(struct cpufreq_policy *policy) static int omap_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
freq_table_free(); freq_table_free();
clk_put(policy->clk); clk_put(policy->clk);
return 0; return 0;
......
...@@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = { ...@@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cpufreq_p4_target, .target_index = cpufreq_p4_target,
.init = cpufreq_p4_cpu_init, .init = cpufreq_p4_cpu_init,
.exit = cpufreq_generic_exit,
.get = cpufreq_p4_get, .get = cpufreq_p4_get,
.name = "p4-clockmod", .name = "p4-clockmod",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
......
...@@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
if (sdcpwr_mapbase) if (sdcpwr_mapbase)
iounmap(sdcpwr_mapbase); iounmap(sdcpwr_mapbase);
cpufreq_frequency_table_put_attr(policy->cpu);
return 0; return 0;
} }
......
...@@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) ...@@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
if (i == max_multiplier) if (i == max_multiplier)
powernow_k6_target(policy, i); powernow_k6_target(policy, i);
} }
cpufreq_frequency_table_put_attr(policy->cpu);
return 0; return 0;
} }
......
...@@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) ...@@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
static int powernow_cpu_exit(struct cpufreq_policy *policy) static int powernow_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
#ifdef CONFIG_X86_POWERNOW_K7_ACPI #ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (acpi_processor_perf) { if (acpi_processor_perf) {
acpi_processor_unregister_performance(acpi_processor_perf, 0); acpi_processor_unregister_performance(acpi_processor_perf, 0);
......
...@@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) ...@@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
powernow_k8_cpu_exit_acpi(data); powernow_k8_cpu_exit_acpi(data);
cpufreq_frequency_table_put_attr(pol->cpu);
kfree(data->powernow_table); kfree(data->powernow_table);
kfree(data); kfree(data);
for_each_cpu(cpu, pol->cpus) for_each_cpu(cpu, pol->cpus)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <sysdev/fsl_soc.h>
/** /**
* struct cpu_data - per CPU data struct * struct cpu_data - per CPU data struct
...@@ -205,7 +206,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -205,7 +206,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
for_each_cpu(i, per_cpu(cpu_mask, cpu)) for_each_cpu(i, per_cpu(cpu_mask, cpu))
per_cpu(cpu_data, i) = data; per_cpu(cpu_data, i) = data;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cpuinfo.transition_latency =
(12 * NSEC_PER_SEC) / fsl_get_sys_freq();
of_node_put(np); of_node_put(np);
return 0; return 0;
...@@ -228,7 +230,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -228,7 +230,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
struct cpu_data *data = per_cpu(cpu_data, policy->cpu); struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
unsigned int cpu; unsigned int cpu;
cpufreq_frequency_table_put_attr(policy->cpu);
of_node_put(data->parent); of_node_put(data->parent);
kfree(data->table); kfree(data->table);
kfree(data); kfree(data);
......
...@@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = { ...@@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cbe_cpufreq_target, .target_index = cbe_cpufreq_target,
.init = cbe_cpufreq_cpu_init, .init = cbe_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cbe-cpufreq", .name = "cbe-cpufreq",
.flags = CPUFREQ_CONST_LOOPS, .flags = CPUFREQ_CONST_LOOPS,
}; };
......
...@@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = { ...@@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = pxa_set_target, .target_index = pxa_set_target,
.init = pxa_cpufreq_init, .init = pxa_cpufreq_init,
.exit = cpufreq_generic_exit,
.get = pxa_cpufreq_get, .get = pxa_cpufreq_get,
.name = "PXA2xx", .name = "PXA2xx",
}; };
......
...@@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = { ...@@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = pxa3xx_cpufreq_set, .target_index = pxa3xx_cpufreq_set,
.init = pxa3xx_cpufreq_init, .init = pxa3xx_cpufreq_init,
.exit = cpufreq_generic_exit,
.get = pxa3xx_cpufreq_get, .get = pxa3xx_cpufreq_get,
.name = "pxa3xx-cpufreq", .name = "pxa3xx-cpufreq",
}; };
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/suspend.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
...@@ -435,18 +434,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -435,18 +434,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
return ret; return ret;
} }
#ifdef CONFIG_PM
static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
{
return 0;
}
static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
{
return 0;
}
#endif
static int check_mem_type(void __iomem *dmc_reg) static int check_mem_type(void __iomem *dmc_reg)
{ {
unsigned long val; unsigned long val;
...@@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
policy->suspend_freq = SLEEP_FREQ;
return cpufreq_generic_init(policy, s5pv210_freq_table, 40000); return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
out_dmc1: out_dmc1:
...@@ -511,32 +499,6 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -511,32 +499,6 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int ret;
switch (event) {
case PM_SUSPEND_PREPARE:
ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
if (ret < 0)
return NOTIFY_BAD;
/* Disable updation of cpu frequency */
no_cpufreq_access = true;
return NOTIFY_OK;
case PM_POST_RESTORE:
case PM_POST_SUSPEND:
/* Enable updation of cpu frequency */
no_cpufreq_access = false;
cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
...@@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = { ...@@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = {
.init = s5pv210_cpu_init, .init = s5pv210_cpu_init,
.name = "s5pv210", .name = "s5pv210",
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = s5pv210_cpufreq_suspend, .suspend = cpufreq_generic_suspend,
.resume = s5pv210_cpufreq_resume, .resume = cpufreq_generic_suspend, /* We need to set SLEEP FREQ again */
#endif #endif
}; };
static struct notifier_block s5pv210_cpufreq_notifier = {
.notifier_call = s5pv210_cpufreq_notifier_event,
};
static struct notifier_block s5pv210_cpufreq_reboot_notifier = { static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
.notifier_call = s5pv210_cpufreq_reboot_notifier_event, .notifier_call = s5pv210_cpufreq_reboot_notifier_event,
}; };
...@@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void) ...@@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void)
return PTR_ERR(int_regulator); return PTR_ERR(int_regulator);
} }
register_pm_notifier(&s5pv210_cpufreq_notifier);
register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
return cpufreq_register_driver(&s5pv210_driver); return cpufreq_register_driver(&s5pv210_driver);
......
...@@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = { ...@@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = sc520_freq_target, .target_index = sc520_freq_target,
.init = sc520_freq_cpu_init, .init = sc520_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "sc520_freq", .name = "sc520_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
cpufreq_frequency_table_put_attr(cpu);
clk_put(cpuclk); clk_put(cpuclk);
return 0; return 0;
......
...@@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
{ {
if (cpufreq_us2e_driver) { if (cpufreq_us2e_driver)
cpufreq_frequency_table_put_attr(policy->cpu);
us2e_freq_target(policy, 0); us2e_freq_target(policy, 0);
}
return 0; return 0;
} }
......
...@@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
static int us3_freq_cpu_exit(struct cpufreq_policy *policy) static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
{ {
if (cpufreq_us3_driver) { if (cpufreq_us3_driver)
cpufreq_frequency_table_put_attr(policy->cpu);
us3_freq_target(policy, 0); us3_freq_target(policy, 0);
}
return 0; return 0;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = { ...@@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = {
.target_index = spear_cpufreq_target, .target_index = spear_cpufreq_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = spear_cpufreq_init, .init = spear_cpufreq_init,
.exit = cpufreq_generic_exit,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
static int spear_cpufreq_driver_init(void) static int spear_cpufreq_probe(struct platform_device *pdev)
{ {
struct device_node *np; struct device_node *np;
const struct property *prop; const struct property *prop;
...@@ -235,7 +235,15 @@ static int spear_cpufreq_driver_init(void) ...@@ -235,7 +235,15 @@ static int spear_cpufreq_driver_init(void)
of_node_put(np); of_node_put(np);
return ret; return ret;
} }
late_initcall(spear_cpufreq_driver_init);
static struct platform_driver spear_cpufreq_platdrv = {
.driver = {
.name = "spear-cpufreq",
.owner = THIS_MODULE,
},
.probe = spear_cpufreq_probe,
};
module_platform_driver(spear_cpufreq_platdrv);
MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>"); MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
MODULE_DESCRIPTION("SPEAr CPUFreq driver"); MODULE_DESCRIPTION("SPEAr CPUFreq driver");
......
...@@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) ...@@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
if (!per_cpu(centrino_model, cpu)) if (!per_cpu(centrino_model, cpu))
return -ENODEV; return -ENODEV;
cpufreq_frequency_table_put_attr(cpu);
per_cpu(centrino_model, cpu) = NULL; per_cpu(centrino_model, cpu) = NULL;
return 0; return 0;
......
...@@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = speedstep_target, .target_index = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.exit = cpufreq_generic_exit,
.get = speedstep_get, .get = speedstep_get,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = speedstep_target, .target_index = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.exit = cpufreq_generic_exit,
.get = speedstep_get, .get = speedstep_get,
.resume = speedstep_resume, .resume = speedstep_resume,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/suspend.h>
static struct cpufreq_frequency_table freq_table[] = { static struct cpufreq_frequency_table freq_table[] = {
{ .frequency = 216000 }, { .frequency = 216000 },
...@@ -47,9 +46,6 @@ static struct clk *pll_x_clk; ...@@ -47,9 +46,6 @@ static struct clk *pll_x_clk;
static struct clk *pll_p_clk; static struct clk *pll_p_clk;
static struct clk *emc_clk; static struct clk *emc_clk;
static DEFINE_MUTEX(tegra_cpu_lock);
static bool is_suspended;
static int tegra_cpu_clk_set_rate(unsigned long rate) static int tegra_cpu_clk_set_rate(unsigned long rate)
{ {
int ret; int ret;
...@@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy, ...@@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
static int tegra_target(struct cpufreq_policy *policy, unsigned int index) static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
{ {
int ret = -EBUSY; return tegra_update_cpu_speed(policy, freq_table[index].frequency);
mutex_lock(&tegra_cpu_lock);
if (!is_suspended)
ret = tegra_update_cpu_speed(policy,
freq_table[index].frequency);
mutex_unlock(&tegra_cpu_lock);
return ret;
} }
static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
{
mutex_lock(&tegra_cpu_lock);
if (event == PM_SUSPEND_PREPARE) {
struct cpufreq_policy *policy = cpufreq_cpu_get(0);
is_suspended = true;
pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
freq_table[0].frequency);
if (clk_get_rate(cpu_clk) / 1000 != freq_table[0].frequency)
tegra_update_cpu_speed(policy, freq_table[0].frequency);
cpufreq_cpu_put(policy);
} else if (event == PM_POST_SUSPEND) {
is_suspended = false;
}
mutex_unlock(&tegra_cpu_lock);
return NOTIFY_OK;
}
static struct notifier_block tegra_cpu_pm_notifier = {
.notifier_call = tegra_pm_notify,
};
static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_init(struct cpufreq_policy *policy)
{ {
int ret; int ret;
...@@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) ...@@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
if (policy->cpu == 0)
register_pm_notifier(&tegra_cpu_pm_notifier);
policy->clk = cpu_clk; policy->clk = cpu_clk;
policy->suspend_freq = freq_table[0].frequency;
return 0; return 0;
} }
static int tegra_cpu_exit(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
clk_disable_unprepare(cpu_clk); clk_disable_unprepare(cpu_clk);
clk_disable_unprepare(emc_clk); clk_disable_unprepare(emc_clk);
return 0; return 0;
...@@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = { ...@@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
.exit = tegra_cpu_exit, .exit = tegra_cpu_exit,
.name = "tegra", .name = "tegra",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
#ifdef CONFIG_PM
.suspend = cpufreq_generic_suspend,
#endif
}; };
static int __init tegra_cpufreq_init(void) static int __init tegra_cpufreq_init(void)
......
...@@ -125,9 +125,6 @@ sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, ...@@ -125,9 +125,6 @@ sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
if (freqs->new < freqs->old) if (freqs->new < freqs->old)
sa1100_pcmcia_set_mecr(skt, freqs->new); sa1100_pcmcia_set_mecr(skt, freqs->new);
break; break;
case CPUFREQ_RESUMECHANGE:
sa1100_pcmcia_set_mecr(skt, freqs->new);
break;
} }
return 0; return 0;
......
...@@ -1041,8 +1041,7 @@ static int sci_notifier(struct notifier_block *self, ...@@ -1041,8 +1041,7 @@ static int sci_notifier(struct notifier_block *self,
sci_port = container_of(self, struct sci_port, freq_transition); sci_port = container_of(self, struct sci_port, freq_transition);
if ((phase == CPUFREQ_POSTCHANGE) || if (phase == CPUFREQ_POSTCHANGE) {
(phase == CPUFREQ_RESUMECHANGE)) {
struct uart_port *port = &sci_port->port; struct uart_port *port = &sci_port->port;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
......
...@@ -74,6 +74,8 @@ struct cpufreq_policy { ...@@ -74,6 +74,8 @@ struct cpufreq_policy {
unsigned int max; /* in kHz */ unsigned int max; /* in kHz */
unsigned int cur; /* in kHz, only needed if cpufreq unsigned int cur; /* in kHz, only needed if cpufreq
* governors are used */ * governors are used */
unsigned int suspend_freq; /* freq to set during suspend */
unsigned int policy; /* see above */ unsigned int policy; /* see above */
struct cpufreq_governor *governor; /* see below */ struct cpufreq_governor *governor; /* see below */
void *governor_data; void *governor_data;
...@@ -83,6 +85,7 @@ struct cpufreq_policy { ...@@ -83,6 +85,7 @@ struct cpufreq_policy {
* called, but you're in IRQ context */ * called, but you're in IRQ context */
struct cpufreq_real_policy user_policy; struct cpufreq_real_policy user_policy;
struct cpufreq_frequency_table *freq_table;
struct list_head policy_list; struct list_head policy_list;
struct kobject kobj; struct kobject kobj;
...@@ -224,6 +227,7 @@ struct cpufreq_driver { ...@@ -224,6 +227,7 @@ struct cpufreq_driver {
int (*bios_limit) (int cpu, unsigned int *limit); int (*bios_limit) (int cpu, unsigned int *limit);
int (*exit) (struct cpufreq_policy *policy); int (*exit) (struct cpufreq_policy *policy);
void (*stop_cpu) (struct cpufreq_policy *policy);
int (*suspend) (struct cpufreq_policy *policy); int (*suspend) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy); int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr; struct freq_attr **attr;
...@@ -296,6 +300,15 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) ...@@ -296,6 +300,15 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq); policy->cpuinfo.max_freq);
} }
#ifdef CONFIG_CPU_FREQ
void cpufreq_suspend(void);
void cpufreq_resume(void);
int cpufreq_generic_suspend(struct cpufreq_policy *policy);
#else
static inline void cpufreq_suspend(void) {}
static inline void cpufreq_resume(void) {}
#endif
/********************************************************************* /*********************************************************************
* CPUFREQ NOTIFIER INTERFACE * * CPUFREQ NOTIFIER INTERFACE *
*********************************************************************/ *********************************************************************/
...@@ -306,8 +319,6 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) ...@@ -306,8 +319,6 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
/* Transition notifiers */ /* Transition notifiers */
#define CPUFREQ_PRECHANGE (0) #define CPUFREQ_PRECHANGE (0)
#define CPUFREQ_POSTCHANGE (1) #define CPUFREQ_POSTCHANGE (1)
#define CPUFREQ_RESUMECHANGE (8)
#define CPUFREQ_SUSPENDCHANGE (9)
/* Policy Notifiers */ /* Policy Notifiers */
#define CPUFREQ_ADJUST (0) #define CPUFREQ_ADJUST (0)
...@@ -463,7 +474,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -463,7 +474,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
unsigned int freq); unsigned int freq);
void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
...@@ -490,9 +500,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); ...@@ -490,9 +500,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
/* the following are really really optional */ /* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
extern struct freq_attr *cpufreq_generic_attr[]; extern struct freq_attr *cpufreq_generic_attr[];
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
void cpufreq_frequency_table_put_attr(unsigned int cpu);
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table); struct cpufreq_frequency_table *table);
...@@ -500,10 +507,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu); ...@@ -500,10 +507,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu);
int cpufreq_generic_init(struct cpufreq_policy *policy, int cpufreq_generic_init(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table, struct cpufreq_frequency_table *table,
unsigned int transition_latency); unsigned int transition_latency);
static inline int cpufreq_generic_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
#endif /* _LINUX_CPUFREQ_H */ #endif /* _LINUX_CPUFREQ_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment