mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	add support exynos mct device tree and move into drivers/clocksource
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRYugaAAoJEA0Cl+kVi2xqvi0QAKyF/UbDR6aOSIOoCzgm1iUC +F9WvvCLyJdy0y09IKEbwM+aZyzsfC7vO/9wp58ROv1AhD9f1/yk1H+O8NRS668v jt8RZlrL30ea0HkRjHRgTCS2sObCXG2pGOduX9i5XKCC4EnM9P/qNe4uJjziY8K8 FmAanWpJahe0E9szLnWDuF7hhsRkTpjrLWtYYmc1H4LXydoZnxEgGM3xjbqL+m4/ BPwlCrPtu/WsZzM7Tdx6fVIC2wryrwoH5e1EL3fI2IrWhreOtVWYzoTwUoSy7Xbz ERjQoCt3yNVmPO1TwfS9nR/bc0+j8gsFuJRzN42PsP09JFQPVt8Q1o1cpIIHWgvZ /pkJAsaBfbQgPOLNof5uHasPVSZYe38TIey782hYA0pmT1RCt46FuJ6zM9M0483q 4vysYCU/Vc3GOtAQOpsCNbsEMthRzjtjsJoZ5owDsCaiV+eNWC3VrWI2Wm1EO7Mn FUthkBY58jPM/9BdFC67ZwBPtSSUhAeZpcUXkcaNj8pgw8Rvfcip/09Vy0Uh0Ef8 A5dYZec8CNyZKECspzUTlgwyK7xiWD0r3uyr4/a413qb1pr9zdOFlZeespT9bgfI uD+tMPpJ+R9fK9BSbRw9FMx1Pe395vZRUmu9WepvQDwQDvoYSi/SVKBMYtn27Bsm CD/r/wUs1ktL2rPNcXVz =Os9U -----END PGP SIGNATURE----- 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>
This commit is contained in:
		
						commit
						228e3023eb
					
				
					 23 changed files with 316 additions and 150 deletions
				
			
		| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					Samsung's Multi Core Timer (MCT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
 | 
				
			||||||
 | 
					global timer and CPU local timers. The global timer is a 64-bit free running
 | 
				
			||||||
 | 
					up-counter and can generate 4 interrupts when the counter reaches one of the
 | 
				
			||||||
 | 
					four preset counter values. The CPU local timers are 32-bit free running
 | 
				
			||||||
 | 
					down-counters and generate an interrupt when the counter expires. There is
 | 
				
			||||||
 | 
					one CPU local timer instantiated in MCT for every CPU in the system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Required properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- compatible: should be "samsung,exynos4210-mct".
 | 
				
			||||||
 | 
					  (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
 | 
				
			||||||
 | 
					  (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- reg: base address of the mct controller and length of the address space
 | 
				
			||||||
 | 
					  it occupies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- interrupts: the list of interrupts generated by the controller. The following
 | 
				
			||||||
 | 
					  should be the order of the interrupts specified. The local timer interrupts
 | 
				
			||||||
 | 
					  should be specified after the four global timer interrupts have been
 | 
				
			||||||
 | 
					  specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						0: Global Timer Interrupt 0
 | 
				
			||||||
 | 
						1: Global Timer Interrupt 1
 | 
				
			||||||
 | 
						2: Global Timer Interrupt 2
 | 
				
			||||||
 | 
						3: Global Timer Interrupt 3
 | 
				
			||||||
 | 
						4: Local Timer Interrupt 0
 | 
				
			||||||
 | 
						5: Local Timer Interrupt 1
 | 
				
			||||||
 | 
						6: ..
 | 
				
			||||||
 | 
						7: ..
 | 
				
			||||||
 | 
						i: Local Timer Interrupt n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example 1: In this example, the system uses only the first global timer
 | 
				
			||||||
 | 
						   interrupt generated by MCT and the remaining three global timer
 | 
				
			||||||
 | 
						   interrupts are unused. Two local timer interrupts have been
 | 
				
			||||||
 | 
						   specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@10050000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4210-mct";
 | 
				
			||||||
 | 
							reg = <0x10050000 0x800>;
 | 
				
			||||||
 | 
							interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
 | 
				
			||||||
 | 
								     <0 42 0>, <0 48 0>;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example 2: In this example, the MCT global and local timer interrupts are
 | 
				
			||||||
 | 
						   connected to two seperate interrupt controllers. Hence, an
 | 
				
			||||||
 | 
						   interrupt-map is created to map the interrupts to the respective
 | 
				
			||||||
 | 
						   interrupt controllers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@101C0000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4210-mct";
 | 
				
			||||||
 | 
							reg = <0x101C0000 0x800>;
 | 
				
			||||||
 | 
							interrupt-controller;
 | 
				
			||||||
 | 
							#interrups-cells = <2>;
 | 
				
			||||||
 | 
							interrupt-parent = <&mct_map>;
 | 
				
			||||||
 | 
							interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
 | 
				
			||||||
 | 
								     <4 0>, <5 0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mct_map: mct-map {
 | 
				
			||||||
 | 
								#interrupt-cells = <2>;
 | 
				
			||||||
 | 
								#address-cells = <0>;
 | 
				
			||||||
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
								interrupt-map = <0x0 0 &combiner 23 3>,
 | 
				
			||||||
 | 
										<0x4 0 &gic 0 120 0>,
 | 
				
			||||||
 | 
										<0x5 0 &gic 0 121 0>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
| 
						 | 
					@ -1654,7 +1654,7 @@ config LOCAL_TIMERS
 | 
				
			||||||
	bool "Use local timer interrupts"
 | 
						bool "Use local timer interrupts"
 | 
				
			||||||
	depends on SMP
 | 
						depends on SMP
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
	select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
 | 
						select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !CLKSRC_EXYNOS_MCT)
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Enable support for local timers on SMP platforms, rather then the
 | 
						  Enable support for local timers on SMP platforms, rather then the
 | 
				
			||||||
	  legacy IPI broadcast method.  Local timers allows the system
 | 
						  legacy IPI broadcast method.  Local timers allows the system
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,28 @@ combiner:interrupt-controller@10440000 {
 | 
				
			||||||
			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 | 
								     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@10050000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4210-mct";
 | 
				
			||||||
 | 
							reg = <0x10050000 0x800>;
 | 
				
			||||||
 | 
							interrupt-controller;
 | 
				
			||||||
 | 
							#interrups-cells = <2>;
 | 
				
			||||||
 | 
							interrupt-parent = <&mct_map>;
 | 
				
			||||||
 | 
							interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
 | 
				
			||||||
 | 
								     <4 0>, <5 0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mct_map: mct-map {
 | 
				
			||||||
 | 
								#interrupt-cells = <2>;
 | 
				
			||||||
 | 
								#address-cells = <0>;
 | 
				
			||||||
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
								interrupt-map = <0x0 0 &gic 0 57 0>,
 | 
				
			||||||
 | 
										<0x1 0 &gic 0 69 0>,
 | 
				
			||||||
 | 
										<0x2 0 &combiner 12 6>,
 | 
				
			||||||
 | 
										<0x3 0 &combiner 12 7>,
 | 
				
			||||||
 | 
										<0x4 0 &gic 0 42 0>,
 | 
				
			||||||
 | 
										<0x5 0 &gic 0 48 0>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pinctrl_0: pinctrl@11400000 {
 | 
						pinctrl_0: pinctrl@11400000 {
 | 
				
			||||||
		compatible = "samsung,exynos4210-pinctrl";
 | 
							compatible = "samsung,exynos4210-pinctrl";
 | 
				
			||||||
		reg = <0x11400000 0x1000>;
 | 
							reg = <0x11400000 0x1000>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,4 +25,26 @@ / {
 | 
				
			||||||
	gic:interrupt-controller@10490000 {
 | 
						gic:interrupt-controller@10490000 {
 | 
				
			||||||
		cpu-offset = <0x8000>;
 | 
							cpu-offset = <0x8000>;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@10050000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4412-mct";
 | 
				
			||||||
 | 
							reg = <0x10050000 0x800>;
 | 
				
			||||||
 | 
							interrupt-controller;
 | 
				
			||||||
 | 
							#interrups-cells = <2>;
 | 
				
			||||||
 | 
							interrupt-parent = <&mct_map>;
 | 
				
			||||||
 | 
							interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
 | 
				
			||||||
 | 
								     <4 0>, <5 0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mct_map: mct-map {
 | 
				
			||||||
 | 
								#interrupt-cells = <2>;
 | 
				
			||||||
 | 
								#address-cells = <0>;
 | 
				
			||||||
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
								interrupt-map = <0x0 0 &gic 0 57 0>,
 | 
				
			||||||
 | 
										<0x1 0 &combiner 12 5>,
 | 
				
			||||||
 | 
										<0x2 0 &combiner 12 6>,
 | 
				
			||||||
 | 
										<0x3 0 &combiner 12 7>,
 | 
				
			||||||
 | 
										<0x4 0 &gic 1 12 0>,
 | 
				
			||||||
 | 
										<0x5 0 &gic 1 12 0>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,4 +25,28 @@ / {
 | 
				
			||||||
	gic:interrupt-controller@10490000 {
 | 
						gic:interrupt-controller@10490000 {
 | 
				
			||||||
		cpu-offset = <0x4000>;
 | 
							cpu-offset = <0x4000>;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@10050000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4412-mct";
 | 
				
			||||||
 | 
							reg = <0x10050000 0x800>;
 | 
				
			||||||
 | 
							interrupt-controller;
 | 
				
			||||||
 | 
							#interrups-cells = <2>;
 | 
				
			||||||
 | 
							interrupt-parent = <&mct_map>;
 | 
				
			||||||
 | 
							interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
 | 
				
			||||||
 | 
								     <4 0>, <5 0>, <6 0>, <7 0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mct_map: mct-map {
 | 
				
			||||||
 | 
								#interrupt-cells = <2>;
 | 
				
			||||||
 | 
								#address-cells = <0>;
 | 
				
			||||||
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
								interrupt-map = <0x0 0 &gic 0 57 0>,
 | 
				
			||||||
 | 
										<0x1 0 &combiner 12 5>,
 | 
				
			||||||
 | 
										<0x2 0 &combiner 12 6>,
 | 
				
			||||||
 | 
										<0x3 0 &combiner 12 7>,
 | 
				
			||||||
 | 
										<0x4 0 &gic 1 12 0>,
 | 
				
			||||||
 | 
										<0x5 0 &gic 1 12 0>,
 | 
				
			||||||
 | 
										<0x6 0 &gic 1 12 0>,
 | 
				
			||||||
 | 
										<0x7 0 &gic 1 12 0>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,28 @@ combiner:interrupt-controller@10440000 {
 | 
				
			||||||
			     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 | 
								     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct@101C0000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos4210-mct";
 | 
				
			||||||
 | 
							reg = <0x101C0000 0x800>;
 | 
				
			||||||
 | 
							interrupt-controller;
 | 
				
			||||||
 | 
							#interrups-cells = <2>;
 | 
				
			||||||
 | 
							interrupt-parent = <&mct_map>;
 | 
				
			||||||
 | 
							interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
 | 
				
			||||||
 | 
								     <4 0>, <5 0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mct_map: mct-map {
 | 
				
			||||||
 | 
								#interrupt-cells = <2>;
 | 
				
			||||||
 | 
								#address-cells = <0>;
 | 
				
			||||||
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
								interrupt-map = <0x0 0 &combiner 23 3>,
 | 
				
			||||||
 | 
										<0x1 0 &combiner 23 4>,
 | 
				
			||||||
 | 
										<0x2 0 &combiner 25 2>,
 | 
				
			||||||
 | 
										<0x3 0 &combiner 25 3>,
 | 
				
			||||||
 | 
										<0x4 0 &gic 0 120 0>,
 | 
				
			||||||
 | 
										<0x5 0 &gic 0 121 0>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	watchdog {
 | 
						watchdog {
 | 
				
			||||||
		compatible = "samsung,s3c2410-wdt";
 | 
							compatible = "samsung,s3c2410-wdt";
 | 
				
			||||||
		reg = <0x101D0000 0x100>;
 | 
							reg = <0x101D0000 0x100>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,12 +79,6 @@ config SOC_EXYNOS5440
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Enable EXYNOS5440 SoC support
 | 
						  Enable EXYNOS5440 SoC support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config EXYNOS4_MCT
 | 
					 | 
				
			||||||
	bool
 | 
					 | 
				
			||||||
	default y
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	  Use MCT (Multi Core Timer) as kernel timers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config EXYNOS_DEV_DMA
 | 
					config EXYNOS_DEV_DMA
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
| 
						 | 
					@ -406,6 +400,7 @@ config MACH_EXYNOS4_DT
 | 
				
			||||||
	bool "Samsung Exynos4 Machine using device tree"
 | 
						bool "Samsung Exynos4 Machine using device tree"
 | 
				
			||||||
	depends on ARCH_EXYNOS4
 | 
						depends on ARCH_EXYNOS4
 | 
				
			||||||
	select ARM_AMBA
 | 
						select ARM_AMBA
 | 
				
			||||||
 | 
						select CLKSRC_OF
 | 
				
			||||||
	select CPU_EXYNOS4210
 | 
						select CPU_EXYNOS4210
 | 
				
			||||||
	select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
 | 
						select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
 | 
				
			||||||
	select PINCTRL
 | 
						select PINCTRL
 | 
				
			||||||
| 
						 | 
					@ -422,6 +417,7 @@ config MACH_EXYNOS5_DT
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
	depends on ARCH_EXYNOS5
 | 
						depends on ARCH_EXYNOS5
 | 
				
			||||||
	select ARM_AMBA
 | 
						select ARM_AMBA
 | 
				
			||||||
 | 
						select CLKSRC_OF
 | 
				
			||||||
	select USE_OF
 | 
						select USE_OF
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
 | 
						  Machine support for Samsung EXYNOS5 machine with device tree enabled.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,8 +26,6 @@ obj-$(CONFIG_ARCH_EXYNOS)	+= pmu.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 | 
					obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 | 
					obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# machine support
 | 
					# machine support
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,11 +256,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 | 
				
			||||||
		.pfn		= __phys_to_pfn(EXYNOS5_PA_SROMC),
 | 
							.pfn		= __phys_to_pfn(EXYNOS5_PA_SROMC),
 | 
				
			||||||
		.length		= SZ_4K,
 | 
							.length		= SZ_4K,
 | 
				
			||||||
		.type		= MT_DEVICE,
 | 
							.type		= MT_DEVICE,
 | 
				
			||||||
	}, {
 | 
					 | 
				
			||||||
		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
 | 
					 | 
				
			||||||
		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
 | 
					 | 
				
			||||||
		.length		= SZ_4K,
 | 
					 | 
				
			||||||
		.type		= MT_DEVICE,
 | 
					 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		.virtual	= (unsigned long)S5P_VA_SYSRAM,
 | 
							.virtual	= (unsigned long)S5P_VA_SYSRAM,
 | 
				
			||||||
		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 | 
							.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 | 
					#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 | 
				
			||||||
#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 | 
					#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void exynos4_timer_init(void);
 | 
					extern void mct_init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct map_desc;
 | 
					struct map_desc;
 | 
				
			||||||
void exynos_init_io(struct map_desc *mach_desc, int size);
 | 
					void exynos_init_io(struct map_desc *mach_desc, int size);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,8 +30,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* For EXYNOS4 and EXYNOS5 */
 | 
					/* For EXYNOS4 and EXYNOS5 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS_IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
 | 
					#define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* For EXYNOS4 SoCs */
 | 
					/* For EXYNOS4 SoCs */
 | 
				
			||||||
| 
						 | 
					@ -323,8 +321,6 @@
 | 
				
			||||||
#define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
 | 
					#define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
 | 
				
			||||||
#define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
 | 
					#define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS5_IRQ_MCT_L0		IRQ_SPI(120)
 | 
					 | 
				
			||||||
#define EXYNOS5_IRQ_MCT_L1		IRQ_SPI(121)
 | 
					 | 
				
			||||||
#define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
 | 
					#define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
 | 
				
			||||||
#define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
 | 
					#define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
 | 
				
			||||||
#define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
 | 
					#define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
 | 
				
			||||||
| 
						 | 
					@ -419,8 +415,6 @@
 | 
				
			||||||
#define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
 | 
					#define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
 | 
					#define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
 | 
				
			||||||
#define EXYNOS5_IRQ_MCT_G0		COMBINER_IRQ(23, 3)
 | 
					 | 
				
			||||||
#define EXYNOS5_IRQ_MCT_G1		COMBINER_IRQ(23, 4)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
 | 
					#define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
 | 
				
			||||||
#define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
 | 
					#define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,6 @@
 | 
				
			||||||
#define EXYNOS5_PA_CMU			0x10010000
 | 
					#define EXYNOS5_PA_CMU			0x10010000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS4_PA_SYSTIMER		0x10050000
 | 
					#define EXYNOS4_PA_SYSTIMER		0x10050000
 | 
				
			||||||
#define EXYNOS5_PA_SYSTIMER		0x101C0000
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXYNOS4_PA_WATCHDOG		0x10060000
 | 
					#define EXYNOS4_PA_WATCHDOG		0x10060000
 | 
				
			||||||
#define EXYNOS5_PA_WATCHDOG		0x101D0000
 | 
					#define EXYNOS5_PA_WATCHDOG		0x101D0000
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,53 +0,0 @@
 | 
				
			||||||
/* arch/arm/mach-exynos4/include/mach/regs-mct.h
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 | 
					 | 
				
			||||||
 *		http://www.samsung.com
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * EXYNOS4 MCT configutation
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License version 2 as
 | 
					 | 
				
			||||||
 * published by the Free Software Foundation.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __ASM_ARCH_REGS_MCT_H
 | 
					 | 
				
			||||||
#define __ASM_ARCH_REGS_MCT_H __FILE__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <mach/map.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
 | 
					 | 
				
			||||||
#define EXYNOS4_MCT_L_MASK		(0xffffff00)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MCT_L_TCNTB_OFFSET		(0x00)
 | 
					 | 
				
			||||||
#define MCT_L_ICNTB_OFFSET		(0x08)
 | 
					 | 
				
			||||||
#define MCT_L_TCON_OFFSET		(0x20)
 | 
					 | 
				
			||||||
#define MCT_L_INT_CSTAT_OFFSET		(0x30)
 | 
					 | 
				
			||||||
#define MCT_L_INT_ENB_OFFSET		(0x34)
 | 
					 | 
				
			||||||
#define MCT_L_WSTAT_OFFSET		(0x40)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MCT_G_TCON_START		(1 << 8)
 | 
					 | 
				
			||||||
#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
 | 
					 | 
				
			||||||
#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
 | 
					 | 
				
			||||||
#define MCT_L_TCON_INT_START		(1 << 1)
 | 
					 | 
				
			||||||
#define MCT_L_TCON_TIMER_START		(1 << 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* __ASM_ARCH_REGS_MCT_H */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -202,6 +202,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
 | 
				
			||||||
	.map_io		= armlex4210_map_io,
 | 
						.map_io		= armlex4210_map_io,
 | 
				
			||||||
	.init_machine	= armlex4210_machine_init,
 | 
						.init_machine	= armlex4210_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/of_platform.h>
 | 
					#include <linux/of_platform.h>
 | 
				
			||||||
#include <linux/serial_core.h>
 | 
					#include <linux/serial_core.h>
 | 
				
			||||||
 | 
					#include <linux/clocksource.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/mach/arch.h>
 | 
					#include <asm/mach/arch.h>
 | 
				
			||||||
#include <mach/map.h>
 | 
					#include <mach/map.h>
 | 
				
			||||||
| 
						 | 
					@ -142,7 +143,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
 | 
				
			||||||
	.map_io		= exynos4_dt_map_io,
 | 
						.map_io		= exynos4_dt_map_io,
 | 
				
			||||||
	.init_machine	= exynos4_dt_machine_init,
 | 
						.init_machine	= exynos4_dt_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= clocksource_of_init,
 | 
				
			||||||
	.dt_compat	= exynos4_dt_compat,
 | 
						.dt_compat	= exynos4_dt_compat,
 | 
				
			||||||
	.restart        = exynos4_restart,
 | 
						.restart        = exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@
 | 
				
			||||||
#include <linux/serial_core.h>
 | 
					#include <linux/serial_core.h>
 | 
				
			||||||
#include <linux/memblock.h>
 | 
					#include <linux/memblock.h>
 | 
				
			||||||
#include <linux/io.h>
 | 
					#include <linux/io.h>
 | 
				
			||||||
 | 
					#include <linux/clocksource.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/mach/arch.h>
 | 
					#include <asm/mach/arch.h>
 | 
				
			||||||
#include <mach/map.h>
 | 
					#include <mach/map.h>
 | 
				
			||||||
| 
						 | 
					@ -216,7 +217,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
 | 
				
			||||||
	.map_io		= exynos5_dt_map_io,
 | 
						.map_io		= exynos5_dt_map_io,
 | 
				
			||||||
	.init_machine	= exynos5_dt_machine_init,
 | 
						.init_machine	= exynos5_dt_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= clocksource_of_init,
 | 
				
			||||||
	.dt_compat	= exynos5_dt_compat,
 | 
						.dt_compat	= exynos5_dt_compat,
 | 
				
			||||||
	.restart        = exynos5_restart,
 | 
						.restart        = exynos5_restart,
 | 
				
			||||||
	.reserve	= exynos5_reserve,
 | 
						.reserve	= exynos5_reserve,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1380,7 +1380,7 @@ MACHINE_START(NURI, "NURI")
 | 
				
			||||||
	.map_io		= nuri_map_io,
 | 
						.map_io		= nuri_map_io,
 | 
				
			||||||
	.init_machine	= nuri_machine_init,
 | 
						.init_machine	= nuri_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.reserve        = &nuri_reserve,
 | 
						.reserve        = &nuri_reserve,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -815,7 +815,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
 | 
				
			||||||
	.map_io		= origen_map_io,
 | 
						.map_io		= origen_map_io,
 | 
				
			||||||
	.init_machine	= origen_machine_init,
 | 
						.init_machine	= origen_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.reserve	= &origen_reserve,
 | 
						.reserve	= &origen_reserve,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
 | 
				
			||||||
	.init_irq	= exynos4_init_irq,
 | 
						.init_irq	= exynos4_init_irq,
 | 
				
			||||||
	.map_io		= smdk4x12_map_io,
 | 
						.map_io		= smdk4x12_map_io,
 | 
				
			||||||
	.init_machine	= smdk4x12_machine_init,
 | 
						.init_machine	= smdk4x12_machine_init,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
	.reserve	= &smdk4x12_reserve,
 | 
						.reserve	= &smdk4x12_reserve,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					@ -390,7 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
 | 
				
			||||||
	.map_io		= smdk4x12_map_io,
 | 
						.map_io		= smdk4x12_map_io,
 | 
				
			||||||
	.init_machine	= smdk4x12_machine_init,
 | 
						.init_machine	= smdk4x12_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
	.reserve	= &smdk4x12_reserve,
 | 
						.reserve	= &smdk4x12_reserve,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -423,7 +423,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
 | 
				
			||||||
	.init_irq	= exynos4_init_irq,
 | 
						.init_irq	= exynos4_init_irq,
 | 
				
			||||||
	.map_io		= smdkv310_map_io,
 | 
						.map_io		= smdkv310_map_io,
 | 
				
			||||||
	.init_machine	= smdkv310_machine_init,
 | 
						.init_machine	= smdkv310_machine_init,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.reserve	= &smdkv310_reserve,
 | 
						.reserve	= &smdkv310_reserve,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					@ -436,7 +436,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
 | 
				
			||||||
	.map_io		= smdkv310_map_io,
 | 
						.map_io		= smdkv310_map_io,
 | 
				
			||||||
	.init_machine	= smdkv310_machine_init,
 | 
						.init_machine	= smdkv310_machine_init,
 | 
				
			||||||
	.init_late	= exynos_init_late,
 | 
						.init_late	= exynos_init_late,
 | 
				
			||||||
	.init_time	= exynos4_timer_init,
 | 
						.init_time	= mct_init,
 | 
				
			||||||
	.reserve	= &smdkv310_reserve,
 | 
						.reserve	= &smdkv310_reserve,
 | 
				
			||||||
	.restart	= exynos4_restart,
 | 
						.restart	= exynos4_restart,
 | 
				
			||||||
MACHINE_END
 | 
					MACHINE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,3 +70,8 @@ config CLKSRC_METAG_GENERIC
 | 
				
			||||||
	def_bool y if METAG
 | 
						def_bool y if METAG
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  This option enables support for the Meta per-thread timers.
 | 
						  This option enables support for the Meta per-thread timers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config CLKSRC_EXYNOS_MCT
 | 
				
			||||||
 | 
						def_bool y if ARCH_EXYNOS
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Support for Multi Core Timer controller on Exynos SoCs.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
 | 
				
			||||||
obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
 | 
					obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
 | 
				
			||||||
obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
 | 
					obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
 | 
				
			||||||
obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence_ttc_timer.o
 | 
					obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence_ttc_timer.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 | 
					obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 | 
				
			||||||
obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 | 
					obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,9 @@
 | 
				
			||||||
#include <linux/delay.h>
 | 
					#include <linux/delay.h>
 | 
				
			||||||
#include <linux/percpu.h>
 | 
					#include <linux/percpu.h>
 | 
				
			||||||
#include <linux/of.h>
 | 
					#include <linux/of.h>
 | 
				
			||||||
 | 
					#include <linux/of_irq.h>
 | 
				
			||||||
 | 
					#include <linux/of_address.h>
 | 
				
			||||||
 | 
					#include <linux/clocksource.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/arch_timer.h>
 | 
					#include <asm/arch_timer.h>
 | 
				
			||||||
#include <asm/localtimer.h>
 | 
					#include <asm/localtimer.h>
 | 
				
			||||||
| 
						 | 
					@ -28,9 +31,36 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <mach/map.h>
 | 
					#include <mach/map.h>
 | 
				
			||||||
#include <mach/irqs.h>
 | 
					#include <mach/irqs.h>
 | 
				
			||||||
#include <mach/regs-mct.h>
 | 
					 | 
				
			||||||
#include <asm/mach/time.h>
 | 
					#include <asm/mach/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXYNOS4_MCTREG(x)		(x)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
 | 
				
			||||||
 | 
					#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
 | 
				
			||||||
 | 
					#define EXYNOS4_MCT_L_MASK		(0xffffff00)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MCT_L_TCNTB_OFFSET		(0x00)
 | 
				
			||||||
 | 
					#define MCT_L_ICNTB_OFFSET		(0x08)
 | 
				
			||||||
 | 
					#define MCT_L_TCON_OFFSET		(0x20)
 | 
				
			||||||
 | 
					#define MCT_L_INT_CSTAT_OFFSET		(0x30)
 | 
				
			||||||
 | 
					#define MCT_L_INT_ENB_OFFSET		(0x34)
 | 
				
			||||||
 | 
					#define MCT_L_WSTAT_OFFSET		(0x40)
 | 
				
			||||||
 | 
					#define MCT_G_TCON_START		(1 << 8)
 | 
				
			||||||
 | 
					#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
 | 
				
			||||||
 | 
					#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
 | 
				
			||||||
 | 
					#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
 | 
				
			||||||
 | 
					#define MCT_L_TCON_INT_START		(1 << 1)
 | 
				
			||||||
 | 
					#define MCT_L_TCON_TIMER_START		(1 << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TICK_BASE_CNT	1
 | 
					#define TICK_BASE_CNT	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
| 
						 | 
					@ -38,64 +68,75 @@ enum {
 | 
				
			||||||
	MCT_INT_PPI
 | 
						MCT_INT_PPI
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MCT_G0_IRQ,
 | 
				
			||||||
 | 
						MCT_G1_IRQ,
 | 
				
			||||||
 | 
						MCT_G2_IRQ,
 | 
				
			||||||
 | 
						MCT_G3_IRQ,
 | 
				
			||||||
 | 
						MCT_L0_IRQ,
 | 
				
			||||||
 | 
						MCT_L1_IRQ,
 | 
				
			||||||
 | 
						MCT_L2_IRQ,
 | 
				
			||||||
 | 
						MCT_L3_IRQ,
 | 
				
			||||||
 | 
						MCT_NR_IRQS,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __iomem *reg_base;
 | 
				
			||||||
static unsigned long clk_rate;
 | 
					static unsigned long clk_rate;
 | 
				
			||||||
static unsigned int mct_int_type;
 | 
					static unsigned int mct_int_type;
 | 
				
			||||||
 | 
					static int mct_irqs[MCT_NR_IRQS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mct_clock_event_device {
 | 
					struct mct_clock_event_device {
 | 
				
			||||||
	struct clock_event_device *evt;
 | 
						struct clock_event_device *evt;
 | 
				
			||||||
	void __iomem *base;
 | 
						unsigned long base;
 | 
				
			||||||
	char name[10];
 | 
						char name[10];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void exynos4_mct_write(unsigned int value, void *addr)
 | 
					static void exynos4_mct_write(unsigned int value, unsigned long offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void __iomem *stat_addr;
 | 
						unsigned long stat_addr;
 | 
				
			||||||
	u32 mask;
 | 
						u32 mask;
 | 
				
			||||||
	u32 i;
 | 
						u32 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__raw_writel(value, addr);
 | 
						__raw_writel(value, reg_base + offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
 | 
						if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
 | 
				
			||||||
		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
 | 
							stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
 | 
				
			||||||
		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
 | 
							switch (offset & EXYNOS4_MCT_L_MASK) {
 | 
				
			||||||
		case (u32) MCT_L_TCON_OFFSET:
 | 
							case MCT_L_TCON_OFFSET:
 | 
				
			||||||
			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
 | 
					 | 
				
			||||||
			mask = 1 << 3;		/* L_TCON write status */
 | 
								mask = 1 << 3;		/* L_TCON write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) MCT_L_ICNTB_OFFSET:
 | 
							case MCT_L_ICNTB_OFFSET:
 | 
				
			||||||
			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
 | 
					 | 
				
			||||||
			mask = 1 << 1;		/* L_ICNTB write status */
 | 
								mask = 1 << 1;		/* L_ICNTB write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) MCT_L_TCNTB_OFFSET:
 | 
							case MCT_L_TCNTB_OFFSET:
 | 
				
			||||||
			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
 | 
					 | 
				
			||||||
			mask = 1 << 0;		/* L_TCNTB write status */
 | 
								mask = 1 << 0;		/* L_TCNTB write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		switch ((u32) addr) {
 | 
							switch (offset) {
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_TCON:
 | 
							case EXYNOS4_MCT_G_TCON:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
				
			||||||
			mask = 1 << 16;		/* G_TCON write status */
 | 
								mask = 1 << 16;		/* G_TCON write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_COMP0_L:
 | 
							case EXYNOS4_MCT_G_COMP0_L:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
				
			||||||
			mask = 1 << 0;		/* G_COMP0_L write status */
 | 
								mask = 1 << 0;		/* G_COMP0_L write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_COMP0_U:
 | 
							case EXYNOS4_MCT_G_COMP0_U:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
				
			||||||
			mask = 1 << 1;		/* G_COMP0_U write status */
 | 
								mask = 1 << 1;		/* G_COMP0_U write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
 | 
							case EXYNOS4_MCT_G_COMP0_ADD_INCR:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_WSTAT;
 | 
				
			||||||
			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
 | 
								mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_CNT_L:
 | 
							case EXYNOS4_MCT_G_CNT_L:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 | 
				
			||||||
			mask = 1 << 0;		/* G_CNT_L write status */
 | 
								mask = 1 << 0;		/* G_CNT_L write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (u32) EXYNOS4_MCT_G_CNT_U:
 | 
							case EXYNOS4_MCT_G_CNT_U:
 | 
				
			||||||
			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 | 
								stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 | 
				
			||||||
			mask = 1 << 1;		/* G_CNT_U write status */
 | 
								mask = 1 << 1;		/* G_CNT_U write status */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -106,12 +147,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Wait maximum 1 ms until written values are applied */
 | 
						/* Wait maximum 1 ms until written values are applied */
 | 
				
			||||||
	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
 | 
						for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
 | 
				
			||||||
		if (__raw_readl(stat_addr) & mask) {
 | 
							if (__raw_readl(reg_base + stat_addr) & mask) {
 | 
				
			||||||
			__raw_writel(mask, stat_addr);
 | 
								__raw_writel(mask, reg_base + stat_addr);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
 | 
						panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Clocksource handling */
 | 
					/* Clocksource handling */
 | 
				
			||||||
| 
						 | 
					@ -122,7 +163,7 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 | 
				
			||||||
	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
 | 
						exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
 | 
				
			||||||
	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
 | 
						exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
 | 
						reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 | 
				
			||||||
	reg |= MCT_G_TCON_START;
 | 
						reg |= MCT_G_TCON_START;
 | 
				
			||||||
	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 | 
						exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -130,12 +171,12 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 | 
				
			||||||
static cycle_t exynos4_frc_read(struct clocksource *cs)
 | 
					static cycle_t exynos4_frc_read(struct clocksource *cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int lo, hi;
 | 
						unsigned int lo, hi;
 | 
				
			||||||
	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
 | 
						u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		hi = hi2;
 | 
							hi = hi2;
 | 
				
			||||||
		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
 | 
							lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
 | 
				
			||||||
		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
 | 
							hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 | 
				
			||||||
	} while (hi != hi2);
 | 
						} while (hi != hi2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ((cycle_t)hi << 32) | lo;
 | 
						return ((cycle_t)hi << 32) | lo;
 | 
				
			||||||
| 
						 | 
					@ -167,7 +208,7 @@ static void exynos4_mct_comp0_stop(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int tcon;
 | 
						unsigned int tcon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
 | 
						tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 | 
				
			||||||
	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 | 
						tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
 | 
						exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
 | 
				
			||||||
| 
						 | 
					@ -180,7 +221,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
 | 
				
			||||||
	unsigned int tcon;
 | 
						unsigned int tcon;
 | 
				
			||||||
	cycle_t comp_cycle;
 | 
						cycle_t comp_cycle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
 | 
						tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mode == CLOCK_EVT_MODE_PERIODIC) {
 | 
						if (mode == CLOCK_EVT_MODE_PERIODIC) {
 | 
				
			||||||
		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
 | 
							tcon |= MCT_G_TCON_COMP0_AUTO_INC;
 | 
				
			||||||
| 
						 | 
					@ -257,11 +298,7 @@ static void exynos4_clockevent_init(void)
 | 
				
			||||||
	mct_comp_device.cpumask = cpumask_of(0);
 | 
						mct_comp_device.cpumask = cpumask_of(0);
 | 
				
			||||||
	clockevents_config_and_register(&mct_comp_device, clk_rate,
 | 
						clockevents_config_and_register(&mct_comp_device, clk_rate,
 | 
				
			||||||
					0xf, 0xffffffff);
 | 
										0xf, 0xffffffff);
 | 
				
			||||||
 | 
						setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
 | 
				
			||||||
	if (soc_is_exynos5250())
 | 
					 | 
				
			||||||
		setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_LOCAL_TIMERS
 | 
					#ifdef CONFIG_LOCAL_TIMERS
 | 
				
			||||||
| 
						 | 
					@ -273,12 +310,12 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long tmp;
 | 
						unsigned long tmp;
 | 
				
			||||||
	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
 | 
						unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
 | 
				
			||||||
	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
 | 
						unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp = __raw_readl(addr);
 | 
						tmp = __raw_readl(reg_base + offset);
 | 
				
			||||||
	if (tmp & mask) {
 | 
						if (tmp & mask) {
 | 
				
			||||||
		tmp &= ~mask;
 | 
							tmp &= ~mask;
 | 
				
			||||||
		exynos4_mct_write(tmp, addr);
 | 
							exynos4_mct_write(tmp, offset);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,7 +334,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
 | 
				
			||||||
	/* enable MCT tick interrupt */
 | 
						/* enable MCT tick interrupt */
 | 
				
			||||||
	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 | 
						exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
 | 
						tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
 | 
				
			||||||
	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 | 
						tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 | 
				
			||||||
	       MCT_L_TCON_INTERVAL_MODE;
 | 
						       MCT_L_TCON_INTERVAL_MODE;
 | 
				
			||||||
	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
 | 
						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)
 | 
				
			||||||
		exynos4_mct_tick_stop(mevt);
 | 
							exynos4_mct_tick_stop(mevt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clear the MCT tick interrupt */
 | 
						/* Clear the MCT tick interrupt */
 | 
				
			||||||
	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
 | 
						if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
 | 
				
			||||||
		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 | 
							exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -385,7 +422,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mct_clock_event_device *mevt;
 | 
						struct mct_clock_event_device *mevt;
 | 
				
			||||||
	unsigned int cpu = smp_processor_id();
 | 
						unsigned int cpu = smp_processor_id();
 | 
				
			||||||
	int mct_lx_irq;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mevt = this_cpu_ptr(&percpu_mct_tick);
 | 
						mevt = this_cpu_ptr(&percpu_mct_tick);
 | 
				
			||||||
	mevt->evt = evt;
 | 
						mevt->evt = evt;
 | 
				
			||||||
| 
						 | 
					@ -406,21 +442,17 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mct_int_type == MCT_INT_SPI) {
 | 
						if (mct_int_type == MCT_INT_SPI) {
 | 
				
			||||||
		if (cpu == 0) {
 | 
							if (cpu == 0) {
 | 
				
			||||||
			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
 | 
					 | 
				
			||||||
						EXYNOS5_IRQ_MCT_L0;
 | 
					 | 
				
			||||||
			mct_tick0_event_irq.dev_id = mevt;
 | 
								mct_tick0_event_irq.dev_id = mevt;
 | 
				
			||||||
			evt->irq = mct_lx_irq;
 | 
								evt->irq = mct_irqs[MCT_L0_IRQ];
 | 
				
			||||||
			setup_irq(mct_lx_irq, &mct_tick0_event_irq);
 | 
								setup_irq(evt->irq, &mct_tick0_event_irq);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
 | 
					 | 
				
			||||||
						EXYNOS5_IRQ_MCT_L1;
 | 
					 | 
				
			||||||
			mct_tick1_event_irq.dev_id = mevt;
 | 
								mct_tick1_event_irq.dev_id = mevt;
 | 
				
			||||||
			evt->irq = mct_lx_irq;
 | 
								evt->irq = mct_irqs[MCT_L1_IRQ];
 | 
				
			||||||
			setup_irq(mct_lx_irq, &mct_tick1_event_irq);
 | 
								setup_irq(evt->irq, &mct_tick1_event_irq);
 | 
				
			||||||
			irq_set_affinity(mct_lx_irq, cpumask_of(1));
 | 
								irq_set_affinity(evt->irq, cpumask_of(1));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
 | 
							enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -436,7 +468,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			remove_irq(evt->irq, &mct_tick1_event_irq);
 | 
								remove_irq(evt->irq, &mct_tick1_event_irq);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
 | 
							disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 | 
					static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 | 
				
			||||||
| 
						 | 
					@ -445,41 +477,80 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif /* CONFIG_LOCAL_TIMERS */
 | 
					#endif /* CONFIG_LOCAL_TIMERS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __init exynos4_timer_resources(void)
 | 
					static void __init exynos4_timer_resources(void __iomem *base)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct clk *mct_clk;
 | 
						struct clk *mct_clk;
 | 
				
			||||||
	mct_clk = clk_get(NULL, "xtal");
 | 
						mct_clk = clk_get(NULL, "xtal");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_rate = clk_get_rate(mct_clk);
 | 
						clk_rate = clk_get_rate(mct_clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg_base = base;
 | 
				
			||||||
 | 
						if (!reg_base)
 | 
				
			||||||
 | 
							panic("%s: unable to ioremap mct address space\n", __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_LOCAL_TIMERS
 | 
					#ifdef CONFIG_LOCAL_TIMERS
 | 
				
			||||||
	if (mct_int_type == MCT_INT_PPI) {
 | 
						if (mct_int_type == MCT_INT_PPI) {
 | 
				
			||||||
		int err;
 | 
							int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER,
 | 
							err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
 | 
				
			||||||
					 exynos4_mct_tick_isr, "MCT",
 | 
										 exynos4_mct_tick_isr, "MCT",
 | 
				
			||||||
					 &percpu_mct_tick);
 | 
										 &percpu_mct_tick);
 | 
				
			||||||
		WARN(err, "MCT: can't request IRQ %d (%d)\n",
 | 
							WARN(err, "MCT: can't request IRQ %d (%d)\n",
 | 
				
			||||||
		     EXYNOS_IRQ_MCT_LOCALTIMER, err);
 | 
							     mct_irqs[MCT_L0_IRQ], err);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local_timer_register(&exynos4_mct_tick_ops);
 | 
						local_timer_register(&exynos4_mct_tick_ops);
 | 
				
			||||||
#endif /* CONFIG_LOCAL_TIMERS */
 | 
					#endif /* CONFIG_LOCAL_TIMERS */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __init exynos4_timer_init(void)
 | 
					void __init mct_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (soc_is_exynos5440()) {
 | 
						if (soc_is_exynos4210()) {
 | 
				
			||||||
		arch_timer_of_register();
 | 
							mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
 | 
				
			||||||
		return;
 | 
							mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
 | 
				
			||||||
 | 
							mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
 | 
				
			||||||
 | 
							mct_int_type = MCT_INT_SPI;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							panic("unable to determine mct controller type\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
 | 
						exynos4_timer_resources(S5P_VA_SYSTIMER);
 | 
				
			||||||
		mct_int_type = MCT_INT_SPI;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		mct_int_type = MCT_INT_PPI;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exynos4_timer_resources();
 | 
					 | 
				
			||||||
	exynos4_clocksource_init();
 | 
						exynos4_clocksource_init();
 | 
				
			||||||
	exynos4_clockevent_init();
 | 
						exynos4_clockevent_init();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __init mct_init_dt(struct device_node *np, unsigned int int_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 nr_irqs, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mct_int_type = int_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This driver uses only one global timer interrupt */
 | 
				
			||||||
 | 
						mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Find out the number of local irqs specified. The local
 | 
				
			||||||
 | 
						 * timer irqs are specified after the four global timer
 | 
				
			||||||
 | 
						 * irqs are specified.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						nr_irqs = of_irq_count(np);
 | 
				
			||||||
 | 
						for (i = MCT_L0_IRQ; i < nr_irqs; i++)
 | 
				
			||||||
 | 
							mct_irqs[i] = irq_of_parse_and_map(np, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exynos4_timer_resources(of_iomap(np, 0));
 | 
				
			||||||
 | 
						exynos4_clocksource_init();
 | 
				
			||||||
 | 
						exynos4_clockevent_init();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __init mct_init_spi(struct device_node *np)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return mct_init_dt(np, MCT_INT_SPI);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __init mct_init_ppi(struct device_node *np)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return mct_init_dt(np, MCT_INT_PPI);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
 | 
				
			||||||
 | 
					CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
 | 
				
			||||||
		Loading…
	
		Reference in a new issue