aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2013-02-15 19:40:51 -0500
committerStephen Boyd <sboyd@codeaurora.org>2013-06-24 20:45:58 -0400
commitee98d27df6827b5ba4bd99cb7d5cb1239b6a1a31 (patch)
tree400f565134a602122fabf70d99e7dae87a7c35c6 /drivers/clocksource
parentef3160cd2f0a400751f2cf6fd2811225fee1d5a7 (diff)
ARM: EXYNOS4: Divorce mct from local timer API
Separate the mct local 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. Acked-by: Kukjin Kim <kgene.kim@samsung.com> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Cc: Thomas Abraham <thomas.abraham@linaro.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/exynos_mct.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 662fcc065821..1c3f5a652044 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -16,6 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/clockchips.h> 18#include <linux/clockchips.h>
19#include <linux/cpu.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
21#include <linux/percpu.h> 22#include <linux/percpu.h>
@@ -24,7 +25,6 @@
24#include <linux/of_address.h> 25#include <linux/of_address.h>
25#include <linux/clocksource.h> 26#include <linux/clocksource.h>
26 27
27#include <asm/localtimer.h>
28#include <asm/mach/time.h> 28#include <asm/mach/time.h>
29 29
30#define EXYNOS4_MCTREG(x) (x) 30#define EXYNOS4_MCTREG(x) (x)
@@ -80,7 +80,7 @@ static unsigned int mct_int_type;
80static int mct_irqs[MCT_NR_IRQS]; 80static int mct_irqs[MCT_NR_IRQS];
81 81
82struct mct_clock_event_device { 82struct mct_clock_event_device {
83 struct clock_event_device *evt; 83 struct clock_event_device evt;
84 unsigned long base; 84 unsigned long base;
85 char name[10]; 85 char name[10];
86}; 86};
@@ -295,8 +295,6 @@ static void exynos4_clockevent_init(void)
295 setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq); 295 setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
296} 296}
297 297
298#ifdef CONFIG_LOCAL_TIMERS
299
300static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); 298static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
301 299
302/* Clock event handling */ 300/* Clock event handling */
@@ -369,7 +367,7 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
369 367
370static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) 368static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
371{ 369{
372 struct clock_event_device *evt = mevt->evt; 370 struct clock_event_device *evt = &mevt->evt;
373 371
374 /* 372 /*
375 * This is for supporting oneshot mode. 373 * This is for supporting oneshot mode.
@@ -391,7 +389,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
391static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) 389static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
392{ 390{
393 struct mct_clock_event_device *mevt = dev_id; 391 struct mct_clock_event_device *mevt = dev_id;
394 struct clock_event_device *evt = mevt->evt; 392 struct clock_event_device *evt = &mevt->evt;
395 393
396 exynos4_mct_tick_clear(mevt); 394 exynos4_mct_tick_clear(mevt);
397 395
@@ -417,8 +415,7 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
417 struct mct_clock_event_device *mevt; 415 struct mct_clock_event_device *mevt;
418 unsigned int cpu = smp_processor_id(); 416 unsigned int cpu = smp_processor_id();
419 417
420 mevt = this_cpu_ptr(&percpu_mct_tick); 418 mevt = container_of(evt, struct mct_clock_event_device, evt);
421 mevt->evt = evt;
422 419
423 mevt->base = EXYNOS4_MCT_L_BASE(cpu); 420 mevt->base = EXYNOS4_MCT_L_BASE(cpu);
424 sprintf(mevt->name, "mct_tick%d", cpu); 421 sprintf(mevt->name, "mct_tick%d", cpu);
@@ -452,7 +449,7 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
452 return 0; 449 return 0;
453} 450}
454 451
455static void exynos4_local_timer_stop(struct clock_event_device *evt) 452static void __cpuinit exynos4_local_timer_stop(struct clock_event_device *evt)
456{ 453{
457 unsigned int cpu = smp_processor_id(); 454 unsigned int cpu = smp_processor_id();
458 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); 455 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
@@ -465,14 +462,37 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
465 disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); 462 disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
466} 463}
467 464
468static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { 465static int __cpuinit exynos4_mct_cpu_notify(struct notifier_block *self,
469 .setup = exynos4_local_timer_setup, 466 unsigned long action, void *hcpu)
470 .stop = exynos4_local_timer_stop, 467{
468 struct mct_clock_event_device *mevt;
469
470 /*
471 * Grab cpu pointer in each case to avoid spurious
472 * preemptible warnings
473 */
474 switch (action & ~CPU_TASKS_FROZEN) {
475 case CPU_STARTING:
476 mevt = this_cpu_ptr(&percpu_mct_tick);
477 exynos4_local_timer_setup(&mevt->evt);
478 break;
479 case CPU_DYING:
480 mevt = this_cpu_ptr(&percpu_mct_tick);
481 exynos4_local_timer_stop(&mevt->evt);
482 break;
483 }
484
485 return NOTIFY_OK;
486}
487
488static struct notifier_block exynos4_mct_cpu_nb __cpuinitdata = {
489 .notifier_call = exynos4_mct_cpu_notify,
471}; 490};
472#endif /* CONFIG_LOCAL_TIMERS */
473 491
474static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) 492static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
475{ 493{
494 int err;
495 struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
476 struct clk *mct_clk, *tick_clk; 496 struct clk *mct_clk, *tick_clk;
477 497
478 tick_clk = np ? of_clk_get_by_name(np, "fin_pll") : 498 tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
@@ -490,9 +510,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
490 if (!reg_base) 510 if (!reg_base)
491 panic("%s: unable to ioremap mct address space\n", __func__); 511 panic("%s: unable to ioremap mct address space\n", __func__);
492 512
493#ifdef CONFIG_LOCAL_TIMERS
494 if (mct_int_type == MCT_INT_PPI) { 513 if (mct_int_type == MCT_INT_PPI) {
495 int err;
496 514
497 err = request_percpu_irq(mct_irqs[MCT_L0_IRQ], 515 err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
498 exynos4_mct_tick_isr, "MCT", 516 exynos4_mct_tick_isr, "MCT",
@@ -501,8 +519,16 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
501 mct_irqs[MCT_L0_IRQ], err); 519 mct_irqs[MCT_L0_IRQ], err);
502 } 520 }
503 521
504 local_timer_register(&exynos4_mct_tick_ops); 522 err = register_cpu_notifier(&exynos4_mct_cpu_nb);
505#endif /* CONFIG_LOCAL_TIMERS */ 523 if (err)
524 goto out_irq;
525
526 /* Immediately configure the timer on the boot CPU */
527 exynos4_local_timer_setup(&mevt->evt);
528 return;
529
530out_irq:
531 free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
506} 532}
507 533
508void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1) 534void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1)