aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2013-02-15 19:02:20 -0500
committerStephen Boyd <sboyd@codeaurora.org>2013-06-24 20:45:58 -0400
commita894fcc2d01a89e6fe3da0845a4d80a5312e1124 (patch)
tree90029c9dacd4b5f53583b09d516480cb138fb364 /arch/arm
parent3d53ceeca7bae807e5aba0935347f3757127a821 (diff)
ARM: smp_twd: Divorce smp_twd from local timer API
Separate the smp_twd timers from the local timer API. This will allow us to remove ARM local timer support in the near future and gets us closer to moving this driver to drivers/clocksource. Tested-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Tony Lindgren <tony@atomide.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/kernel/smp_twd.c64
-rw-r--r--arch/arm/mach-highbank/Kconfig2
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-omap2/Kconfig2
-rw-r--r--arch/arm/mach-realview/Kconfig8
-rw-r--r--arch/arm/mach-spear/Kconfig2
-rw-r--r--arch/arm/mach-tegra/Kconfig2
-rw-r--r--arch/arm/mach-ux500/Kconfig2
-rw-r--r--arch/arm/mach-vexpress/Kconfig2
-rw-r--r--arch/arm/mach-zynq/Kconfig2
11 files changed, 56 insertions, 34 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 53d3a356f61f..374a1d8900ec 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -638,7 +638,7 @@ config ARCH_SHMOBILE
638 select CLKDEV_LOOKUP 638 select CLKDEV_LOOKUP
639 select GENERIC_CLOCKEVENTS 639 select GENERIC_CLOCKEVENTS
640 select HAVE_ARM_SCU if SMP 640 select HAVE_ARM_SCU if SMP
641 select HAVE_ARM_TWD if LOCAL_TIMERS 641 select HAVE_ARM_TWD if SMP
642 select HAVE_CLK 642 select HAVE_CLK
643 select HAVE_MACH_CLKDEV 643 select HAVE_MACH_CLKDEV
644 select HAVE_SMP 644 select HAVE_SMP
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 90525d9d290b..aac1495b44de 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/cpu.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/device.h> 16#include <linux/device.h>
16#include <linux/err.h> 17#include <linux/err.h>
@@ -24,7 +25,6 @@
24 25
25#include <asm/smp_plat.h> 26#include <asm/smp_plat.h>
26#include <asm/smp_twd.h> 27#include <asm/smp_twd.h>
27#include <asm/localtimer.h>
28 28
29/* set up by the platform code */ 29/* set up by the platform code */
30static void __iomem *twd_base; 30static void __iomem *twd_base;
@@ -33,7 +33,7 @@ static struct clk *twd_clk;
33static unsigned long twd_timer_rate; 33static unsigned long twd_timer_rate;
34static DEFINE_PER_CPU(bool, percpu_setup_called); 34static DEFINE_PER_CPU(bool, percpu_setup_called);
35 35
36static struct clock_event_device __percpu **twd_evt; 36static struct clock_event_device __percpu *twd_evt;
37static int twd_ppi; 37static int twd_ppi;
38 38
39static void twd_set_mode(enum clock_event_mode mode, 39static void twd_set_mode(enum clock_event_mode mode,
@@ -90,8 +90,10 @@ static int twd_timer_ack(void)
90 return 0; 90 return 0;
91} 91}
92 92
93static void twd_timer_stop(struct clock_event_device *clk) 93static void twd_timer_stop(void)
94{ 94{
95 struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
96
95 twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); 97 twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
96 disable_percpu_irq(clk->irq); 98 disable_percpu_irq(clk->irq);
97} 99}
@@ -106,7 +108,7 @@ static void twd_update_frequency(void *new_rate)
106{ 108{
107 twd_timer_rate = *((unsigned long *) new_rate); 109 twd_timer_rate = *((unsigned long *) new_rate);
108 110
109 clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); 111 clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
110} 112}
111 113
112static int twd_rate_change(struct notifier_block *nb, 114static int twd_rate_change(struct notifier_block *nb,
@@ -132,7 +134,7 @@ static struct notifier_block twd_clk_nb = {
132 134
133static int twd_clk_init(void) 135static int twd_clk_init(void)
134{ 136{
135 if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) 137 if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
136 return clk_notifier_register(twd_clk, &twd_clk_nb); 138 return clk_notifier_register(twd_clk, &twd_clk_nb);
137 139
138 return 0; 140 return 0;
@@ -151,7 +153,7 @@ static void twd_update_frequency(void *data)
151{ 153{
152 twd_timer_rate = clk_get_rate(twd_clk); 154 twd_timer_rate = clk_get_rate(twd_clk);
153 155
154 clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); 156 clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
155} 157}
156 158
157static int twd_cpufreq_transition(struct notifier_block *nb, 159static int twd_cpufreq_transition(struct notifier_block *nb,
@@ -177,7 +179,7 @@ static struct notifier_block twd_cpufreq_nb = {
177 179
178static int twd_cpufreq_init(void) 180static int twd_cpufreq_init(void)
179{ 181{
180 if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) 182 if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
181 return cpufreq_register_notifier(&twd_cpufreq_nb, 183 return cpufreq_register_notifier(&twd_cpufreq_nb,
182 CPUFREQ_TRANSITION_NOTIFIER); 184 CPUFREQ_TRANSITION_NOTIFIER);
183 185
@@ -228,7 +230,7 @@ static void __cpuinit twd_calibrate_rate(void)
228 230
229static irqreturn_t twd_handler(int irq, void *dev_id) 231static irqreturn_t twd_handler(int irq, void *dev_id)
230{ 232{
231 struct clock_event_device *evt = *(struct clock_event_device **)dev_id; 233 struct clock_event_device *evt = dev_id;
232 234
233 if (twd_timer_ack()) { 235 if (twd_timer_ack()) {
234 evt->event_handler(evt); 236 evt->event_handler(evt);
@@ -265,9 +267,9 @@ static void twd_get_clock(struct device_node *np)
265/* 267/*
266 * Setup the local clock events for a CPU. 268 * Setup the local clock events for a CPU.
267 */ 269 */
268static int __cpuinit twd_timer_setup(struct clock_event_device *clk) 270static void __cpuinit twd_timer_setup(void)
269{ 271{
270 struct clock_event_device **this_cpu_clk; 272 struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
271 int cpu = smp_processor_id(); 273 int cpu = smp_processor_id();
272 274
273 /* 275 /*
@@ -276,9 +278,9 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
276 */ 278 */
277 if (per_cpu(percpu_setup_called, cpu)) { 279 if (per_cpu(percpu_setup_called, cpu)) {
278 __raw_writel(0, twd_base + TWD_TIMER_CONTROL); 280 __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
279 clockevents_register_device(*__this_cpu_ptr(twd_evt)); 281 clockevents_register_device(clk);
280 enable_percpu_irq(clk->irq, 0); 282 enable_percpu_irq(clk->irq, 0);
281 return 0; 283 return;
282 } 284 }
283 per_cpu(percpu_setup_called, cpu) = true; 285 per_cpu(percpu_setup_called, cpu) = true;
284 286
@@ -297,27 +299,37 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
297 clk->set_mode = twd_set_mode; 299 clk->set_mode = twd_set_mode;
298 clk->set_next_event = twd_set_next_event; 300 clk->set_next_event = twd_set_next_event;
299 clk->irq = twd_ppi; 301 clk->irq = twd_ppi;
300 302 clk->cpumask = cpumask_of(cpu);
301 this_cpu_clk = __this_cpu_ptr(twd_evt);
302 *this_cpu_clk = clk;
303 303
304 clockevents_config_and_register(clk, twd_timer_rate, 304 clockevents_config_and_register(clk, twd_timer_rate,
305 0xf, 0xffffffff); 305 0xf, 0xffffffff);
306 enable_percpu_irq(clk->irq, 0); 306 enable_percpu_irq(clk->irq, 0);
307}
307 308
308 return 0; 309static int __cpuinit twd_timer_cpu_notify(struct notifier_block *self,
310 unsigned long action, void *hcpu)
311{
312 switch (action & ~CPU_TASKS_FROZEN) {
313 case CPU_STARTING:
314 twd_timer_setup();
315 break;
316 case CPU_DYING:
317 twd_timer_stop();
318 break;
319 }
320
321 return NOTIFY_OK;
309} 322}
310 323
311static struct local_timer_ops twd_lt_ops __cpuinitdata = { 324static struct notifier_block twd_timer_cpu_nb __cpuinitdata = {
312 .setup = twd_timer_setup, 325 .notifier_call = twd_timer_cpu_notify,
313 .stop = twd_timer_stop,
314}; 326};
315 327
316static int __init twd_local_timer_common_register(struct device_node *np) 328static int __init twd_local_timer_common_register(struct device_node *np)
317{ 329{
318 int err; 330 int err;
319 331
320 twd_evt = alloc_percpu(struct clock_event_device *); 332 twd_evt = alloc_percpu(struct clock_event_device);
321 if (!twd_evt) { 333 if (!twd_evt) {
322 err = -ENOMEM; 334 err = -ENOMEM;
323 goto out_free; 335 goto out_free;
@@ -329,12 +341,22 @@ static int __init twd_local_timer_common_register(struct device_node *np)
329 goto out_free; 341 goto out_free;
330 } 342 }
331 343
332 err = local_timer_register(&twd_lt_ops); 344 err = register_cpu_notifier(&twd_timer_cpu_nb);
333 if (err) 345 if (err)
334 goto out_irq; 346 goto out_irq;
335 347
336 twd_get_clock(np); 348 twd_get_clock(np);
337 349
350 /*
351 * Immediately configure the timer on the boot CPU, unless we need
352 * jiffies to be incrementing to calibrate the rate in which case
353 * setup the timer in late_time_init.
354 */
355 if (twd_timer_rate)
356 twd_timer_setup();
357 else
358 late_time_init = twd_timer_setup;
359
338 return 0; 360 return 0;
339 361
340out_irq: 362out_irq:
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index cd9fcb1cd7ab..6acbdabf6222 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -12,7 +12,7 @@ config ARCH_HIGHBANK
12 select CPU_V7 12 select CPU_V7
13 select GENERIC_CLOCKEVENTS 13 select GENERIC_CLOCKEVENTS
14 select HAVE_ARM_SCU 14 select HAVE_ARM_SCU
15 select HAVE_ARM_TWD if LOCAL_TIMERS 15 select HAVE_ARM_TWD if SMP
16 select HAVE_SMP 16 select HAVE_SMP
17 select MAILBOX 17 select MAILBOX
18 select PL320_MBOX 18 select PL320_MBOX
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ba44328464f3..c8adc79028b8 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -798,7 +798,7 @@ config SOC_IMX6Q
798 select COMMON_CLK 798 select COMMON_CLK
799 select CPU_V7 799 select CPU_V7
800 select HAVE_ARM_SCU if SMP 800 select HAVE_ARM_SCU if SMP
801 select HAVE_ARM_TWD if LOCAL_TIMERS 801 select HAVE_ARM_TWD if SMP
802 select HAVE_CAN_FLEXCAN if CAN 802 select HAVE_CAN_FLEXCAN if CAN
803 select HAVE_IMX_ANATOP 803 select HAVE_IMX_ANATOP
804 select HAVE_IMX_GPC 804 select HAVE_IMX_GPC
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index f49cd51e162a..edb950a1af05 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -90,7 +90,7 @@ config ARCH_OMAP4
90 select CACHE_L2X0 90 select CACHE_L2X0
91 select CPU_V7 91 select CPU_V7
92 select HAVE_ARM_SCU if SMP 92 select HAVE_ARM_SCU if SMP
93 select HAVE_ARM_TWD if LOCAL_TIMERS 93 select HAVE_ARM_TWD if SMP
94 select HAVE_SMP 94 select HAVE_SMP
95 select LOCAL_TIMERS if SMP 95 select LOCAL_TIMERS if SMP
96 select OMAP_INTERCONNECT 96 select OMAP_INTERCONNECT
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index d210c0f9c2c4..9db2029aa632 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -13,7 +13,7 @@ config REALVIEW_EB_A9MP
13 depends on MACH_REALVIEW_EB 13 depends on MACH_REALVIEW_EB
14 select CPU_V7 14 select CPU_V7
15 select HAVE_ARM_SCU if SMP 15 select HAVE_ARM_SCU if SMP
16 select HAVE_ARM_TWD if LOCAL_TIMERS 16 select HAVE_ARM_TWD if SMP
17 select HAVE_SMP 17 select HAVE_SMP
18 select MIGHT_HAVE_CACHE_L2X0 18 select MIGHT_HAVE_CACHE_L2X0
19 help 19 help
@@ -26,7 +26,7 @@ config REALVIEW_EB_ARM11MP
26 select ARCH_HAS_BARRIERS if SMP 26 select ARCH_HAS_BARRIERS if SMP
27 select CPU_V6K 27 select CPU_V6K
28 select HAVE_ARM_SCU if SMP 28 select HAVE_ARM_SCU if SMP
29 select HAVE_ARM_TWD if LOCAL_TIMERS 29 select HAVE_ARM_TWD if SMP
30 select HAVE_SMP 30 select HAVE_SMP
31 select MIGHT_HAVE_CACHE_L2X0 31 select MIGHT_HAVE_CACHE_L2X0
32 help 32 help
@@ -48,7 +48,7 @@ config MACH_REALVIEW_PB11MP
48 select ARM_GIC 48 select ARM_GIC
49 select CPU_V6K 49 select CPU_V6K
50 select HAVE_ARM_SCU if SMP 50 select HAVE_ARM_SCU if SMP
51 select HAVE_ARM_TWD if LOCAL_TIMERS 51 select HAVE_ARM_TWD if SMP
52 select HAVE_PATA_PLATFORM 52 select HAVE_PATA_PLATFORM
53 select HAVE_SMP 53 select HAVE_SMP
54 select MIGHT_HAVE_CACHE_L2X0 54 select MIGHT_HAVE_CACHE_L2X0
@@ -92,7 +92,7 @@ config MACH_REALVIEW_PBX
92 select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET 92 select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
93 select ARM_GIC 93 select ARM_GIC
94 select HAVE_ARM_SCU if SMP 94 select HAVE_ARM_SCU if SMP
95 select HAVE_ARM_TWD if LOCAL_TIMERS 95 select HAVE_ARM_TWD if SMP
96 select HAVE_PATA_PLATFORM 96 select HAVE_PATA_PLATFORM
97 select HAVE_SMP 97 select HAVE_SMP
98 select MIGHT_HAVE_CACHE_L2X0 98 select MIGHT_HAVE_CACHE_L2X0
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index 442917eedff3..df0d59afeb40 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -23,7 +23,7 @@ config ARCH_SPEAR13XX
23 select CPU_V7 23 select CPU_V7
24 select GPIO_SPEAR_SPICS 24 select GPIO_SPEAR_SPICS
25 select HAVE_ARM_SCU if SMP 25 select HAVE_ARM_SCU if SMP
26 select HAVE_ARM_TWD if LOCAL_TIMERS 26 select HAVE_ARM_TWD if SMP
27 select HAVE_SMP 27 select HAVE_SMP
28 select MIGHT_HAVE_CACHE_L2X0 28 select MIGHT_HAVE_CACHE_L2X0
29 select PINCTRL 29 select PINCTRL
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 84d72fc36dfe..1f3ea1f6cedf 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -8,7 +8,7 @@ config ARCH_TEGRA
8 select COMMON_CLK 8 select COMMON_CLK
9 select GENERIC_CLOCKEVENTS 9 select GENERIC_CLOCKEVENTS
10 select HAVE_ARM_SCU if SMP 10 select HAVE_ARM_SCU if SMP
11 select HAVE_ARM_TWD if LOCAL_TIMERS 11 select HAVE_ARM_TWD if SMP
12 select HAVE_CLK 12 select HAVE_CLK
13 select HAVE_SMP 13 select HAVE_SMP
14 select MIGHT_HAVE_CACHE_L2X0 14 select MIGHT_HAVE_CACHE_L2X0
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 6a4387e39df8..0614ee2b0523 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -8,7 +8,7 @@ config ARCH_U8500
8 select CPU_V7 8 select CPU_V7
9 select GENERIC_CLOCKEVENTS 9 select GENERIC_CLOCKEVENTS
10 select HAVE_ARM_SCU if SMP 10 select HAVE_ARM_SCU if SMP
11 select HAVE_ARM_TWD if LOCAL_TIMERS 11 select HAVE_ARM_TWD if SMP
12 select HAVE_SMP 12 select HAVE_SMP
13 select MIGHT_HAVE_CACHE_L2X0 13 select MIGHT_HAVE_CACHE_L2X0
14 help 14 help
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 5907e10c37fd..5bfdd73dea19 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -10,7 +10,7 @@ config ARCH_VEXPRESS
10 select CPU_V7 10 select CPU_V7
11 select GENERIC_CLOCKEVENTS 11 select GENERIC_CLOCKEVENTS
12 select HAVE_ARM_SCU if SMP 12 select HAVE_ARM_SCU if SMP
13 select HAVE_ARM_TWD if LOCAL_TIMERS 13 select HAVE_ARM_TWD if SMP
14 select HAVE_CLK 14 select HAVE_CLK
15 select HAVE_PATA_PLATFORM 15 select HAVE_PATA_PLATFORM
16 select HAVE_SMP 16 select HAVE_SMP
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index c1d61f281e68..04f8a4a6e755 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -6,7 +6,7 @@ config ARCH_ZYNQ
6 select CPU_V7 6 select CPU_V7
7 select GENERIC_CLOCKEVENTS 7 select GENERIC_CLOCKEVENTS
8 select HAVE_ARM_SCU if SMP 8 select HAVE_ARM_SCU if SMP
9 select HAVE_ARM_TWD if LOCAL_TIMERS 9 select HAVE_ARM_TWD if SMP
10 select ICST 10 select ICST
11 select MIGHT_HAVE_CACHE_L2X0 11 select MIGHT_HAVE_CACHE_L2X0
12 select USE_OF 12 select USE_OF