diff options
author | Changhwan Youn <chaos.youn@samsung.com> | 2011-10-04 04:09:26 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-10-04 05:35:03 -0400 |
commit | c8987470a3a3e56295ee8c9130f5298e807bf4f7 (patch) | |
tree | 7a978ba76001de13373b07765dfd1766b699c586 /arch | |
parent | 90a454b4c5ef16ec71797b3dcaf454e604c786a3 (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.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/mct.c | 113 |
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; | |||
41 | struct mct_clock_event_device { | 41 | struct 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 | ||
46 | struct mct_clock_event_device mct_tick[2]; | 47 | struct mct_clock_event_device mct_tick[NR_CPUS]; |
47 | 48 | ||
48 | static void exynos4_mct_write(unsigned int value, void *addr) | 49 | static 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 | ||
335 | static inline int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) | 332 | static 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; |