diff options
author | Changhwan Youn <chaos.youn@samsung.com> | 2011-10-04 04:02:58 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-10-04 05:35:00 -0400 |
commit | 3a062281129229b50e06547af3110f8eccd2f4e4 (patch) | |
tree | 5ff884bf90a6dbccd4859f8aaf4e8bc1685f7009 /arch/arm/mach-exynos4 | |
parent | 637c2afa57ec9cd0ddc8879ea0cda4d8835ba71d (diff) |
ARM: EXYNOS4: Add support MCT PPI for EXYNOS4212
This patch implements clock event timer using MCT PPI
and make EXYNOS4212 use MCT PPI instead of MCT SPI.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos4')
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/entry-macro.S | 6 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/irqs.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/mct.c | 55 |
3 files changed, 53 insertions, 10 deletions
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S index d7a1e281ce7a..61393dcf5559 100644 --- a/arch/arm/mach-exynos4/include/mach/entry-macro.S +++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S | |||
@@ -80,4 +80,10 @@ | |||
80 | /* As above, this assumes that irqstat and base are preserved.. */ | 80 | /* As above, this assumes that irqstat and base are preserved.. */ |
81 | 81 | ||
82 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | 82 | .macro test_for_ltirq, irqnr, irqstat, base, tmp |
83 | bic \irqnr, \irqstat, #0x1c00 | ||
84 | mov \tmp, #0 | ||
85 | cmp \irqnr, #28 | ||
86 | moveq \tmp, #1 | ||
87 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
88 | cmp \tmp, #0 | ||
83 | .endm | 89 | .endm |
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h index f8952f8f3757..2d3f6bcd9bc0 100644 --- a/arch/arm/mach-exynos4/include/mach/irqs.h +++ b/arch/arm/mach-exynos4/include/mach/irqs.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #define IRQ_PPI(x) S5P_IRQ(x+16) | 20 | #define IRQ_PPI(x) S5P_IRQ(x+16) |
21 | 21 | ||
22 | #define IRQ_MCT_LOCALTIMER IRQ_PPI(12) | ||
23 | |||
22 | /* SPI: Shared Peripheral Interrupt */ | 24 | /* SPI: Shared Peripheral Interrupt */ |
23 | 25 | ||
24 | #define IRQ_SPI(x) S5P_IRQ(x+32) | 26 | #define IRQ_SPI(x) S5P_IRQ(x+32) |
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(); |