From 8097e8eb85bd04983f38cecab00e8a9e90a6189f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 13 Dec 2011 12:48:18 +0100 Subject: [PATCH] --- yaml --- r: 279798 b: refs/heads/master c: 4fd7f9b128107034fa925b6877fae3c275f0da86 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/kernel/smp_twd.c | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index eee902588ce6..e8f4edb07788 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5def51b0f827931bb559e6195060d774894fc9f9 +refs/heads/master: 4fd7f9b128107034fa925b6877fae3c275f0da86 diff --git a/trunk/arch/arm/kernel/smp_twd.c b/trunk/arch/arm/kernel/smp_twd.c index a9783947c086..c8e938553d47 100644 --- a/trunk/arch/arm/kernel/smp_twd.c +++ b/trunk/arch/arm/kernel/smp_twd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,52 @@ void twd_timer_stop(struct clock_event_device *clk) disable_percpu_irq(clk->irq); } +#ifdef CONFIG_CPU_FREQ + +/* + * Updates clockevent frequency when the cpu frequency changes. + * Called on the cpu that is changing frequency with interrupts disabled. + */ +static void twd_update_frequency(void *data) +{ + twd_timer_rate = clk_get_rate(twd_clk); + + clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); +} + +static int twd_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *freqs = data; + + /* + * The twd clock events must be reprogrammed to account for the new + * frequency. The timer is local to a cpu, so cross-call to the + * changing cpu. + */ + if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) + smp_call_function_single(freqs->cpu, twd_update_frequency, + NULL, 1); + + return NOTIFY_OK; +} + +static struct notifier_block twd_cpufreq_nb = { + .notifier_call = twd_cpufreq_transition, +}; + +static int twd_cpufreq_init(void) +{ + if (!IS_ERR(twd_clk)) + return cpufreq_register_notifier(&twd_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + return 0; +} +core_initcall(twd_cpufreq_init); + +#endif + static void __cpuinit twd_calibrate_rate(void) { unsigned long count;