diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2011-11-02 22:13:12 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-11-06 00:53:15 -0400 |
commit | e700e41d9abfbf9fee01e979a41b185695132c19 (patch) | |
tree | 4809ee5a48e006d3ec7f6bf0d284be99de29dd34 /arch | |
parent | d8633c1da161de7e0b880d919d305a97c01372f4 (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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-exynos4/mct.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c index f191608b28d..97343df8f13 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 | ||
47 | struct mct_clock_event_device mct_tick[NR_CPUS]; | 47 | static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); |
48 | 48 | ||
49 | static void exynos4_mct_write(unsigned int value, void *addr) | 49 | static void exynos4_mct_write(unsigned int value, void *addr) |
50 | { | 50 | { |
@@ -302,7 +302,7 @@ static void exynos4_mct_tick_start(unsigned long cycles, | |||
302 | static int exynos4_tick_set_next_event(unsigned long cycles, | 302 | static 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, | |||
312 | static inline void exynos4_tick_set_mode(enum clock_event_mode mode, | 312 | static 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 | ||
377 | static void exynos4_mct_tick_init(struct clock_event_device *evt) | 377 | static 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) | |||
427 | void local_timer_stop(struct clock_event_device *evt) | 429 | void 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 | ||
435 | static void __init exynos4_timer_resources(void) | 439 | static 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 | ||
443 | static void __init exynos4_timer_init(void) | 457 | static void __init exynos4_timer_init(void) |