aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos4
diff options
context:
space:
mode:
authorChanghwan Youn <chaos.youn@samsung.com>2011-10-04 04:02:58 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-10-04 05:35:00 -0400
commit3a062281129229b50e06547af3110f8eccd2f4e4 (patch)
tree5ff884bf90a6dbccd4859f8aaf4e8bc1685f7009 /arch/arm/mach-exynos4
parent637c2afa57ec9cd0ddc8879ea0cda4d8835ba71d (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.S6
-rw-r--r--arch/arm/mach-exynos4/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-exynos4/mct.c55
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
32enum {
33 MCT_INT_SPI,
34 MCT_INT_PPI
35};
36
27static unsigned long clk_cnt_per_tick; 37static unsigned long clk_cnt_per_tick;
28static unsigned long clk_rate; 38static unsigned long clk_rate;
39static unsigned int mct_int_type;
29 40
30struct mct_clock_event_device { 41struct 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
324static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) 335static 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
356static 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
405int local_timer_ack(void) 432int 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
420static void __init exynos4_timer_init(void) 450static 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();