aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2011-11-02 22:13:12 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-11-06 00:53:15 -0400
commite700e41d9abfbf9fee01e979a41b185695132c19 (patch)
tree4809ee5a48e006d3ec7f6bf0d284be99de29dd34
parentd8633c1da161de7e0b880d919d305a97c01372f4 (diff)
ARM: EXYNOS4: convert MCT to percpu interrupt API
MCT recently gained per cpu interrupts, and missed the fact that ARM has moved to a genirq based implementation. This patch converts the driver to the new API. Boot tested on Origen. Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
-rw-r--r--arch/arm/mach-exynos4/mct.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index f191608b28d6..97343df8f132 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -44,7 +44,7 @@ struct mct_clock_event_device {
44 char name[10]; 44 char name[10];
45}; 45};
46 46
47struct mct_clock_event_device mct_tick[NR_CPUS]; 47static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
48 48
49static void exynos4_mct_write(unsigned int value, void *addr) 49static void exynos4_mct_write(unsigned int value, void *addr)
50{ 50{
@@ -302,7 +302,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
302static int exynos4_tick_set_next_event(unsigned long cycles, 302static int exynos4_tick_set_next_event(unsigned long cycles,
303 struct clock_event_device *evt) 303 struct clock_event_device *evt)
304{ 304{
305 struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; 305 struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
306 306
307 exynos4_mct_tick_start(cycles, mevt); 307 exynos4_mct_tick_start(cycles, mevt);
308 308
@@ -312,7 +312,7 @@ static int exynos4_tick_set_next_event(unsigned long cycles,
312static inline void exynos4_tick_set_mode(enum clock_event_mode mode, 312static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
313 struct clock_event_device *evt) 313 struct clock_event_device *evt)
314{ 314{
315 struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; 315 struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
316 316
317 exynos4_mct_tick_stop(mevt); 317 exynos4_mct_tick_stop(mevt);
318 318
@@ -376,14 +376,16 @@ static struct irqaction mct_tick1_event_irq = {
376 376
377static void exynos4_mct_tick_init(struct clock_event_device *evt) 377static void exynos4_mct_tick_init(struct clock_event_device *evt)
378{ 378{
379 struct mct_clock_event_device *mevt;
379 unsigned int cpu = smp_processor_id(); 380 unsigned int cpu = smp_processor_id();
380 381
381 mct_tick[cpu].evt = evt; 382 mevt = this_cpu_ptr(&percpu_mct_tick);
383 mevt->evt = evt;
382 384
383 mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu); 385 mevt->base = EXYNOS4_MCT_L_BASE(cpu);
384 sprintf(mct_tick[cpu].name, "mct_tick%d", cpu); 386 sprintf(mevt->name, "mct_tick%d", cpu);
385 387
386 evt->name = mct_tick[cpu].name; 388 evt->name = mevt->name;
387 evt->cpumask = cpumask_of(cpu); 389 evt->cpumask = cpumask_of(cpu);
388 evt->set_next_event = exynos4_tick_set_next_event; 390 evt->set_next_event = exynos4_tick_set_next_event;
389 evt->set_mode = exynos4_tick_set_mode; 391 evt->set_mode = exynos4_tick_set_mode;
@@ -398,21 +400,21 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
398 400
399 clockevents_register_device(evt); 401 clockevents_register_device(evt);
400 402
401 exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET); 403 exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET);
402 404
403 if (mct_int_type == MCT_INT_SPI) { 405 if (mct_int_type == MCT_INT_SPI) {
404 if (cpu == 0) { 406 if (cpu == 0) {
405 mct_tick0_event_irq.dev_id = &mct_tick[cpu]; 407 mct_tick0_event_irq.dev_id = mevt;
406 evt->irq = IRQ_MCT_L0; 408 evt->irq = IRQ_MCT_L0;
407 setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); 409 setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
408 } else { 410 } else {
409 mct_tick1_event_irq.dev_id = &mct_tick[cpu]; 411 mct_tick1_event_irq.dev_id = mevt;
410 evt->irq = IRQ_MCT_L1; 412 evt->irq = IRQ_MCT_L1;
411 setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); 413 setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
412 irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); 414 irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
413 } 415 }
414 } else { 416 } else {
415 gic_enable_ppi(IRQ_MCT_LOCALTIMER); 417 enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
416 } 418 }
417} 419}
418 420
@@ -427,9 +429,11 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
427void local_timer_stop(struct clock_event_device *evt) 429void local_timer_stop(struct clock_event_device *evt)
428{ 430{
429 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); 431 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
430 disable_irq(evt->irq); 432 if (mct_int_type == MCT_INT_SPI)
433 disable_irq(evt->irq);
434 else
435 disable_percpu_irq(IRQ_MCT_LOCALTIMER);
431} 436}
432
433#endif /* CONFIG_LOCAL_TIMERS */ 437#endif /* CONFIG_LOCAL_TIMERS */
434 438
435static void __init exynos4_timer_resources(void) 439static void __init exynos4_timer_resources(void)
@@ -438,6 +442,16 @@ static void __init exynos4_timer_resources(void)
438 mct_clk = clk_get(NULL, "xtal"); 442 mct_clk = clk_get(NULL, "xtal");
439 443
440 clk_rate = clk_get_rate(mct_clk); 444 clk_rate = clk_get_rate(mct_clk);
445
446 if (mct_int_type == MCT_INT_PPI) {
447 int err;
448
449 err = request_percpu_irq(IRQ_MCT_LOCALTIMER,
450 exynos4_mct_tick_isr, "MCT",
451 &percpu_mct_tick);
452 WARN(err, "MCT: can't request IRQ %d (%d)\n",
453 IRQ_MCT_LOCALTIMER, err);
454 }
441} 455}
442 456
443static void __init exynos4_timer_init(void) 457static void __init exynos4_timer_init(void)