All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-20  0:24 ` Colin Cross
  0 siblings, 0 replies; 14+ messages in thread
From: Colin Cross @ 2011-05-20  0:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Colin Cross, Thomas Gleixner, Russell King, Santosh Shilimkar,
	Rob Herring, linux-kernel

The localtimer's clock changes with the cpu clock.  After a
cpufreq transition, update the clockevent's frequency and
reprogram the next clock event.

Adds a clock called "smp_twd" that is used to determine the
twd frequency, which can also be used at init time to
avoid calibrating the twd frequency.

Clock changes are based on Rob Herring's work.

Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
Signed-off-by: Colin Cross <ccross@android.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Rob Herring <robherring2@gmail.com>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/kernel/smp_twd.c |   86 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 80 insertions(+), 6 deletions(-)

This patch depends on Thomas Gleixner's patch to add clockevents_update_freq

v2: Squash in changes from Linus Wallej, enable smp_twd clock during init

diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 60636f4..b5bd303 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -10,13 +10,17 @@
  */
 #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>
@@ -24,7 +28,9 @@
 /* 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 +86,48 @@ 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_update_freq(__get_cpu_var(twd_ce), 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_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;
@@ -119,12 +167,39 @@ static void __cpuinit twd_calibrate_rate(void)
 	}
 }
 
+static struct clk *twd_get_clock(void)
+{
+	struct clk *clk;
+	int err;
+
+	clk = clk_get_sys("smp_twd", NULL);
+	if (IS_ERR(clk)) {
+		pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk));
+		return clk;
+	}
+
+	err = clk_enable(clk);
+	if (err) {
+		pr_err("smp_twd: clock failed to enable: %d\n", err);
+		clk_put(clk);
+		return ERR_PTR(err);
+	}
+
+	return clk;
+}
+
 /*
  * Setup the local clock events for a CPU.
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-	twd_calibrate_rate();
+	if (!twd_clk)
+		twd_clk = twd_get_clock();
+
+	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 +207,12 @@ 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);
-	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);
 
-	clockevents_register_device(clk);
+	__get_cpu_var(twd_ce) = clk;
+
+	clockevents_config_and_register(clk, twd_timer_rate,
+					0xf, 0xffffffff);
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-20  0:24 ` Colin Cross
  0 siblings, 0 replies; 14+ messages in thread
From: Colin Cross @ 2011-05-20  0:24 UTC (permalink / raw)
  To: linux-arm-kernel

The localtimer's clock changes with the cpu clock.  After a
cpufreq transition, update the clockevent's frequency and
reprogram the next clock event.

Adds a clock called "smp_twd" that is used to determine the
twd frequency, which can also be used at init time to
avoid calibrating the twd frequency.

Clock changes are based on Rob Herring's work.

Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
Signed-off-by: Colin Cross <ccross@android.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Rob Herring <robherring2@gmail.com>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/kernel/smp_twd.c |   86 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 80 insertions(+), 6 deletions(-)

This patch depends on Thomas Gleixner's patch to add clockevents_update_freq

v2: Squash in changes from Linus Wallej, enable smp_twd clock during init

diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 60636f4..b5bd303 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -10,13 +10,17 @@
  */
 #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>
@@ -24,7 +28,9 @@
 /* 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 +86,48 @@ 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_update_freq(__get_cpu_var(twd_ce), 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_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;
@@ -119,12 +167,39 @@ static void __cpuinit twd_calibrate_rate(void)
 	}
 }
 
+static struct clk *twd_get_clock(void)
+{
+	struct clk *clk;
+	int err;
+
+	clk = clk_get_sys("smp_twd", NULL);
+	if (IS_ERR(clk)) {
+		pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk));
+		return clk;
+	}
+
+	err = clk_enable(clk);
+	if (err) {
+		pr_err("smp_twd: clock failed to enable: %d\n", err);
+		clk_put(clk);
+		return ERR_PTR(err);
+	}
+
+	return clk;
+}
+
 /*
  * Setup the local clock events for a CPU.
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-	twd_calibrate_rate();
+	if (!twd_clk)
+		twd_clk = twd_get_clock();
+
+	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 +207,12 @@ 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);
-	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);
 
-	clockevents_register_device(clk);
+	__get_cpu_var(twd_ce) = clk;
+
+	clockevents_config_and_register(clk, twd_timer_rate,
+					0xf, 0xffffffff);
 }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-20  0:24 ` Colin Cross
@ 2011-05-20 21:50   ` Linus Walleij
  -1 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2011-05-20 21:50 UTC (permalink / raw)
  To: Thomas Gleixner, Colin Cross
  Cc: linux-arm-kernel, Russell King, Santosh Shilimkar, Rob Herring,
	linux-kernel

On Fri, May 20, 2011 at 2:24 AM, Colin Cross <ccross@android.com> wrote:

> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross <ccross@android.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Rob Herring <robherring2@gmail.com>
> Tested-by: Linus Walleij <linus.walleij@linaro.org>

OK Thomas can you take this in through the clock/timer
branch? Works fine for me and Colin and solves many problems
apart from making the code look neat.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-20 21:50   ` Linus Walleij
  0 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2011-05-20 21:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, May 20, 2011 at 2:24 AM, Colin Cross <ccross@android.com> wrote:

> The localtimer's clock changes with the cpu clock. ?After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross <ccross@android.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Rob Herring <robherring2@gmail.com>
> Tested-by: Linus Walleij <linus.walleij@linaro.org>

OK Thomas can you take this in through the clock/timer
branch? Works fine for me and Colin and solves many problems
apart from making the code look neat.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-20  0:24 ` Colin Cross
@ 2011-05-21  3:33   ` Rob Herring
  -1 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2011-05-21  3:33 UTC (permalink / raw)
  To: Colin Cross
  Cc: linux-arm-kernel, Thomas Gleixner, Russell King,
	Santosh Shilimkar, linux-kernel

On 05/19/2011 07:24 PM, Colin Cross wrote:
> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross<ccross@android.com>
> Cc: Thomas Gleixner<tglx@linutronix.de>
> Cc: Russell King<linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
> Cc: Rob Herring<robherring2@gmail.com>
> Tested-by: Linus Walleij<linus.walleij@linaro.org>

Acked-by: Rob Herring <rob.herring@calxeda.com>

> ---
>   arch/arm/kernel/smp_twd.c |   86 +++++++++++++++++++++++++++++++++++++++++---
>   1 files changed, 80 insertions(+), 6 deletions(-)
>
> This patch depends on Thomas Gleixner's patch to add clockevents_update_freq
>
> v2: Squash in changes from Linus Wallej, enable smp_twd clock during init
>
> diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
> index 60636f4..b5bd303 100644
> --- a/arch/arm/kernel/smp_twd.c
> +++ b/arch/arm/kernel/smp_twd.c
> @@ -10,13 +10,17 @@
>    */
>   #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>
> @@ -24,7 +28,9 @@
>   /* 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 +86,48 @@ 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_update_freq(__get_cpu_var(twd_ce), 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_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;
> @@ -119,12 +167,39 @@ static void __cpuinit twd_calibrate_rate(void)
>   	}
>   }
>
> +static struct clk *twd_get_clock(void)
> +{
> +	struct clk *clk;
> +	int err;
> +
> +	clk = clk_get_sys("smp_twd", NULL);
> +	if (IS_ERR(clk)) {
> +		pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk));
> +		return clk;
> +	}
> +
> +	err = clk_enable(clk);
> +	if (err) {
> +		pr_err("smp_twd: clock failed to enable: %d\n", err);
> +		clk_put(clk);
> +		return ERR_PTR(err);
> +	}
> +
> +	return clk;
> +}
> +
>   /*
>    * Setup the local clock events for a CPU.
>    */
>   void __cpuinit twd_timer_setup(struct clock_event_device *clk)
>   {
> -	twd_calibrate_rate();
> +	if (!twd_clk)
> +		twd_clk = twd_get_clock();
> +
> +	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 +207,12 @@ 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);
> -	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);
>
> -	clockevents_register_device(clk);
> +	__get_cpu_var(twd_ce) = clk;
> +
> +	clockevents_config_and_register(clk, twd_timer_rate,
> +					0xf, 0xffffffff);
>   }


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-21  3:33   ` Rob Herring
  0 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2011-05-21  3:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/19/2011 07:24 PM, Colin Cross wrote:
> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross<ccross@android.com>
> Cc: Thomas Gleixner<tglx@linutronix.de>
> Cc: Russell King<linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
> Cc: Rob Herring<robherring2@gmail.com>
> Tested-by: Linus Walleij<linus.walleij@linaro.org>

Acked-by: Rob Herring <rob.herring@calxeda.com>

> ---
>   arch/arm/kernel/smp_twd.c |   86 +++++++++++++++++++++++++++++++++++++++++---
>   1 files changed, 80 insertions(+), 6 deletions(-)
>
> This patch depends on Thomas Gleixner's patch to add clockevents_update_freq
>
> v2: Squash in changes from Linus Wallej, enable smp_twd clock during init
>
> diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
> index 60636f4..b5bd303 100644
> --- a/arch/arm/kernel/smp_twd.c
> +++ b/arch/arm/kernel/smp_twd.c
> @@ -10,13 +10,17 @@
>    */
>   #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>
> @@ -24,7 +28,9 @@
>   /* 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 +86,48 @@ 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_update_freq(__get_cpu_var(twd_ce), 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_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;
> @@ -119,12 +167,39 @@ static void __cpuinit twd_calibrate_rate(void)
>   	}
>   }
>
> +static struct clk *twd_get_clock(void)
> +{
> +	struct clk *clk;
> +	int err;
> +
> +	clk = clk_get_sys("smp_twd", NULL);
> +	if (IS_ERR(clk)) {
> +		pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk));
> +		return clk;
> +	}
> +
> +	err = clk_enable(clk);
> +	if (err) {
> +		pr_err("smp_twd: clock failed to enable: %d\n", err);
> +		clk_put(clk);
> +		return ERR_PTR(err);
> +	}
> +
> +	return clk;
> +}
> +
>   /*
>    * Setup the local clock events for a CPU.
>    */
>   void __cpuinit twd_timer_setup(struct clock_event_device *clk)
>   {
> -	twd_calibrate_rate();
> +	if (!twd_clk)
> +		twd_clk = twd_get_clock();
> +
> +	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 +207,12 @@ 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);
> -	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);
>
> -	clockevents_register_device(clk);
> +	__get_cpu_var(twd_ce) = clk;
> +
> +	clockevents_config_and_register(clk, twd_timer_rate,
> +					0xf, 0xffffffff);
>   }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-20  0:24 ` Colin Cross
@ 2011-05-21  6:29   ` Santosh Shilimkar
  -1 siblings, 0 replies; 14+ messages in thread
From: Santosh Shilimkar @ 2011-05-21  6:29 UTC (permalink / raw)
  To: Colin Cross
  Cc: linux-arm-kernel, Thomas Gleixner, Russell King, Rob Herring,
	linux-kernel

On 5/20/2011 5:54 AM, Colin Cross wrote:
> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross<ccross@android.com>
> Cc: Thomas Gleixner<tglx@linutronix.de>
> Cc: Russell King<linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
> Cc: Rob Herring<robherring2@gmail.com>
> Tested-by: Linus Walleij<linus.walleij@linaro.org>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

What about the clock-node patches?
Do you want those to get merged via sub-arch tree's once this
patch + Thomas's new API gets merged ?

Regards
Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-21  6:29   ` Santosh Shilimkar
  0 siblings, 0 replies; 14+ messages in thread
From: Santosh Shilimkar @ 2011-05-21  6:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 5/20/2011 5:54 AM, Colin Cross wrote:
> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.
>
> Adds a clock called "smp_twd" that is used to determine the
> twd frequency, which can also be used at init time to
> avoid calibrating the twd frequency.
>
> Clock changes are based on Rob Herring's work.
>
> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
> Signed-off-by: Colin Cross<ccross@android.com>
> Cc: Thomas Gleixner<tglx@linutronix.de>
> Cc: Russell King<linux@arm.linux.org.uk>
> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
> Cc: Rob Herring<robherring2@gmail.com>
> Tested-by: Linus Walleij<linus.walleij@linaro.org>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

What about the clock-node patches?
Do you want those to get merged via sub-arch tree's once this
patch + Thomas's new API gets merged ?

Regards
Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-21  6:29   ` Santosh Shilimkar
@ 2011-05-23  5:18     ` Colin Cross
  -1 siblings, 0 replies; 14+ messages in thread
From: Colin Cross @ 2011-05-23  5:18 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: linux-arm-kernel, Thomas Gleixner, Russell King, Rob Herring, lkml

On Fri, May 20, 2011 at 11:29 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On 5/20/2011 5:54 AM, Colin Cross wrote:
>>
>> The localtimer's clock changes with the cpu clock.  After a
>> cpufreq transition, update the clockevent's frequency and
>> reprogram the next clock event.
>>
>> Adds a clock called "smp_twd" that is used to determine the
>> twd frequency, which can also be used at init time to
>> avoid calibrating the twd frequency.
>>
>> Clock changes are based on Rob Herring's work.
>>
>> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
>> Signed-off-by: Colin Cross<ccross@android.com>
>> Cc: Thomas Gleixner<tglx@linutronix.de>
>> Cc: Russell King<linux@arm.linux.org.uk>
>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>> Cc: Rob Herring<robherring2@gmail.com>
>> Tested-by: Linus Walleij<linus.walleij@linaro.org>
>> ---
>
> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
> What about the clock-node patches?
> Do you want those to get merged via sub-arch tree's once this
> patch + Thomas's new API gets merged ?

The clock-node patches can be merged independently - twd scaling just
won't work until they are both merged.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-23  5:18     ` Colin Cross
  0 siblings, 0 replies; 14+ messages in thread
From: Colin Cross @ 2011-05-23  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, May 20, 2011 at 11:29 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On 5/20/2011 5:54 AM, Colin Cross wrote:
>>
>> The localtimer's clock changes with the cpu clock. ?After a
>> cpufreq transition, update the clockevent's frequency and
>> reprogram the next clock event.
>>
>> Adds a clock called "smp_twd" that is used to determine the
>> twd frequency, which can also be used at init time to
>> avoid calibrating the twd frequency.
>>
>> Clock changes are based on Rob Herring's work.
>>
>> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
>> Signed-off-by: Colin Cross<ccross@android.com>
>> Cc: Thomas Gleixner<tglx@linutronix.de>
>> Cc: Russell King<linux@arm.linux.org.uk>
>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>> Cc: Rob Herring<robherring2@gmail.com>
>> Tested-by: Linus Walleij<linus.walleij@linaro.org>
>> ---
>
> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
> What about the clock-node patches?
> Do you want those to get merged via sub-arch tree's once this
> patch + Thomas's new API gets merged ?

The clock-node patches can be merged independently - twd scaling just
won't work until they are both merged.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-23  5:18     ` Colin Cross
@ 2011-05-23  6:50       ` Santosh Shilimkar
  -1 siblings, 0 replies; 14+ messages in thread
From: Santosh Shilimkar @ 2011-05-23  6:50 UTC (permalink / raw)
  To: Colin Cross
  Cc: linux-arm-kernel, Thomas Gleixner, Russell King, Rob Herring, lkml

On 5/23/2011 10:48 AM, Colin Cross wrote:
> On Fri, May 20, 2011 at 11:29 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com>  wrote:
>> On 5/20/2011 5:54 AM, Colin Cross wrote:
>>>
>>> The localtimer's clock changes with the cpu clock.  After a
>>> cpufreq transition, update the clockevent's frequency and
>>> reprogram the next clock event.
>>>
>>> Adds a clock called "smp_twd" that is used to determine the
>>> twd frequency, which can also be used at init time to
>>> avoid calibrating the twd frequency.
>>>
>>> Clock changes are based on Rob Herring's work.
>>>
>>> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
>>> Signed-off-by: Colin Cross<ccross@android.com>
>>> Cc: Thomas Gleixner<tglx@linutronix.de>
>>> Cc: Russell King<linux@arm.linux.org.uk>
>>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>>> Cc: Rob Herring<robherring2@gmail.com>
>>> Tested-by: Linus Walleij<linus.walleij@linaro.org>
>>> ---
>>
>> Acked-by: Santosh Shilimkar<santosh.shilimkar@ti.com>
>>
>> What about the clock-node patches?
>> Do you want those to get merged via sub-arch tree's once this
>> patch + Thomas's new API gets merged ?
>
> The clock-node patches can be merged independently - twd scaling just
> won't work until they are both merged.
Yep. That should be ok.

Regards
Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-23  6:50       ` Santosh Shilimkar
  0 siblings, 0 replies; 14+ messages in thread
From: Santosh Shilimkar @ 2011-05-23  6:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 5/23/2011 10:48 AM, Colin Cross wrote:
> On Fri, May 20, 2011 at 11:29 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com>  wrote:
>> On 5/20/2011 5:54 AM, Colin Cross wrote:
>>>
>>> The localtimer's clock changes with the cpu clock.  After a
>>> cpufreq transition, update the clockevent's frequency and
>>> reprogram the next clock event.
>>>
>>> Adds a clock called "smp_twd" that is used to determine the
>>> twd frequency, which can also be used at init time to
>>> avoid calibrating the twd frequency.
>>>
>>> Clock changes are based on Rob Herring's work.
>>>
>>> Change-Id: I413b5cd07fb2b79bc9fad8b4bf257332d1da7bcd
>>> Signed-off-by: Colin Cross<ccross@android.com>
>>> Cc: Thomas Gleixner<tglx@linutronix.de>
>>> Cc: Russell King<linux@arm.linux.org.uk>
>>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>>> Cc: Rob Herring<robherring2@gmail.com>
>>> Tested-by: Linus Walleij<linus.walleij@linaro.org>
>>> ---
>>
>> Acked-by: Santosh Shilimkar<santosh.shilimkar@ti.com>
>>
>> What about the clock-node patches?
>> Do you want those to get merged via sub-arch tree's once this
>> patch + Thomas's new API gets merged ?
>
> The clock-node patches can be merged independently - twd scaling just
> won't work until they are both merged.
Yep. That should be ok.

Regards
Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
  2011-05-20  0:24 ` Colin Cross
@ 2011-05-30 12:41   ` Linus Walleij
  -1 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2011-05-30 12:41 UTC (permalink / raw)
  To: Colin Cross
  Cc: linux-arm-kernel, Russell King, linux-kernel, Santosh Shilimkar,
	Thomas Gleixner

2011/5/20 Colin Cross <ccross@android.com>:

> The localtimer's clock changes with the cpu clock.  After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.

Colin can you put this into Russells patch tracker with all the ACKs?

Actually I think this is -rc material since it fixes a real bug for us
atleast, maybe that's just me.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change
@ 2011-05-30 12:41   ` Linus Walleij
  0 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2011-05-30 12:41 UTC (permalink / raw)
  To: linux-arm-kernel

2011/5/20 Colin Cross <ccross@android.com>:

> The localtimer's clock changes with the cpu clock. ?After a
> cpufreq transition, update the clockevent's frequency and
> reprogram the next clock event.

Colin can you put this into Russells patch tracker with all the ACKs?

Actually I think this is -rc material since it fixes a real bug for us
atleast, maybe that's just me.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-05-30 12:41 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-20  0:24 [PATCH v2] ARM: smp_twd: Reconfigure clockevents after cpufreq change Colin Cross
2011-05-20  0:24 ` Colin Cross
2011-05-20 21:50 ` Linus Walleij
2011-05-20 21:50   ` Linus Walleij
2011-05-21  3:33 ` Rob Herring
2011-05-21  3:33   ` Rob Herring
2011-05-21  6:29 ` Santosh Shilimkar
2011-05-21  6:29   ` Santosh Shilimkar
2011-05-23  5:18   ` Colin Cross
2011-05-23  5:18     ` Colin Cross
2011-05-23  6:50     ` Santosh Shilimkar
2011-05-23  6:50       ` Santosh Shilimkar
2011-05-30 12:41 ` Linus Walleij
2011-05-30 12:41   ` Linus Walleij

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.