aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/exynos_mct.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-07-23 17:51:34 -0400
committerOlof Johansson <olof@lixom.net>2013-07-23 19:54:15 -0400
commit47dcd3563e45fc5a59bf7f3326ef56087be8bebe (patch)
tree5cebf3d803be1ad0ac8914332da1472cdc0e2652 /drivers/clocksource/exynos_mct.c
parent3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b (diff)
parent060fd3043e5e3488504b9e70182e188dd9113aea (diff)
Merge tag 'remove-local-timers' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm into next/cleanup
From Stephen Boyd: Now that we have a generic arch hook for broadcast we can remove the local timer API entirely. Doing so will reduce code in ARM core, reduce the architecture dependencies of our timer drivers, and simplify the code because we no longer go through an architecture layer that is essentially a hotplug notifier. * tag 'remove-local-timers' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm: ARM: smp: Remove local timer API clocksource: time-armada-370-xp: Divorce from local timer API clocksource: time-armada-370-xp: Fix sparse warning ARM: msm: Divorce msm_timer from local timer API ARM: PRIMA2: Divorce timer-marco from local timer API ARM: EXYNOS4: Divorce mct from local timer API ARM: OMAP2+: Divorce from local timer API ARM: smp_twd: Divorce smp_twd from local timer API ARM: smp: Remove duplicate dummy timer implementation Resolved a large number of conflicts due to __cpuinit cleanups, etc. Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/clocksource/exynos_mct.c')
-rw-r--r--drivers/clocksource/exynos_mct.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index b2bbc415f120..5b34768f4d7c 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
@@ -405,8 +403,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
405 struct mct_clock_event_device *mevt; 403 struct mct_clock_event_device *mevt;
406 unsigned int cpu = smp_processor_id(); 404 unsigned int cpu = smp_processor_id();
407 405
408 mevt = this_cpu_ptr(&percpu_mct_tick); 406 mevt = container_of(evt, struct mct_clock_event_device, evt);
409 mevt->evt = evt;
410 407
411 mevt->base = EXYNOS4_MCT_L_BASE(cpu); 408 mevt->base = EXYNOS4_MCT_L_BASE(cpu);
412 sprintf(mevt->name, "mct_tick%d", cpu); 409 sprintf(mevt->name, "mct_tick%d", cpu);
@@ -448,14 +445,37 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
448 disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); 445 disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
449} 446}
450 447
451static struct local_timer_ops exynos4_mct_tick_ops = { 448static int exynos4_mct_cpu_notify(struct notifier_block *self,
452 .setup = exynos4_local_timer_setup, 449 unsigned long action, void *hcpu)
453 .stop = exynos4_local_timer_stop, 450{
451 struct mct_clock_event_device *mevt;
452
453 /*
454 * Grab cpu pointer in each case to avoid spurious
455 * preemptible warnings
456 */
457 switch (action & ~CPU_TASKS_FROZEN) {
458 case CPU_STARTING:
459 mevt = this_cpu_ptr(&percpu_mct_tick);
460 exynos4_local_timer_setup(&mevt->evt);
461 break;
462 case CPU_DYING:
463 mevt = this_cpu_ptr(&percpu_mct_tick);
464 exynos4_local_timer_stop(&mevt->evt);
465 break;
466 }
467
468 return NOTIFY_OK;
469}
470
471static struct notifier_block exynos4_mct_cpu_nb = {
472 .notifier_call = exynos4_mct_cpu_notify,
454}; 473};
455#endif /* CONFIG_LOCAL_TIMERS */
456 474
457static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) 475static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
458{ 476{
477 int err;
478 struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
459 struct clk *mct_clk, *tick_clk; 479 struct clk *mct_clk, *tick_clk;
460 480
461 tick_clk = np ? of_clk_get_by_name(np, "fin_pll") : 481 tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
@@ -473,9 +493,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
473 if (!reg_base) 493 if (!reg_base)
474 panic("%s: unable to ioremap mct address space\n", __func__); 494 panic("%s: unable to ioremap mct address space\n", __func__);
475 495
476#ifdef CONFIG_LOCAL_TIMERS
477 if (mct_int_type == MCT_INT_PPI) { 496 if (mct_int_type == MCT_INT_PPI) {
478 int err;
479 497
480 err = request_percpu_irq(mct_irqs[MCT_L0_IRQ], 498 err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
481 exynos4_mct_tick_isr, "MCT", 499 exynos4_mct_tick_isr, "MCT",
@@ -484,8 +502,16 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
484 mct_irqs[MCT_L0_IRQ], err); 502 mct_irqs[MCT_L0_IRQ], err);
485 } 503 }
486 504
487 local_timer_register(&exynos4_mct_tick_ops); 505 err = register_cpu_notifier(&exynos4_mct_cpu_nb);
488#endif /* CONFIG_LOCAL_TIMERS */ 506 if (err)
507 goto out_irq;
508
509 /* Immediately configure the timer on the boot CPU */
510 exynos4_local_timer_setup(&mevt->evt);
511 return;
512
513out_irq:
514 free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
489} 515}
490 516
491void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1) 517void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1)