aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2013-03-09 02:56:34 -0500
committerKukjin Kim <kgene.kim@samsung.com>2013-03-09 02:56:34 -0500
commit8ec46b97f24d60645c8f708c87e0caecebd25d77 (patch)
tree3663c411f7a4e7a9bfc0a8e720679b93a5860b7c
parentb85b64cc22122adca695e0f8c340cc677ad92e8c (diff)
parent6938d75a8c1a1752f9fa7ef14a0c570036c7b73b (diff)
Merge branch 'next/mct-exynos' into next/clk-exynos
Conflicts: arch/arm/mach-exynos/mach-exynos4-dt.c
-rw-r--r--Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt68
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi22
-rw-r--r--arch/arm/boot/dts/exynos4212.dtsi22
-rw-r--r--arch/arm/boot/dts/exynos4412.dtsi24
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi22
-rw-r--r--arch/arm/mach-exynos/Kconfig8
-rw-r--r--arch/arm/mach-exynos/Makefile2
-rw-r--r--arch/arm/mach-exynos/common.c5
-rw-r--r--arch/arm/mach-exynos/common.h2
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h6
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h1
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-mct.h53
-rw-r--r--arch/arm/mach-exynos/mach-armlex4210.c2
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c3
-rw-r--r--arch/arm/mach-exynos/mach-exynos5-dt.c3
-rw-r--r--arch/arm/mach-exynos/mach-nuri.c2
-rw-r--r--arch/arm/mach-exynos/mach-origen.c2
-rw-r--r--arch/arm/mach-exynos/mach-smdk4x12.c4
-rw-r--r--arch/arm/mach-exynos/mach-smdkv310.c4
-rw-r--r--drivers/clocksource/Kconfig5
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/exynos_mct.c (renamed from arch/arm/mach-exynos/mct.c)195
23 files changed, 309 insertions, 149 deletions
diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
new file mode 100644
index 000000000000..cb47bfbcaeea
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
@@ -0,0 +1,68 @@
1Samsung's Multi Core Timer (MCT)
2
3The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
4global timer and CPU local timers. The global timer is a 64-bit free running
5up-counter and can generate 4 interrupts when the counter reaches one of the
6four preset counter values. The CPU local timers are 32-bit free running
7down-counters and generate an interrupt when the counter expires. There is
8one CPU local timer instantiated in MCT for every CPU in the system.
9
10Required properties:
11
12- compatible: should be "samsung,exynos4210-mct".
13 (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
14 (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
15
16- reg: base address of the mct controller and length of the address space
17 it occupies.
18
19- interrupts: the list of interrupts generated by the controller. The following
20 should be the order of the interrupts specified. The local timer interrupts
21 should be specified after the four global timer interrupts have been
22 specified.
23
24 0: Global Timer Interrupt 0
25 1: Global Timer Interrupt 1
26 2: Global Timer Interrupt 2
27 3: Global Timer Interrupt 3
28 4: Local Timer Interrupt 0
29 5: Local Timer Interrupt 1
30 6: ..
31 7: ..
32 i: Local Timer Interrupt n
33
34Example 1: In this example, the system uses only the first global timer
35 interrupt generated by MCT and the remaining three global timer
36 interrupts are unused. Two local timer interrupts have been
37 specified.
38
39 mct@10050000 {
40 compatible = "samsung,exynos4210-mct";
41 reg = <0x10050000 0x800>;
42 interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
43 <0 42 0>, <0 48 0>;
44 };
45
46Example 2: In this example, the MCT global and local timer interrupts are
47 connected to two seperate interrupt controllers. Hence, an
48 interrupt-map is created to map the interrupts to the respective
49 interrupt controllers.
50
51 mct@101C0000 {
52 compatible = "samsung,exynos4210-mct";
53 reg = <0x101C0000 0x800>;
54 interrupt-controller;
55 #interrups-cells = <2>;
56 interrupt-parent = <&mct_map>;
57 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
58 <4 0>, <5 0>;
59
60 mct_map: mct-map {
61 #interrupt-cells = <2>;
62 #address-cells = <0>;
63 #size-cells = <0>;
64 interrupt-map = <0x0 0 &combiner 23 3>,
65 <0x4 0 &gic 0 120 0>,
66 <0x5 0 &gic 0 121 0>;
67 };
68 };
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 46fcfa8805f8..ee414be31b4d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1655,7 +1655,7 @@ config LOCAL_TIMERS
1655 bool "Use local timer interrupts" 1655 bool "Use local timer interrupts"
1656 depends on SMP 1656 depends on SMP
1657 default y 1657 default y
1658 select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) 1658 select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !CLKSRC_EXYNOS_MCT)
1659 help 1659 help
1660 Enable support for local timers on SMP platforms, rather then the 1660 Enable support for local timers on SMP platforms, rather then the
1661 legacy IPI broadcast method. Local timers allows the system 1661 legacy IPI broadcast method. Local timers allows the system
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 2feffc70814c..49a2786e00b9 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -47,6 +47,28 @@
47 <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; 47 <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
48 }; 48 };
49 49
50 mct@10050000 {
51 compatible = "samsung,exynos4210-mct";
52 reg = <0x10050000 0x800>;
53 interrupt-controller;
54 #interrups-cells = <2>;
55 interrupt-parent = <&mct_map>;
56 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
57 <4 0>, <5 0>;
58
59 mct_map: mct-map {
60 #interrupt-cells = <2>;
61 #address-cells = <0>;
62 #size-cells = <0>;
63 interrupt-map = <0x0 0 &gic 0 57 0>,
64 <0x1 0 &gic 0 69 0>,
65 <0x2 0 &combiner 12 6>,
66 <0x3 0 &combiner 12 7>,
67 <0x4 0 &gic 0 42 0>,
68 <0x5 0 &gic 0 48 0>;
69 };
70 };
71
50 pinctrl_0: pinctrl@11400000 { 72 pinctrl_0: pinctrl@11400000 {
51 compatible = "samsung,exynos4210-pinctrl"; 73 compatible = "samsung,exynos4210-pinctrl";
52 reg = <0x11400000 0x1000>; 74 reg = <0x11400000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index c6ae2005961f..36d4299789ef 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -25,4 +25,26 @@
25 gic:interrupt-controller@10490000 { 25 gic:interrupt-controller@10490000 {
26 cpu-offset = <0x8000>; 26 cpu-offset = <0x8000>;
27 }; 27 };
28
29 mct@10050000 {
30 compatible = "samsung,exynos4412-mct";
31 reg = <0x10050000 0x800>;
32 interrupt-controller;
33 #interrups-cells = <2>;
34 interrupt-parent = <&mct_map>;
35 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
36 <4 0>, <5 0>;
37
38 mct_map: mct-map {
39 #interrupt-cells = <2>;
40 #address-cells = <0>;
41 #size-cells = <0>;
42 interrupt-map = <0x0 0 &gic 0 57 0>,
43 <0x1 0 &combiner 12 5>,
44 <0x2 0 &combiner 12 6>,
45 <0x3 0 &combiner 12 7>,
46 <0x4 0 &gic 1 12 0>,
47 <0x5 0 &gic 1 12 0>;
48 };
49 };
28}; 50};
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index d7dfe312772a..821c9fdd1e3b 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -25,4 +25,28 @@
25 gic:interrupt-controller@10490000 { 25 gic:interrupt-controller@10490000 {
26 cpu-offset = <0x4000>; 26 cpu-offset = <0x4000>;
27 }; 27 };
28
29 mct@10050000 {
30 compatible = "samsung,exynos4412-mct";
31 reg = <0x10050000 0x800>;
32 interrupt-controller;
33 #interrups-cells = <2>;
34 interrupt-parent = <&mct_map>;
35 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
36 <4 0>, <5 0>, <6 0>, <7 0>;
37
38 mct_map: mct-map {
39 #interrupt-cells = <2>;
40 #address-cells = <0>;
41 #size-cells = <0>;
42 interrupt-map = <0x0 0 &gic 0 57 0>,
43 <0x1 0 &combiner 12 5>,
44 <0x2 0 &combiner 12 6>,
45 <0x3 0 &combiner 12 7>,
46 <0x4 0 &gic 1 12 0>,
47 <0x5 0 &gic 1 12 0>,
48 <0x6 0 &gic 1 12 0>,
49 <0x7 0 &gic 1 12 0>;
50 };
51 };
28}; 52};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 37a90dd6a4d2..4fe76bf299fb 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -79,6 +79,28 @@
79 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; 79 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
80 }; 80 };
81 81
82 mct@101C0000 {
83 compatible = "samsung,exynos4210-mct";
84 reg = <0x101C0000 0x800>;
85 interrupt-controller;
86 #interrups-cells = <2>;
87 interrupt-parent = <&mct_map>;
88 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
89 <4 0>, <5 0>;
90
91 mct_map: mct-map {
92 #interrupt-cells = <2>;
93 #address-cells = <0>;
94 #size-cells = <0>;
95 interrupt-map = <0x0 0 &combiner 23 3>,
96 <0x1 0 &combiner 23 4>,
97 <0x2 0 &combiner 25 2>,
98 <0x3 0 &combiner 25 3>,
99 <0x4 0 &gic 0 120 0>,
100 <0x5 0 &gic 0 121 0>;
101 };
102 };
103
82 watchdog { 104 watchdog {
83 compatible = "samsung,s3c2410-wdt"; 105 compatible = "samsung,s3c2410-wdt";
84 reg = <0x101D0000 0x100>; 106 reg = <0x101D0000 0x100>;
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index bc15b9ee8174..ef3b69a6277c 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -80,12 +80,6 @@ config SOC_EXYNOS5440
80 help 80 help
81 Enable EXYNOS5440 SoC support 81 Enable EXYNOS5440 SoC support
82 82
83config EXYNOS4_MCT
84 bool
85 default y
86 help
87 Use MCT (Multi Core Timer) as kernel timers
88
89config EXYNOS_DEV_DMA 83config EXYNOS_DEV_DMA
90 bool 84 bool
91 help 85 help
@@ -407,6 +401,7 @@ config MACH_EXYNOS4_DT
407 bool "Samsung Exynos4 Machine using device tree" 401 bool "Samsung Exynos4 Machine using device tree"
408 depends on ARCH_EXYNOS4 402 depends on ARCH_EXYNOS4
409 select ARM_AMBA 403 select ARM_AMBA
404 select CLKSRC_OF
410 select CPU_EXYNOS4210 405 select CPU_EXYNOS4210
411 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD 406 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
412 select PINCTRL 407 select PINCTRL
@@ -424,6 +419,7 @@ config MACH_EXYNOS5_DT
424 default y 419 default y
425 depends on ARCH_EXYNOS5 420 depends on ARCH_EXYNOS5
426 select ARM_AMBA 421 select ARM_AMBA
422 select CLKSRC_OF
427 select USE_OF 423 select USE_OF
428 help 424 help
429 Machine support for Samsung EXYNOS5 machine with device tree enabled. 425 Machine support for Samsung EXYNOS5 machine with device tree enabled.
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 435757e57bb4..daf289b21486 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -26,8 +26,6 @@ obj-$(CONFIG_ARCH_EXYNOS) += pmu.o
26 26
27obj-$(CONFIG_SMP) += platsmp.o headsmp.o 27obj-$(CONFIG_SMP) += platsmp.o headsmp.o
28 28
29obj-$(CONFIG_EXYNOS4_MCT) += mct.o
30
31obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 29obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
32 30
33# machine support 31# machine support
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index d63d399c7bae..f91dad6fe9a3 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -257,11 +257,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
257 .length = SZ_4K, 257 .length = SZ_4K,
258 .type = MT_DEVICE, 258 .type = MT_DEVICE,
259 }, { 259 }, {
260 .virtual = (unsigned long)S5P_VA_SYSTIMER,
261 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
262 .length = SZ_4K,
263 .type = MT_DEVICE,
264 }, {
265 .virtual = (unsigned long)S5P_VA_SYSRAM, 260 .virtual = (unsigned long)S5P_VA_SYSRAM,
266 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM), 261 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
267 .length = SZ_4K, 262 .length = SZ_4K,
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 9339bb8954be..3b186eaaaa7b 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -12,7 +12,7 @@
12#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H 12#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
13#define __ARCH_ARM_MACH_EXYNOS_COMMON_H 13#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
14 14
15extern void exynos4_timer_init(void); 15extern void mct_init(void);
16 16
17struct map_desc; 17struct map_desc;
18void exynos_init_io(struct map_desc *mach_desc, int size); 18void exynos_init_io(struct map_desc *mach_desc, int size);
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 1f4dc35cd4b9..c0e75d8dd737 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -30,8 +30,6 @@
30 30
31/* For EXYNOS4 and EXYNOS5 */ 31/* For EXYNOS4 and EXYNOS5 */
32 32
33#define EXYNOS_IRQ_MCT_LOCALTIMER IRQ_PPI(12)
34
35#define EXYNOS_IRQ_EINT16_31 IRQ_SPI(32) 33#define EXYNOS_IRQ_EINT16_31 IRQ_SPI(32)
36 34
37/* For EXYNOS4 SoCs */ 35/* For EXYNOS4 SoCs */
@@ -323,8 +321,6 @@
323#define EXYNOS5_IRQ_CEC IRQ_SPI(114) 321#define EXYNOS5_IRQ_CEC IRQ_SPI(114)
324#define EXYNOS5_IRQ_SATA IRQ_SPI(115) 322#define EXYNOS5_IRQ_SATA IRQ_SPI(115)
325 323
326#define EXYNOS5_IRQ_MCT_L0 IRQ_SPI(120)
327#define EXYNOS5_IRQ_MCT_L1 IRQ_SPI(121)
328#define EXYNOS5_IRQ_MMC44 IRQ_SPI(123) 324#define EXYNOS5_IRQ_MMC44 IRQ_SPI(123)
329#define EXYNOS5_IRQ_MDMA1 IRQ_SPI(124) 325#define EXYNOS5_IRQ_MDMA1 IRQ_SPI(124)
330#define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125) 326#define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125)
@@ -419,8 +415,6 @@
419#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(22, 4) 415#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(22, 4)
420 416
421#define EXYNOS5_IRQ_EINT0 COMBINER_IRQ(23, 0) 417#define EXYNOS5_IRQ_EINT0 COMBINER_IRQ(23, 0)
422#define EXYNOS5_IRQ_MCT_G0 COMBINER_IRQ(23, 3)
423#define EXYNOS5_IRQ_MCT_G1 COMBINER_IRQ(23, 4)
424 418
425#define EXYNOS5_IRQ_EINT1 COMBINER_IRQ(24, 0) 419#define EXYNOS5_IRQ_EINT1 COMBINER_IRQ(24, 0)
426#define EXYNOS5_IRQ_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1) 420#define EXYNOS5_IRQ_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 1df6abbf53b8..7f99b7b187d6 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -65,7 +65,6 @@
65#define EXYNOS5_PA_CMU 0x10010000 65#define EXYNOS5_PA_CMU 0x10010000
66 66
67#define EXYNOS4_PA_SYSTIMER 0x10050000 67#define EXYNOS4_PA_SYSTIMER 0x10050000
68#define EXYNOS5_PA_SYSTIMER 0x101C0000
69 68
70#define EXYNOS4_PA_WATCHDOG 0x10060000 69#define EXYNOS4_PA_WATCHDOG 0x10060000
71#define EXYNOS5_PA_WATCHDOG 0x101D0000 70#define EXYNOS5_PA_WATCHDOG 0x101D0000
diff --git a/arch/arm/mach-exynos/include/mach/regs-mct.h b/arch/arm/mach-exynos/include/mach/regs-mct.h
deleted file mode 100644
index 80dd02ad6d61..000000000000
--- a/arch/arm/mach-exynos/include/mach/regs-mct.h
+++ /dev/null
@@ -1,53 +0,0 @@
1/* arch/arm/mach-exynos4/include/mach/regs-mct.h
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * EXYNOS4 MCT configutation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_REGS_MCT_H
14#define __ASM_ARCH_REGS_MCT_H __FILE__
15
16#include <mach/map.h>
17
18#define EXYNOS4_MCTREG(x) (S5P_VA_SYSTIMER + (x))
19
20#define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100)
21#define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104)
22#define EXYNOS4_MCT_G_CNT_WSTAT EXYNOS4_MCTREG(0x110)
23
24#define EXYNOS4_MCT_G_COMP0_L EXYNOS4_MCTREG(0x200)
25#define EXYNOS4_MCT_G_COMP0_U EXYNOS4_MCTREG(0x204)
26#define EXYNOS4_MCT_G_COMP0_ADD_INCR EXYNOS4_MCTREG(0x208)
27
28#define EXYNOS4_MCT_G_TCON EXYNOS4_MCTREG(0x240)
29
30#define EXYNOS4_MCT_G_INT_CSTAT EXYNOS4_MCTREG(0x244)
31#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
32#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
33
34#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
35#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
36#define EXYNOS4_MCT_L_MASK (0xffffff00)
37
38#define MCT_L_TCNTB_OFFSET (0x00)
39#define MCT_L_ICNTB_OFFSET (0x08)
40#define MCT_L_TCON_OFFSET (0x20)
41#define MCT_L_INT_CSTAT_OFFSET (0x30)
42#define MCT_L_INT_ENB_OFFSET (0x34)
43#define MCT_L_WSTAT_OFFSET (0x40)
44
45#define MCT_G_TCON_START (1 << 8)
46#define MCT_G_TCON_COMP0_AUTO_INC (1 << 1)
47#define MCT_G_TCON_COMP0_ENABLE (1 << 0)
48
49#define MCT_L_TCON_INTERVAL_MODE (1 << 2)
50#define MCT_L_TCON_INT_START (1 << 1)
51#define MCT_L_TCON_TIMER_START (1 << 0)
52
53#endif /* __ASM_ARCH_REGS_MCT_H */
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 685f29173afa..3b1a34742679 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -202,6 +202,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
202 .map_io = armlex4210_map_io, 202 .map_io = armlex4210_map_io,
203 .init_machine = armlex4210_machine_init, 203 .init_machine = armlex4210_machine_init,
204 .init_late = exynos_init_late, 204 .init_late = exynos_init_late,
205 .init_time = exynos4_timer_init, 205 .init_time = mct_init,
206 .restart = exynos4_restart, 206 .restart = exynos4_restart,
207MACHINE_END 207MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index fad268f8548c..daa7b0da9a2d 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -15,6 +15,7 @@
15#include <linux/of_fdt.h> 15#include <linux/of_fdt.h>
16#include <linux/serial_core.h> 16#include <linux/serial_core.h>
17#include <linux/memblock.h> 17#include <linux/memblock.h>
18#include <linux/clocksource.h>
18 19
19#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
20#include <mach/map.h> 21#include <mach/map.h>
@@ -158,7 +159,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
158 .map_io = exynos4_dt_map_io, 159 .map_io = exynos4_dt_map_io,
159 .init_machine = exynos4_dt_machine_init, 160 .init_machine = exynos4_dt_machine_init,
160 .init_late = exynos_init_late, 161 .init_late = exynos_init_late,
161 .init_time = exynos4_timer_init, 162 .init_time = clocksource_of_init,
162 .dt_compat = exynos4_dt_compat, 163 .dt_compat = exynos4_dt_compat,
163 .restart = exynos4_restart, 164 .restart = exynos4_restart,
164 .reserve = exynos4_reserve, 165 .reserve = exynos4_reserve,
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index 8ef895745175..62d43dacf636 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -14,6 +14,7 @@
14#include <linux/serial_core.h> 14#include <linux/serial_core.h>
15#include <linux/memblock.h> 15#include <linux/memblock.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/clocksource.h>
17 18
18#include <asm/mach/arch.h> 19#include <asm/mach/arch.h>
19#include <mach/map.h> 20#include <mach/map.h>
@@ -217,7 +218,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
217 .map_io = exynos5_dt_map_io, 218 .map_io = exynos5_dt_map_io,
218 .init_machine = exynos5_dt_machine_init, 219 .init_machine = exynos5_dt_machine_init,
219 .init_late = exynos_init_late, 220 .init_late = exynos_init_late,
220 .init_time = exynos4_timer_init, 221 .init_time = clocksource_of_init,
221 .dt_compat = exynos5_dt_compat, 222 .dt_compat = exynos5_dt_compat,
222 .restart = exynos5_restart, 223 .restart = exynos5_restart,
223 .reserve = exynos5_reserve, 224 .reserve = exynos5_reserve,
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 1ea79730187f..da3605d15110 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1380,7 +1380,7 @@ MACHINE_START(NURI, "NURI")
1380 .map_io = nuri_map_io, 1380 .map_io = nuri_map_io,
1381 .init_machine = nuri_machine_init, 1381 .init_machine = nuri_machine_init,
1382 .init_late = exynos_init_late, 1382 .init_late = exynos_init_late,
1383 .init_time = exynos4_timer_init, 1383 .init_time = mct_init,
1384 .reserve = &nuri_reserve, 1384 .reserve = &nuri_reserve,
1385 .restart = exynos4_restart, 1385 .restart = exynos4_restart,
1386MACHINE_END 1386MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 579d2d171daa..1772cd284f4c 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -815,7 +815,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
815 .map_io = origen_map_io, 815 .map_io = origen_map_io,
816 .init_machine = origen_machine_init, 816 .init_machine = origen_machine_init,
817 .init_late = exynos_init_late, 817 .init_late = exynos_init_late,
818 .init_time = exynos4_timer_init, 818 .init_time = mct_init,
819 .reserve = &origen_reserve, 819 .reserve = &origen_reserve,
820 .restart = exynos4_restart, 820 .restart = exynos4_restart,
821MACHINE_END 821MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index fe6149624b84..34a6356364eb 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -376,7 +376,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
376 .init_irq = exynos4_init_irq, 376 .init_irq = exynos4_init_irq,
377 .map_io = smdk4x12_map_io, 377 .map_io = smdk4x12_map_io,
378 .init_machine = smdk4x12_machine_init, 378 .init_machine = smdk4x12_machine_init,
379 .init_time = exynos4_timer_init, 379 .init_time = mct_init,
380 .restart = exynos4_restart, 380 .restart = exynos4_restart,
381 .reserve = &smdk4x12_reserve, 381 .reserve = &smdk4x12_reserve,
382MACHINE_END 382MACHINE_END
@@ -390,7 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
390 .map_io = smdk4x12_map_io, 390 .map_io = smdk4x12_map_io,
391 .init_machine = smdk4x12_machine_init, 391 .init_machine = smdk4x12_machine_init,
392 .init_late = exynos_init_late, 392 .init_late = exynos_init_late,
393 .init_time = exynos4_timer_init, 393 .init_time = mct_init,
394 .restart = exynos4_restart, 394 .restart = exynos4_restart,
395 .reserve = &smdk4x12_reserve, 395 .reserve = &smdk4x12_reserve,
396MACHINE_END 396MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index d71672922b19..893b14e8c62a 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -423,7 +423,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
423 .init_irq = exynos4_init_irq, 423 .init_irq = exynos4_init_irq,
424 .map_io = smdkv310_map_io, 424 .map_io = smdkv310_map_io,
425 .init_machine = smdkv310_machine_init, 425 .init_machine = smdkv310_machine_init,
426 .init_time = exynos4_timer_init, 426 .init_time = mct_init,
427 .reserve = &smdkv310_reserve, 427 .reserve = &smdkv310_reserve,
428 .restart = exynos4_restart, 428 .restart = exynos4_restart,
429MACHINE_END 429MACHINE_END
@@ -436,7 +436,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
436 .map_io = smdkv310_map_io, 436 .map_io = smdkv310_map_io,
437 .init_machine = smdkv310_machine_init, 437 .init_machine = smdkv310_machine_init,
438 .init_late = exynos_init_late, 438 .init_late = exynos_init_late,
439 .init_time = exynos4_timer_init, 439 .init_time = mct_init,
440 .reserve = &smdkv310_reserve, 440 .reserve = &smdkv310_reserve,
441 .restart = exynos4_restart, 441 .restart = exynos4_restart,
442MACHINE_END 442MACHINE_END
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e507ab7df60b..e8c453285151 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -67,3 +67,8 @@ config CLKSRC_METAG_GENERIC
67 def_bool y if METAG 67 def_bool y if METAG
68 help 68 help
69 This option enables support for the Meta per-thread timers. 69 This option enables support for the Meta per-thread timers.
70
71config CLKSRC_EXYNOS_MCT
72 def_bool y if ARCH_EXYNOS
73 help
74 Support for Multi Core Timer controller on Exynos SoCs.
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 4d8283aec5b5..1c1b15db7c4d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
19obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o 19obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o
20obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o 20obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
21obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o 21obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
22obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
22 23
23obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o 24obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
24obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o 25obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
diff --git a/arch/arm/mach-exynos/mct.c b/drivers/clocksource/exynos_mct.c
index c9d6650f9b5d..545c98976e93 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -20,6 +20,9 @@
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/percpu.h> 21#include <linux/percpu.h>
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/of_irq.h>
24#include <linux/of_address.h>
25#include <linux/clocksource.h>
23 26
24#include <asm/arch_timer.h> 27#include <asm/arch_timer.h>
25#include <asm/localtimer.h> 28#include <asm/localtimer.h>
@@ -28,9 +31,36 @@
28 31
29#include <mach/map.h> 32#include <mach/map.h>
30#include <mach/irqs.h> 33#include <mach/irqs.h>
31#include <mach/regs-mct.h>
32#include <asm/mach/time.h> 34#include <asm/mach/time.h>
33 35
36#define EXYNOS4_MCTREG(x) (x)
37#define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100)
38#define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104)
39#define EXYNOS4_MCT_G_CNT_WSTAT EXYNOS4_MCTREG(0x110)
40#define EXYNOS4_MCT_G_COMP0_L EXYNOS4_MCTREG(0x200)
41#define EXYNOS4_MCT_G_COMP0_U EXYNOS4_MCTREG(0x204)
42#define EXYNOS4_MCT_G_COMP0_ADD_INCR EXYNOS4_MCTREG(0x208)
43#define EXYNOS4_MCT_G_TCON EXYNOS4_MCTREG(0x240)
44#define EXYNOS4_MCT_G_INT_CSTAT EXYNOS4_MCTREG(0x244)
45#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
46#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
47#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
48#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
49#define EXYNOS4_MCT_L_MASK (0xffffff00)
50
51#define MCT_L_TCNTB_OFFSET (0x00)
52#define MCT_L_ICNTB_OFFSET (0x08)
53#define MCT_L_TCON_OFFSET (0x20)
54#define MCT_L_INT_CSTAT_OFFSET (0x30)
55#define MCT_L_INT_ENB_OFFSET (0x34)
56#define MCT_L_WSTAT_OFFSET (0x40)
57#define MCT_G_TCON_START (1 << 8)
58#define MCT_G_TCON_COMP0_AUTO_INC (1 << 1)
59#define MCT_G_TCON_COMP0_ENABLE (1 << 0)
60#define MCT_L_TCON_INTERVAL_MODE (1 << 2)
61#define MCT_L_TCON_INT_START (1 << 1)
62#define MCT_L_TCON_TIMER_START (1 << 0)
63
34#define TICK_BASE_CNT 1 64#define TICK_BASE_CNT 1
35 65
36enum { 66enum {
@@ -38,64 +68,75 @@ enum {
38 MCT_INT_PPI 68 MCT_INT_PPI
39}; 69};
40 70
71enum {
72 MCT_G0_IRQ,
73 MCT_G1_IRQ,
74 MCT_G2_IRQ,
75 MCT_G3_IRQ,
76 MCT_L0_IRQ,
77 MCT_L1_IRQ,
78 MCT_L2_IRQ,
79 MCT_L3_IRQ,
80 MCT_NR_IRQS,
81};
82
83static void __iomem *reg_base;
41static unsigned long clk_rate; 84static unsigned long clk_rate;
42static unsigned int mct_int_type; 85static unsigned int mct_int_type;
86static int mct_irqs[MCT_NR_IRQS];
43 87
44struct mct_clock_event_device { 88struct mct_clock_event_device {
45 struct clock_event_device *evt; 89 struct clock_event_device *evt;
46 void __iomem *base; 90 unsigned long base;
47 char name[10]; 91 char name[10];
48}; 92};
49 93
50static void exynos4_mct_write(unsigned int value, void *addr) 94static void exynos4_mct_write(unsigned int value, unsigned long offset)
51{ 95{
52 void __iomem *stat_addr; 96 unsigned long stat_addr;
53 u32 mask; 97 u32 mask;
54 u32 i; 98 u32 i;
55 99
56 __raw_writel(value, addr); 100 __raw_writel(value, reg_base + offset);
57 101
58 if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) { 102 if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
59 u32 base = (u32) addr & EXYNOS4_MCT_L_MASK; 103 stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
60 switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) { 104 switch (offset & EXYNOS4_MCT_L_MASK) {
61 case (u32) MCT_L_TCON_OFFSET: 105 case MCT_L_TCON_OFFSET:
62 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
63 mask = 1 << 3; /* L_TCON write status */ 106 mask = 1 << 3; /* L_TCON write status */
64 break; 107 break;
65 case (u32) MCT_L_ICNTB_OFFSET: 108 case MCT_L_ICNTB_OFFSET:
66 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
67 mask = 1 << 1; /* L_ICNTB write status */ 109 mask = 1 << 1; /* L_ICNTB write status */
68 break; 110 break;
69 case (u32) MCT_L_TCNTB_OFFSET: 111 case MCT_L_TCNTB_OFFSET:
70 stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
71 mask = 1 << 0; /* L_TCNTB write status */ 112 mask = 1 << 0; /* L_TCNTB write status */
72 break; 113 break;
73 default: 114 default:
74 return; 115 return;
75 } 116 }
76 } else { 117 } else {
77 switch ((u32) addr) { 118 switch (offset) {
78 case (u32) EXYNOS4_MCT_G_TCON: 119 case EXYNOS4_MCT_G_TCON:
79 stat_addr = EXYNOS4_MCT_G_WSTAT; 120 stat_addr = EXYNOS4_MCT_G_WSTAT;
80 mask = 1 << 16; /* G_TCON write status */ 121 mask = 1 << 16; /* G_TCON write status */
81 break; 122 break;
82 case (u32) EXYNOS4_MCT_G_COMP0_L: 123 case EXYNOS4_MCT_G_COMP0_L:
83 stat_addr = EXYNOS4_MCT_G_WSTAT; 124 stat_addr = EXYNOS4_MCT_G_WSTAT;
84 mask = 1 << 0; /* G_COMP0_L write status */ 125 mask = 1 << 0; /* G_COMP0_L write status */
85 break; 126 break;
86 case (u32) EXYNOS4_MCT_G_COMP0_U: 127 case EXYNOS4_MCT_G_COMP0_U:
87 stat_addr = EXYNOS4_MCT_G_WSTAT; 128 stat_addr = EXYNOS4_MCT_G_WSTAT;
88 mask = 1 << 1; /* G_COMP0_U write status */ 129 mask = 1 << 1; /* G_COMP0_U write status */
89 break; 130 break;
90 case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR: 131 case EXYNOS4_MCT_G_COMP0_ADD_INCR:
91 stat_addr = EXYNOS4_MCT_G_WSTAT; 132 stat_addr = EXYNOS4_MCT_G_WSTAT;
92 mask = 1 << 2; /* G_COMP0_ADD_INCR w status */ 133 mask = 1 << 2; /* G_COMP0_ADD_INCR w status */
93 break; 134 break;
94 case (u32) EXYNOS4_MCT_G_CNT_L: 135 case EXYNOS4_MCT_G_CNT_L:
95 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 136 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
96 mask = 1 << 0; /* G_CNT_L write status */ 137 mask = 1 << 0; /* G_CNT_L write status */
97 break; 138 break;
98 case (u32) EXYNOS4_MCT_G_CNT_U: 139 case EXYNOS4_MCT_G_CNT_U:
99 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 140 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
100 mask = 1 << 1; /* G_CNT_U write status */ 141 mask = 1 << 1; /* G_CNT_U write status */
101 break; 142 break;
@@ -106,12 +147,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
106 147
107 /* Wait maximum 1 ms until written values are applied */ 148 /* Wait maximum 1 ms until written values are applied */
108 for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++) 149 for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
109 if (__raw_readl(stat_addr) & mask) { 150 if (__raw_readl(reg_base + stat_addr) & mask) {
110 __raw_writel(mask, stat_addr); 151 __raw_writel(mask, reg_base + stat_addr);
111 return; 152 return;
112 } 153 }
113 154
114 panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr); 155 panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
115} 156}
116 157
117/* Clocksource handling */ 158/* Clocksource handling */
@@ -122,7 +163,7 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
122 exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L); 163 exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
123 exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U); 164 exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
124 165
125 reg = __raw_readl(EXYNOS4_MCT_G_TCON); 166 reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
126 reg |= MCT_G_TCON_START; 167 reg |= MCT_G_TCON_START;
127 exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); 168 exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
128} 169}
@@ -130,12 +171,12 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
130static cycle_t exynos4_frc_read(struct clocksource *cs) 171static cycle_t exynos4_frc_read(struct clocksource *cs)
131{ 172{
132 unsigned int lo, hi; 173 unsigned int lo, hi;
133 u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U); 174 u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
134 175
135 do { 176 do {
136 hi = hi2; 177 hi = hi2;
137 lo = __raw_readl(EXYNOS4_MCT_G_CNT_L); 178 lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
138 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U); 179 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
139 } while (hi != hi2); 180 } while (hi != hi2);
140 181
141 return ((cycle_t)hi << 32) | lo; 182 return ((cycle_t)hi << 32) | lo;
@@ -167,7 +208,7 @@ static void exynos4_mct_comp0_stop(void)
167{ 208{
168 unsigned int tcon; 209 unsigned int tcon;
169 210
170 tcon = __raw_readl(EXYNOS4_MCT_G_TCON); 211 tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
171 tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC); 212 tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
172 213
173 exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON); 214 exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -180,7 +221,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
180 unsigned int tcon; 221 unsigned int tcon;
181 cycle_t comp_cycle; 222 cycle_t comp_cycle;
182 223
183 tcon = __raw_readl(EXYNOS4_MCT_G_TCON); 224 tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
184 225
185 if (mode == CLOCK_EVT_MODE_PERIODIC) { 226 if (mode == CLOCK_EVT_MODE_PERIODIC) {
186 tcon |= MCT_G_TCON_COMP0_AUTO_INC; 227 tcon |= MCT_G_TCON_COMP0_AUTO_INC;
@@ -257,11 +298,7 @@ static void exynos4_clockevent_init(void)
257 mct_comp_device.cpumask = cpumask_of(0); 298 mct_comp_device.cpumask = cpumask_of(0);
258 clockevents_config_and_register(&mct_comp_device, clk_rate, 299 clockevents_config_and_register(&mct_comp_device, clk_rate,
259 0xf, 0xffffffff); 300 0xf, 0xffffffff);
260 301 setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
261 if (soc_is_exynos5250())
262 setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
263 else
264 setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
265} 302}
266 303
267#ifdef CONFIG_LOCAL_TIMERS 304#ifdef CONFIG_LOCAL_TIMERS
@@ -273,12 +310,12 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
273{ 310{
274 unsigned long tmp; 311 unsigned long tmp;
275 unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START; 312 unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
276 void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET; 313 unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
277 314
278 tmp = __raw_readl(addr); 315 tmp = __raw_readl(reg_base + offset);
279 if (tmp & mask) { 316 if (tmp & mask) {
280 tmp &= ~mask; 317 tmp &= ~mask;
281 exynos4_mct_write(tmp, addr); 318 exynos4_mct_write(tmp, offset);
282 } 319 }
283} 320}
284 321
@@ -297,7 +334,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
297 /* enable MCT tick interrupt */ 334 /* enable MCT tick interrupt */
298 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); 335 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
299 336
300 tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET); 337 tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
301 tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | 338 tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
302 MCT_L_TCON_INTERVAL_MODE; 339 MCT_L_TCON_INTERVAL_MODE;
303 exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); 340 exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -349,7 +386,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
349 exynos4_mct_tick_stop(mevt); 386 exynos4_mct_tick_stop(mevt);
350 387
351 /* Clear the MCT tick interrupt */ 388 /* Clear the MCT tick interrupt */
352 if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { 389 if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
353 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); 390 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
354 return 1; 391 return 1;
355 } else { 392 } else {
@@ -385,7 +422,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
385{ 422{
386 struct mct_clock_event_device *mevt; 423 struct mct_clock_event_device *mevt;
387 unsigned int cpu = smp_processor_id(); 424 unsigned int cpu = smp_processor_id();
388 int mct_lx_irq;
389 425
390 mevt = this_cpu_ptr(&percpu_mct_tick); 426 mevt = this_cpu_ptr(&percpu_mct_tick);
391 mevt->evt = evt; 427 mevt->evt = evt;
@@ -406,21 +442,17 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
406 442
407 if (mct_int_type == MCT_INT_SPI) { 443 if (mct_int_type == MCT_INT_SPI) {
408 if (cpu == 0) { 444 if (cpu == 0) {
409 mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
410 EXYNOS5_IRQ_MCT_L0;
411 mct_tick0_event_irq.dev_id = mevt; 445 mct_tick0_event_irq.dev_id = mevt;
412 evt->irq = mct_lx_irq; 446 evt->irq = mct_irqs[MCT_L0_IRQ];
413 setup_irq(mct_lx_irq, &mct_tick0_event_irq); 447 setup_irq(evt->irq, &mct_tick0_event_irq);
414 } else { 448 } else {
415 mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
416 EXYNOS5_IRQ_MCT_L1;
417 mct_tick1_event_irq.dev_id = mevt; 449 mct_tick1_event_irq.dev_id = mevt;
418 evt->irq = mct_lx_irq; 450 evt->irq = mct_irqs[MCT_L1_IRQ];
419 setup_irq(mct_lx_irq, &mct_tick1_event_irq); 451 setup_irq(evt->irq, &mct_tick1_event_irq);
420 irq_set_affinity(mct_lx_irq, cpumask_of(1)); 452 irq_set_affinity(evt->irq, cpumask_of(1));
421 } 453 }
422 } else { 454 } else {
423 enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0); 455 enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
424 } 456 }
425 457
426 return 0; 458 return 0;
@@ -436,7 +468,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
436 else 468 else
437 remove_irq(evt->irq, &mct_tick1_event_irq); 469 remove_irq(evt->irq, &mct_tick1_event_irq);
438 else 470 else
439 disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER); 471 disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
440} 472}
441 473
442static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { 474static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
@@ -445,41 +477,74 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
445}; 477};
446#endif /* CONFIG_LOCAL_TIMERS */ 478#endif /* CONFIG_LOCAL_TIMERS */
447 479
448static void __init exynos4_timer_resources(void) 480static void __init exynos4_timer_resources(struct device_node *np)
449{ 481{
450 struct clk *mct_clk; 482 struct clk *mct_clk;
451 mct_clk = clk_get(NULL, "xtal"); 483 mct_clk = clk_get(NULL, "xtal");
452 484
453 clk_rate = clk_get_rate(mct_clk); 485 clk_rate = clk_get_rate(mct_clk);
454 486
487 reg_base = np ? of_iomap(np, 0) : S5P_VA_SYSTIMER;
488 if (!reg_base)
489 panic("%s: unable to ioremap mct address space\n", __func__);
490
455#ifdef CONFIG_LOCAL_TIMERS 491#ifdef CONFIG_LOCAL_TIMERS
456 if (mct_int_type == MCT_INT_PPI) { 492 if (mct_int_type == MCT_INT_PPI) {
457 int err; 493 int err;
458 494
459 err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 495 err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
460 exynos4_mct_tick_isr, "MCT", 496 exynos4_mct_tick_isr, "MCT",
461 &percpu_mct_tick); 497 &percpu_mct_tick);
462 WARN(err, "MCT: can't request IRQ %d (%d)\n", 498 WARN(err, "MCT: can't request IRQ %d (%d)\n",
463 EXYNOS_IRQ_MCT_LOCALTIMER, err); 499 mct_irqs[MCT_L0_IRQ], err);
464 } 500 }
465 501
466 local_timer_register(&exynos4_mct_tick_ops); 502 local_timer_register(&exynos4_mct_tick_ops);
467#endif /* CONFIG_LOCAL_TIMERS */ 503#endif /* CONFIG_LOCAL_TIMERS */
468} 504}
469 505
470void __init exynos4_timer_init(void) 506static const struct of_device_id exynos_mct_ids[] = {
471{ 507 { .compatible = "samsung,exynos4210-mct", .data = (void *)MCT_INT_SPI },
472 if (soc_is_exynos5440()) { 508 { .compatible = "samsung,exynos4412-mct", .data = (void *)MCT_INT_PPI },
473 arch_timer_of_register(); 509};
474 return;
475 }
476 510
477 if ((soc_is_exynos4210()) || (soc_is_exynos5250())) 511void __init mct_init(void)
512{
513 struct device_node *np = NULL;
514 const struct of_device_id *match;
515 u32 nr_irqs, i;
516
517#ifdef CONFIG_OF
518 np = of_find_matching_node_and_match(NULL, exynos_mct_ids, &match);
519#endif
520 if (np) {
521 mct_int_type = (u32)(match->data);
522
523 /* This driver uses only one global timer interrupt */
524 mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
525
526 /*
527 * Find out the number of local irqs specified. The local
528 * timer irqs are specified after the four global timer
529 * irqs are specified.
530 */
531#ifdef CONFIG_OF
532 nr_irqs = of_irq_count(np);
533#endif
534 for (i = MCT_L0_IRQ; i < nr_irqs; i++)
535 mct_irqs[i] = irq_of_parse_and_map(np, i);
536 } else if (soc_is_exynos4210()) {
537 mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
538 mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
539 mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
478 mct_int_type = MCT_INT_SPI; 540 mct_int_type = MCT_INT_SPI;
479 else 541 } else {
480 mct_int_type = MCT_INT_PPI; 542 panic("unable to determine mct controller type\n");
543 }
481 544
482 exynos4_timer_resources(); 545 exynos4_timer_resources(np);
483 exynos4_clocksource_init(); 546 exynos4_clocksource_init();
484 exynos4_clockevent_init(); 547 exynos4_clockevent_init();
485} 548}
549CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init)
550CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init)