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 | |
| 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>
| -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 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 | ||
| 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) |
