diff options
Diffstat (limited to 'arch/arm/mach-exynos4/mct.c')
-rw-r--r-- | arch/arm/mach-exynos4/mct.c | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c index ddd86864fb83..f43f3faa6495 100644 --- a/arch/arm/mach-exynos4/mct.c +++ b/arch/arm/mach-exynos4/mct.c | |||
@@ -20,12 +20,23 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | 22 | ||
23 | #include <asm/hardware/gic.h> | ||
24 | |||
25 | #include <plat/cpu.h> | ||
26 | |||
23 | #include <mach/map.h> | 27 | #include <mach/map.h> |
28 | #include <mach/irqs.h> | ||
24 | #include <mach/regs-mct.h> | 29 | #include <mach/regs-mct.h> |
25 | #include <asm/mach/time.h> | 30 | #include <asm/mach/time.h> |
26 | 31 | ||
32 | enum { | ||
33 | MCT_INT_SPI, | ||
34 | MCT_INT_PPI | ||
35 | }; | ||
36 | |||
27 | static unsigned long clk_cnt_per_tick; | 37 | static unsigned long clk_cnt_per_tick; |
28 | static unsigned long clk_rate; | 38 | static unsigned long clk_rate; |
39 | static unsigned int mct_int_type; | ||
29 | 40 | ||
30 | struct mct_clock_event_device { | 41 | struct mct_clock_event_device { |
31 | struct clock_event_device *evt; | 42 | struct clock_event_device *evt; |
@@ -321,9 +332,8 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode, | |||
321 | } | 332 | } |
322 | } | 333 | } |
323 | 334 | ||
324 | static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) | 335 | static inline int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) |
325 | { | 336 | { |
326 | struct mct_clock_event_device *mevt = dev_id; | ||
327 | struct clock_event_device *evt = mevt->evt; | 337 | struct clock_event_device *evt = mevt->evt; |
328 | 338 | ||
329 | /* | 339 | /* |
@@ -335,7 +345,20 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) | |||
335 | exynos4_mct_tick_stop(mevt); | 345 | exynos4_mct_tick_stop(mevt); |
336 | 346 | ||
337 | /* Clear the MCT tick interrupt */ | 347 | /* Clear the MCT tick interrupt */ |
338 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); | 348 | if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { |
349 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); | ||
350 | return 1; | ||
351 | } else { | ||
352 | return 0; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) | ||
357 | { | ||
358 | struct mct_clock_event_device *mevt = dev_id; | ||
359 | struct clock_event_device *evt = mevt->evt; | ||
360 | |||
361 | exynos4_mct_tick_clear(mevt); | ||
339 | 362 | ||
340 | evt->event_handler(evt); | 363 | evt->event_handler(evt); |
341 | 364 | ||
@@ -384,13 +407,17 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
384 | 407 | ||
385 | exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET); | 408 | exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET); |
386 | 409 | ||
387 | if (cpu == 0) { | 410 | if (mct_int_type == MCT_INT_SPI) { |
388 | mct_tick0_event_irq.dev_id = &mct_tick[cpu]; | 411 | if (cpu == 0) { |
389 | setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); | 412 | mct_tick0_event_irq.dev_id = &mct_tick[cpu]; |
413 | setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); | ||
414 | } else { | ||
415 | mct_tick1_event_irq.dev_id = &mct_tick[cpu]; | ||
416 | setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); | ||
417 | irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); | ||
418 | } | ||
390 | } else { | 419 | } else { |
391 | mct_tick1_event_irq.dev_id = &mct_tick[cpu]; | 420 | gic_enable_ppi(IRQ_MCT_LOCALTIMER); |
392 | setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); | ||
393 | irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); | ||
394 | } | 421 | } |
395 | } | 422 | } |
396 | 423 | ||
@@ -404,7 +431,10 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt) | |||
404 | 431 | ||
405 | int local_timer_ack(void) | 432 | int local_timer_ack(void) |
406 | { | 433 | { |
407 | return 0; | 434 | unsigned int cpu = smp_processor_id(); |
435 | struct mct_clock_event_device *mevt = &mct_tick[cpu]; | ||
436 | |||
437 | return exynos4_mct_tick_clear(mevt); | ||
408 | } | 438 | } |
409 | 439 | ||
410 | #endif /* CONFIG_LOCAL_TIMERS */ | 440 | #endif /* CONFIG_LOCAL_TIMERS */ |
@@ -419,6 +449,11 @@ static void __init exynos4_timer_resources(void) | |||
419 | 449 | ||
420 | static void __init exynos4_timer_init(void) | 450 | static void __init exynos4_timer_init(void) |
421 | { | 451 | { |
452 | if (soc_is_exynos4210()) | ||
453 | mct_int_type = MCT_INT_SPI; | ||
454 | else | ||
455 | mct_int_type = MCT_INT_PPI; | ||
456 | |||
422 | exynos4_timer_resources(); | 457 | exynos4_timer_resources(); |
423 | exynos4_clocksource_init(); | 458 | exynos4_clocksource_init(); |
424 | exynos4_clockevent_init(); | 459 | exynos4_clockevent_init(); |