From: Linus Walleij <linus.walleij@linaro.org> To: Colin Cross <ccross@android.com>, Thomas Gleixner <tglx@linutronix.de> Cc: linux-arm-kernel@lists-infradead.org, Russell King <linux@arm.linux.org.uk>, linux-kernel@vger.kernel.org, Santosh Shilimkar <santosh.shilimkar@ti.com>, linux-arm-kernel@lists.infradead.org, Martin Persson <martin.persson@stericsson.com>, Rob Herring <robherring2@gmail.com> Subject: Re: [PATCH] ARM: smp_twd: Reconfigure clockevents after cpufreq change Date: Thu, 19 May 2011 19:32:22 +0200 [thread overview] Message-ID: <BANLkTim4U-CJ_D3VSNzwd23XL3fDXT7onQ@mail.gmail.com> (raw) In-Reply-To: <1305588114-23728-1-git-send-email-ccross@android.com> 2011/5/17 Colin Cross <ccross@android.com>: > This patch depends on Thomas Gleixner's patch to add clockevents_reconfigure > See: https://lkml.org/lkml/2011/5/13/122 Patch set has evolved, see below. Also note that you more or less reimplement Rob Herrings patch: http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=6802/1 (no big deal I guess, give him a nod) To work with Thomas full changeset just create a fresh branch and: git pull git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git timers/clockevents Pls change subject from ARM: to clockevents: and merge through Thomas tree (IMHO). > diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c > index 60636f4..dbf58d4 100644 > --- a/arch/arm/kernel/smp_twd.c > +++ b/arch/arm/kernel/smp_twd.c > @@ -10,21 +10,29 @@ > */ > #include <linux/init.h> > #include <linux/kernel.h> > +#include <linux/clk.h> > +#include <linux/cpufreq.h> > #include <linux/delay.h> > #include <linux/device.h> > +#include <linux/err.h> > #include <linux/smp.h> > #include <linux/jiffies.h> > #include <linux/clockchips.h> > #include <linux/irq.h> > #include <linux/io.h> > +#include <linux/percpu.h> > > #include <asm/smp_twd.h> > #include <asm/hardware/gic.h> > > +#define TWD_MIN_RANGE 4 > + Loose this. Let the framework decide using the function below. > /* set up by the platform code */ > void __iomem *twd_base; > > +static struct clk *twd_clk; > static unsigned long twd_timer_rate; > +static DEFINE_PER_CPU(struct clock_event_device *, twd_ce); > > static void twd_set_mode(enum clock_event_mode mode, > struct clock_event_device *clk) > @@ -80,6 +88,49 @@ int twd_timer_ack(void) > return 0; > } > > +/* > + * 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_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, > + TWD_MIN_RANGE); Changed name to clockevents_update_freq(), dropped range argument. > +} > + > +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_OR_NULL(twd_clk)) > + return cpufreq_register_notifier(&twd_cpufreq_nb, > + CPUFREQ_TRANSITION_NOTIFIER); > + > + return 0; > +} > +core_initcall(twd_cpufreq_init); > + > static void __cpuinit twd_calibrate_rate(void) > { > unsigned long count; > @@ -124,7 +175,16 @@ static void __cpuinit twd_calibrate_rate(void) > */ > void __cpuinit twd_timer_setup(struct clock_event_device *clk) > { > - twd_calibrate_rate(); > + if (twd_clk == NULL) { > + twd_clk = clk_get_sys("smp_twd", NULL); > + if (IS_ERR_OR_NULL(twd_clk)) > + pr_warn("%s: no clock found\n", __func__); > + } > + > + if (!IS_ERR_OR_NULL(twd_clk)) > + twd_timer_rate = clk_get_rate(twd_clk); > + else > + twd_calibrate_rate(); > > clk->name = "local_timer"; > clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | > @@ -132,13 +192,16 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) > clk->rating = 350; > clk->set_mode = twd_set_mode; > clk->set_next_event = twd_set_next_event; > - clk->shift = 20; > - clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift); > + > + clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); > + > clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); > clk->min_delta_ns = clockevent_delta2ns(0xf, clk); Get rid of everything between clk->shift ... and here and replace it with: clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); > /* Make sure our local interrupt controller has this enabled */ > gic_enable_ppi(clk->irq); > > + __get_cpu_var(twd_ce) = clk; > + > clockevents_register_device(clk); > } Or just smack in this patch on top: >From fd546090b8f0cb5df06103c014466c86cf58b73a Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@stericsson.com> Date: Thu, 19 May 2011 18:55:22 +0200 Subject: [PATCH] Fix smallish cleanup --- arch/arm/kernel/smp_twd.c | 13 +++---------- 1 files changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index dbf58d4..968f298 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -25,8 +25,6 @@ #include <asm/smp_twd.h> #include <asm/hardware/gic.h> -#define TWD_MIN_RANGE 4 - /* set up by the platform code */ void __iomem *twd_base; @@ -96,8 +94,7 @@ static void twd_update_frequency(void *data) { twd_timer_rate = clk_get_rate(twd_clk); - clockevents_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, - TWD_MIN_RANGE); + clockevents_update_freq(__get_cpu_var(twd_ce), twd_timer_rate); } static int twd_cpufreq_transition(struct notifier_block *nb, @@ -193,15 +190,11 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; - clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); - - clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); - clk->min_delta_ns = clockevent_delta2ns(0xf, clk); - /* Make sure our local interrupt controller has this enabled */ gic_enable_ppi(clk->irq); __get_cpu_var(twd_ce) = clk; - clockevents_register_device(clk); + clockevents_config_and_register(clk, twd_timer_rate, + 0xf, 0xffffffff); } -- 1.7.3.2 With these changes (provided they work) all should be well, so: Tested-by: Linus Walleij <linus.walleij@linaro.org> If all is well on your side as well, ask Thomas to take this into the timers/clockevents branch where all dependencies are. Yours, Linus Walleij
WARNING: multiple messages have this Message-ID (diff)
From: linus.walleij@linaro.org (Linus Walleij) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] ARM: smp_twd: Reconfigure clockevents after cpufreq change Date: Thu, 19 May 2011 19:32:22 +0200 [thread overview] Message-ID: <BANLkTim4U-CJ_D3VSNzwd23XL3fDXT7onQ@mail.gmail.com> (raw) In-Reply-To: <1305588114-23728-1-git-send-email-ccross@android.com> 2011/5/17 Colin Cross <ccross@android.com>: > This patch depends on Thomas Gleixner's patch to add clockevents_reconfigure > See: https://lkml.org/lkml/2011/5/13/122 Patch set has evolved, see below. Also note that you more or less reimplement Rob Herrings patch: http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=6802/1 (no big deal I guess, give him a nod) To work with Thomas full changeset just create a fresh branch and: git pull git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git timers/clockevents Pls change subject from ARM: to clockevents: and merge through Thomas tree (IMHO). > diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c > index 60636f4..dbf58d4 100644 > --- a/arch/arm/kernel/smp_twd.c > +++ b/arch/arm/kernel/smp_twd.c > @@ -10,21 +10,29 @@ > ?*/ > ?#include <linux/init.h> > ?#include <linux/kernel.h> > +#include <linux/clk.h> > +#include <linux/cpufreq.h> > ?#include <linux/delay.h> > ?#include <linux/device.h> > +#include <linux/err.h> > ?#include <linux/smp.h> > ?#include <linux/jiffies.h> > ?#include <linux/clockchips.h> > ?#include <linux/irq.h> > ?#include <linux/io.h> > +#include <linux/percpu.h> > > ?#include <asm/smp_twd.h> > ?#include <asm/hardware/gic.h> > > +#define TWD_MIN_RANGE 4 > + Loose this. Let the framework decide using the function below. > ?/* set up by the platform code */ > ?void __iomem *twd_base; > > +static struct clk *twd_clk; > ?static unsigned long twd_timer_rate; > +static DEFINE_PER_CPU(struct clock_event_device *, twd_ce); > > ?static void twd_set_mode(enum clock_event_mode mode, > ? ? ? ? ? ? ? ? ? ? ? ?struct clock_event_device *clk) > @@ -80,6 +88,49 @@ int twd_timer_ack(void) > ? ? ? ?return 0; > ?} > > +/* > + * 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_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, > + ? ? ? ? ? ? ? ? ? ? ? TWD_MIN_RANGE); Changed name to clockevents_update_freq(), dropped range argument. > +} > + > +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_OR_NULL(twd_clk)) > + ? ? ? ? ? ? ? return cpufreq_register_notifier(&twd_cpufreq_nb, > + ? ? ? ? ? ? ? ? ? ? ? CPUFREQ_TRANSITION_NOTIFIER); > + > + ? ? ? return 0; > +} > +core_initcall(twd_cpufreq_init); > + > ?static void __cpuinit twd_calibrate_rate(void) > ?{ > ? ? ? ?unsigned long count; > @@ -124,7 +175,16 @@ static void __cpuinit twd_calibrate_rate(void) > ?*/ > ?void __cpuinit twd_timer_setup(struct clock_event_device *clk) > ?{ > - ? ? ? twd_calibrate_rate(); > + ? ? ? if (twd_clk == NULL) { > + ? ? ? ? ? ? ? twd_clk = clk_get_sys("smp_twd", NULL); > + ? ? ? ? ? ? ? if (IS_ERR_OR_NULL(twd_clk)) > + ? ? ? ? ? ? ? ? ? ? ? pr_warn("%s: no clock found\n", __func__); > + ? ? ? } > + > + ? ? ? if (!IS_ERR_OR_NULL(twd_clk)) > + ? ? ? ? ? ? ? twd_timer_rate = clk_get_rate(twd_clk); > + ? ? ? else > + ? ? ? ? ? ? ? twd_calibrate_rate(); > > ? ? ? ?clk->name = "local_timer"; > ? ? ? ?clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | > @@ -132,13 +192,16 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) > ? ? ? ?clk->rating = 350; > ? ? ? ?clk->set_mode = twd_set_mode; > ? ? ? ?clk->set_next_event = twd_set_next_event; > - ? ? ? clk->shift = 20; > - ? ? ? clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift); > + > + ? ? ? clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); > + > ? ? ? ?clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); > ? ? ? ?clk->min_delta_ns = clockevent_delta2ns(0xf, clk); Get rid of everything between clk->shift ... and here and replace it with: clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); > ? ? ? ?/* Make sure our local interrupt controller has this enabled */ > ? ? ? ?gic_enable_ppi(clk->irq); > > + ? ? ? __get_cpu_var(twd_ce) = clk; > + > ? ? ? ?clockevents_register_device(clk); > ?} Or just smack in this patch on top:
next prev parent reply other threads:[~2011-05-19 17:32 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top 2011-05-16 23:21 [PATCH] ARM: smp_twd: Reconfigure clockevents after cpufreq change Colin Cross 2011-05-16 23:21 ` Colin Cross 2011-05-17 14:00 ` Santosh Shilimkar 2011-05-17 14:00 ` Santosh Shilimkar 2011-05-17 17:06 ` Colin Cross 2011-05-17 17:06 ` Colin Cross 2011-05-18 11:32 ` Santosh Shilimkar 2011-05-18 11:32 ` Santosh Shilimkar 2011-05-19 17:32 ` Linus Walleij [this message] 2011-05-19 17:32 ` Linus Walleij 2011-05-19 23:26 ` Colin Cross 2011-05-19 23:26 ` Colin Cross 2011-06-01 9:15 Linus Walleij 2011-06-14 5:50 ` Linus Walleij 2011-06-14 6:00 ` Colin Cross 2011-06-14 6:12 ` Santosh Shilimkar 2011-06-14 6:14 ` Linus Walleij
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=BANLkTim4U-CJ_D3VSNzwd23XL3fDXT7onQ@mail.gmail.com \ --to=linus.walleij@linaro.org \ --cc=ccross@android.com \ --cc=linux-arm-kernel@lists-infradead.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@arm.linux.org.uk \ --cc=martin.persson@stericsson.com \ --cc=robherring2@gmail.com \ --cc=santosh.shilimkar@ti.com \ --cc=tglx@linutronix.de \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.