aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-09 16:07:37 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-09 16:18:24 -0400
commit228e3023eb0430b4b9ed0736f8f87c96a6cd9c7a (patch)
tree4115d59b698a2a6e1953c5b263cab6d2a113d81b
parent894b7382cf20e81d38097d43b8802af6e79d48c4 (diff)
parent354599f460ba79c9fb00f220e42de5a7509ceeb4 (diff)
Merge tag 'mct-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers
From Kukjin Kim <kgene.kim@samsung.com>: add support exynos mct device tree and move into drivers/clocksource * tag 'mct-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: clocksource: mct: Add terminating entry for exynos_mct_ids table clocksource: mct: Add missing semicolons in exynos_mct.c ARM: EXYNOS: move mct driver to drivers/clocksource ARM: EXYNOS: remove static io-remapping of mct registers for Exynos5 ARM: dts: add mct device tree node for all supported Exynos SoC's ARM: EXYNOS: allow dt based discovery of mct controller using clocksource_of_init ARM: EXYNOS: add device tree support for MCT controller driver ARM: EXYNOS: prepare an array of MCT interrupt numbers and use it ARM: EXYNOS: add a register base address variable in mct controller driver Conflicts: drivers/clocksource/Makefile drivers/clocksource/exynos_mct.c [arnd: adapt to CLOCKSOURCE_OF_DECLARE interface change] Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-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/Makefile3
-rw-r--r--drivers/clocksource/exynos_mct.c (renamed from arch/arm/mach-exynos/mct.c)199
23 files changed, 315 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 6adf79869f8c..03301cb114ac 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1654,7 +1654,7 @@ config LOCAL_TIMERS
1654 bool "Use local timer interrupts" 1654 bool "Use local timer interrupts"
1655 depends on SMP 1655 depends on SMP
1656 default y 1656 default y
1657 select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) 1657 select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !CLKSRC_EXYNOS_MCT)
1658 help 1658 help
1659 Enable support for local timers on SMP platforms, rather then the 1659 Enable support for local timers on SMP platforms, rather then the
1660 legacy IPI broadcast method. Local timers allows the system 1660 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 b1ac73e21c80..c60108e0d27e 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -69,6 +69,28 @@
69 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; 69 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
70 }; 70 };
71 71
72 mct@101C0000 {
73 compatible = "samsung,exynos4210-mct";
74 reg = <0x101C0000 0x800>;
75 interrupt-controller;
76 #interrups-cells = <2>;
77 interrupt-parent = <&mct_map>;
78 interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
79 <4 0>, <5 0>;
80
81 mct_map: mct-map {
82 #interrupt-cells = <2>;
83 #address-cells = <0>;
84 #size-cells = <0>;
85 interrupt-map = <0x0 0 &combiner 23 3>,
86 <0x1 0 &combiner 23 4>,
87 <0x2 0 &combiner 25 2>,
88 <0x3 0 &combiner 25 3>,
89 <0x4 0 &gic 0 120 0>,
90 <0x5 0 &gic 0 121 0>;
91 };
92 };
93
72 watchdog { 94 watchdog {
73 compatible = "samsung,s3c2410-wdt"; 95 compatible = "samsung,s3c2410-wdt";
74 reg = <0x101D0000 0x100>; 96 reg = <0x101D0000 0x100>;
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 2f45906d6ee5..faca4326b46a 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -79,12 +79,6 @@ config SOC_EXYNOS5440
79 help 79 help
80 Enable EXYNOS5440 SoC support 80 Enable EXYNOS5440 SoC support
81 81
82config EXYNOS4_MCT
83 bool
84 default y
85 help
86 Use MCT (Multi Core Timer) as kernel timers
87
88config EXYNOS_DEV_DMA 82config EXYNOS_DEV_DMA
89 bool 83 bool
90 help 84 help
@@ -406,6 +400,7 @@ config MACH_EXYNOS4_DT
406 bool "Samsung Exynos4 Machine using device tree" 400 bool "Samsung Exynos4 Machine using device tree"
407 depends on ARCH_EXYNOS4 401 depends on ARCH_EXYNOS4
408 select ARM_AMBA 402 select ARM_AMBA
403 select CLKSRC_OF
409 select CPU_EXYNOS4210 404 select CPU_EXYNOS4210
410 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD 405 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
411 select PINCTRL 406 select PINCTRL
@@ -422,6 +417,7 @@ config MACH_EXYNOS5_DT
422 default y 417 default y
423 depends on ARCH_EXYNOS5 418 depends on ARCH_EXYNOS5
424 select ARM_AMBA 419 select ARM_AMBA
420 select CLKSRC_OF
425 select USE_OF 421 select USE_OF
426 help 422 help
427 Machine support for Samsung EXYNOS5 machine with device tree enabled. 423 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 bdd957978d9b..db7dbd0eb6b4 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 3358088c822a..c4ae108e192d 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/of_platform.h> 14#include <linux/of_platform.h>
15#include <linux/serial_core.h> 15#include <linux/serial_core.h>
16#include <linux/clocksource.h>
16 17
17#include <asm/mach/arch.h> 18#include <asm/mach/arch.h>
18#include <mach/map.h> 19#include <mach/map.h>
@@ -142,7 +143,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
142 .map_io = exynos4_dt_map_io, 143 .map_io = exynos4_dt_map_io,
143 .init_machine = exynos4_dt_machine_init, 144 .init_machine = exynos4_dt_machine_init,
144 .init_late = exynos_init_late, 145 .init_late = exynos_init_late,
145 .init_time = exynos4_timer_init, 146 .init_time = clocksource_of_init,
146 .dt_compat = exynos4_dt_compat, 147 .dt_compat = exynos4_dt_compat,
147 .restart = exynos4_restart, 148 .restart = exynos4_restart,
148MACHINE_END 149MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index acaeb14db54b..7da4791bfb8b 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>
@@ -216,7 +217,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
216 .map_io = exynos5_dt_map_io, 217 .map_io = exynos5_dt_map_io,
217 .init_machine = exynos5_dt_machine_init, 218 .init_machine = exynos5_dt_machine_init,
218 .init_late = exynos_init_late, 219 .init_late = exynos_init_late,
219 .init_time = exynos4_timer_init, 220 .init_time = clocksource_of_init,
220 .dt_compat = exynos5_dt_compat, 221 .dt_compat = exynos5_dt_compat,
221 .restart = exynos5_restart, 222 .restart = exynos5_restart,
222 .reserve = exynos5_reserve, 223 .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 3167fda9bbb3..73fcddb8314d 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -70,3 +70,8 @@ config CLKSRC_METAG_GENERIC
70 def_bool y if METAG 70 def_bool y if METAG
71 help 71 help
72 This option enables support for the Meta per-thread timers. 72 This option enables support for the Meta per-thread timers.
73
74config CLKSRC_EXYNOS_MCT
75 def_bool y if ARCH_EXYNOS
76 help
77 Support for Multi Core Timer controller on Exynos SoCs.
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index e74c8ce26bf0..cd1f09cbd61a 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -19,7 +19,8 @@ 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_CADENCE_TTC_TIMER) += cadence_ttc_timer.o 22obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o
23obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
23 24
24obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o 25obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
25obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o 26obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
diff --git a/arch/arm/mach-exynos/mct.c b/drivers/clocksource/exynos_mct.c
index c9d6650f9b5d..957af8636c9d 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,80 @@ 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(void __iomem *base)
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 = base;
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) 506void __init mct_init(void)
471{ 507{
472 if (soc_is_exynos5440()) { 508 if (soc_is_exynos4210()) {
473 arch_timer_of_register(); 509 mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
474 return; 510 mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
511 mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
512 mct_int_type = MCT_INT_SPI;
513 } else {
514 panic("unable to determine mct controller type\n");
475 } 515 }
476 516
477 if ((soc_is_exynos4210()) || (soc_is_exynos5250())) 517 exynos4_timer_resources(S5P_VA_SYSTIMER);
478 mct_int_type = MCT_INT_SPI; 518 exynos4_clocksource_init();
479 else 519 exynos4_clockevent_init();
480 mct_int_type = MCT_INT_PPI; 520}
481 521
482 exynos4_timer_resources(); 522static void __init mct_init_dt(struct device_node *np, unsigned int int_type)
523{
524 u32 nr_irqs, i;
525
526 mct_int_type = int_type;
527
528 /* This driver uses only one global timer interrupt */
529 mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
530
531 /*
532 * Find out the number of local irqs specified. The local
533 * timer irqs are specified after the four global timer
534 * irqs are specified.
535 */
536 nr_irqs = of_irq_count(np);
537 for (i = MCT_L0_IRQ; i < nr_irqs; i++)
538 mct_irqs[i] = irq_of_parse_and_map(np, i);
539
540 exynos4_timer_resources(of_iomap(np, 0));
483 exynos4_clocksource_init(); 541 exynos4_clocksource_init();
484 exynos4_clockevent_init(); 542 exynos4_clockevent_init();
485} 543}
544
545
546static void __init mct_init_spi(struct device_node *np)
547{
548 return mct_init_dt(np, MCT_INT_SPI);
549}
550
551static void __init mct_init_ppi(struct device_node *np)
552{
553 return mct_init_dt(np, MCT_INT_PPI);
554}
555CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
556CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);