aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChanghwan Youn <chaos.youn@samsung.com>2011-10-04 04:09:26 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-10-04 05:35:03 -0400
commitc8987470a3a3e56295ee8c9130f5298e807bf4f7 (patch)
tree7a978ba76001de13373b07765dfd1766b699c586 /arch
parent90a454b4c5ef16ec71797b3dcaf454e604c786a3 (diff)
ARM: EXYNOS4: Add MCT support for EXYNOS4412
Current MCT implementation only provide 2 event timers, thus cannot support EXYNOS4412 which has 4 CPU cores. This patch fixes MCT implementation to support SoCs with 4 cores. Signed-off-by: Changhwan Youn <chaos.youn@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-mct.h5
-rw-r--r--arch/arm/mach-exynos4/mct.c113
2 files changed, 56 insertions, 62 deletions
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
index ca9c8434b023..80dd02ad6d61 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-mct.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -31,8 +31,9 @@
31#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248) 31#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
32#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C) 32#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
33 33
34#define EXYNOS4_MCT_L0_BASE EXYNOS4_MCTREG(0x300) 34#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
35#define EXYNOS4_MCT_L1_BASE EXYNOS4_MCTREG(0x400) 35#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
36#define EXYNOS4_MCT_L_MASK (0xffffff00)
36 37
37#define MCT_L_TCNTB_OFFSET (0x00) 38#define MCT_L_TCNTB_OFFSET (0x00)
38#define MCT_L_ICNTB_OFFSET (0x08) 39#define MCT_L_ICNTB_OFFSET (0x08)
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index f43f3faa6495..eb182f29f48f 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -41,9 +41,10 @@ static unsigned int mct_int_type;
41struct mct_clock_event_device { 41struct mct_clock_event_device {
42 struct clock_event_device *evt; 42 struct clock_event_device *evt;
43 void __iomem *base; 43 void __iomem *base;
44 char name[10];
44}; 45};
45 46
46struct mct_clock_event_device mct_tick[2]; 47struct mct_clock_event_device mct_tick[NR_CPUS];
47 48
48static void exynos4_mct_write(unsigned int value, void *addr) 49static void exynos4_mct_write(unsigned int value, void *addr)
49{ 50{
@@ -53,57 +54,53 @@ static void exynos4_mct_write(unsigned int value, void *addr)
53 54
54 __raw_writel(value, addr); 55 __raw_writel(value, addr);
55 56
56 switch ((u32) addr) { 57 if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
57 case (u32) EXYNOS4_MCT_G_TCON: 58 u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
58 stat_addr = EXYNOS4_MCT_G_WSTAT; 59 switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
59 mask = 1 << 16; /* G_TCON write status */ 60 case (u32) MCT_L_TCON_OFFSET:
60 break; 61 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
61 case (u32) EXYNOS4_MCT_G_COMP0_L: 62 mask = 1 << 3; /* L_TCON write status */
62 stat_addr = EXYNOS4_MCT_G_WSTAT; 63 break;
63 mask = 1 << 0; /* G_COMP0_L write status */ 64 case (u32) MCT_L_ICNTB_OFFSET:
64 break; 65 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
65 case (u32) EXYNOS4_MCT_G_COMP0_U: 66 mask = 1 << 1; /* L_ICNTB write status */
66 stat_addr = EXYNOS4_MCT_G_WSTAT; 67 break;
67 mask = 1 << 1; /* G_COMP0_U write status */ 68 case (u32) MCT_L_TCNTB_OFFSET:
68 break; 69 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
69 case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR: 70 mask = 1 << 0; /* L_TCNTB write status */
70 stat_addr = EXYNOS4_MCT_G_WSTAT; 71 break;
71 mask = 1 << 2; /* G_COMP0_ADD_INCR write status */ 72 default:
72 break; 73 return;
73 case (u32) EXYNOS4_MCT_G_CNT_L: 74 }
74 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 75 } else {
75 mask = 1 << 0; /* G_CNT_L write status */ 76 switch ((u32) addr) {
76 break; 77 case (u32) EXYNOS4_MCT_G_TCON:
77 case (u32) EXYNOS4_MCT_G_CNT_U: 78 stat_addr = EXYNOS4_MCT_G_WSTAT;
78 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 79 mask = 1 << 16; /* G_TCON write status */
79 mask = 1 << 1; /* G_CNT_U write status */ 80 break;
80 break; 81 case (u32) EXYNOS4_MCT_G_COMP0_L:
81 case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET): 82 stat_addr = EXYNOS4_MCT_G_WSTAT;
82 stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; 83 mask = 1 << 0; /* G_COMP0_L write status */
83 mask = 1 << 3; /* L0_TCON write status */ 84 break;
84 break; 85 case (u32) EXYNOS4_MCT_G_COMP0_U:
85 case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET): 86 stat_addr = EXYNOS4_MCT_G_WSTAT;
86 stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; 87 mask = 1 << 1; /* G_COMP0_U write status */
87 mask = 1 << 3; /* L1_TCON write status */ 88 break;
88 break; 89 case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
89 case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET): 90 stat_addr = EXYNOS4_MCT_G_WSTAT;
90 stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; 91 mask = 1 << 2; /* G_COMP0_ADD_INCR w status */
91 mask = 1 << 0; /* L0_TCNTB write status */ 92 break;
92 break; 93 case (u32) EXYNOS4_MCT_G_CNT_L:
93 case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET): 94 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
94 stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; 95 mask = 1 << 0; /* G_CNT_L write status */
95 mask = 1 << 0; /* L1_TCNTB write status */ 96 break;
96 break; 97 case (u32) EXYNOS4_MCT_G_CNT_U:
97 case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET): 98 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
98 stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; 99 mask = 1 << 1; /* G_CNT_U write status */
99 mask = 1 << 1; /* L0_ICNTB write status */ 100 break;
100 break; 101 default:
101 case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET): 102 return;
102 stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; 103 }
103 mask = 1 << 1; /* L1_ICNTB write status */
104 break;
105 default:
106 return;
107 } 104 }
108 105
109 /* Wait maximum 1 ms until written values are applied */ 106 /* Wait maximum 1 ms until written values are applied */
@@ -332,7 +329,7 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
332 } 329 }
333} 330}
334 331
335static inline int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) 332static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
336{ 333{
337 struct clock_event_device *evt = mevt->evt; 334 struct clock_event_device *evt = mevt->evt;
338 335
@@ -383,14 +380,10 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
383 380
384 mct_tick[cpu].evt = evt; 381 mct_tick[cpu].evt = evt;
385 382
386 if (cpu == 0) { 383 mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu);
387 mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE; 384 sprintf(mct_tick[cpu].name, "mct_tick%d", cpu);
388 evt->name = "mct_tick0";
389 } else {
390 mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
391 evt->name = "mct_tick1";
392 }
393 385
386 evt->name = mct_tick[cpu].name;
394 evt->cpumask = cpumask_of(cpu); 387 evt->cpumask = cpumask_of(cpu);
395 evt->set_next_event = exynos4_tick_set_next_event; 388 evt->set_next_event = exynos4_tick_set_next_event;
396 evt->set_mode = exynos4_tick_set_mode; 389 evt->set_mode = exynos4_tick_set_mode;