Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+316 -150
+68
Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
··· 1 + Samsung's Multi Core Timer (MCT) 2 + 3 + The Samsung's Multi Core Timer (MCT) module includes two main blocks, the 4 + global timer and CPU local timers. The global timer is a 64-bit free running 5 + up-counter and can generate 4 interrupts when the counter reaches one of the 6 + four preset counter values. The CPU local timers are 32-bit free running 7 + down-counters and generate an interrupt when the counter expires. There is 8 + one CPU local timer instantiated in MCT for every CPU in the system. 9 + 10 + Required 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 + 34 + Example 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 + 46 + Example 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 + };
+1 -1
arch/arm/Kconfig
··· 1654 1654 bool "Use local timer interrupts" 1655 1655 depends on SMP 1656 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 1658 help 1659 1659 Enable support for local timers on SMP platforms, rather then the 1660 1660 legacy IPI broadcast method. Local timers allows the system
+22
arch/arm/boot/dts/exynos4210.dtsi
··· 47 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 72 pinctrl_0: pinctrl@11400000 { 51 73 compatible = "samsung,exynos4210-pinctrl"; 52 74 reg = <0x11400000 0x1000>;
+22
arch/arm/boot/dts/exynos4212.dtsi
··· 25 25 gic:interrupt-controller@10490000 { 26 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 };
+24
arch/arm/boot/dts/exynos4412.dtsi
··· 25 25 gic:interrupt-controller@10490000 { 26 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 };
+22
arch/arm/boot/dts/exynos5250.dtsi
··· 69 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 94 watchdog { 73 95 compatible = "samsung,s3c2410-wdt"; 74 96 reg = <0x101D0000 0x100>;
+2 -6
arch/arm/mach-exynos/Kconfig
··· 79 79 help 80 80 Enable EXYNOS5440 SoC support 81 81 82 - config EXYNOS4_MCT 83 - bool 84 - default y 85 - help 86 - Use MCT (Multi Core Timer) as kernel timers 87 - 88 82 config EXYNOS_DEV_DMA 89 83 bool 90 84 help ··· 400 406 bool "Samsung Exynos4 Machine using device tree" 401 407 depends on ARCH_EXYNOS4 402 408 select ARM_AMBA 409 + select CLKSRC_OF 403 410 select CPU_EXYNOS4210 404 411 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD 405 412 select PINCTRL ··· 417 422 default y 418 423 depends on ARCH_EXYNOS5 419 424 select ARM_AMBA 425 + select CLKSRC_OF 420 426 select USE_OF 421 427 help 422 428 Machine support for Samsung EXYNOS5 machine with device tree enabled.
-2
arch/arm/mach-exynos/Makefile
··· 26 26 27 27 obj-$(CONFIG_SMP) += platsmp.o headsmp.o 28 28 29 - obj-$(CONFIG_EXYNOS4_MCT) += mct.o 30 - 31 29 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 32 30 33 31 # machine support
-5
arch/arm/mach-exynos/common.c
··· 257 257 .length = SZ_4K, 258 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 260 .virtual = (unsigned long)S5P_VA_SYSRAM, 266 261 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM), 267 262 .length = SZ_4K,
+1 -1
arch/arm/mach-exynos/common.h
··· 12 12 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H 13 13 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H 14 14 15 - extern void exynos4_timer_init(void); 15 + extern void mct_init(void); 16 16 17 17 struct map_desc; 18 18 void exynos_init_io(struct map_desc *mach_desc, int size);
-6
arch/arm/mach-exynos/include/mach/irqs.h
··· 30 30 31 31 /* For EXYNOS4 and EXYNOS5 */ 32 32 33 - #define EXYNOS_IRQ_MCT_LOCALTIMER IRQ_PPI(12) 34 - 35 33 #define EXYNOS_IRQ_EINT16_31 IRQ_SPI(32) 36 34 37 35 /* For EXYNOS4 SoCs */ ··· 321 323 #define EXYNOS5_IRQ_CEC IRQ_SPI(114) 322 324 #define EXYNOS5_IRQ_SATA IRQ_SPI(115) 323 325 324 - #define EXYNOS5_IRQ_MCT_L0 IRQ_SPI(120) 325 - #define EXYNOS5_IRQ_MCT_L1 IRQ_SPI(121) 326 326 #define EXYNOS5_IRQ_MMC44 IRQ_SPI(123) 327 327 #define EXYNOS5_IRQ_MDMA1 IRQ_SPI(124) 328 328 #define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125) ··· 415 419 #define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(22, 4) 416 420 417 421 #define EXYNOS5_IRQ_EINT0 COMBINER_IRQ(23, 0) 418 - #define EXYNOS5_IRQ_MCT_G0 COMBINER_IRQ(23, 3) 419 - #define EXYNOS5_IRQ_MCT_G1 COMBINER_IRQ(23, 4) 420 422 421 423 #define EXYNOS5_IRQ_EINT1 COMBINER_IRQ(24, 0) 422 424 #define EXYNOS5_IRQ_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1)
-1
arch/arm/mach-exynos/include/mach/map.h
··· 65 65 #define EXYNOS5_PA_CMU 0x10010000 66 66 67 67 #define EXYNOS4_PA_SYSTIMER 0x10050000 68 - #define EXYNOS5_PA_SYSTIMER 0x101C0000 69 68 70 69 #define EXYNOS4_PA_WATCHDOG 0x10060000 71 70 #define EXYNOS5_PA_WATCHDOG 0x101D0000
-53
arch/arm/mach-exynos/include/mach/regs-mct.h
··· 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 */
+1 -1
arch/arm/mach-exynos/mach-armlex4210.c
··· 202 202 .map_io = armlex4210_map_io, 203 203 .init_machine = armlex4210_machine_init, 204 204 .init_late = exynos_init_late, 205 - .init_time = exynos4_timer_init, 205 + .init_time = mct_init, 206 206 .restart = exynos4_restart, 207 207 MACHINE_END
+2 -1
arch/arm/mach-exynos/mach-exynos4-dt.c
··· 13 13 14 14 #include <linux/of_platform.h> 15 15 #include <linux/serial_core.h> 16 + #include <linux/clocksource.h> 16 17 17 18 #include <asm/mach/arch.h> 18 19 #include <mach/map.h> ··· 143 142 .map_io = exynos4_dt_map_io, 144 143 .init_machine = exynos4_dt_machine_init, 145 144 .init_late = exynos_init_late, 146 - .init_time = exynos4_timer_init, 145 + .init_time = clocksource_of_init, 147 146 .dt_compat = exynos4_dt_compat, 148 147 .restart = exynos4_restart, 149 148 MACHINE_END
+2 -1
arch/arm/mach-exynos/mach-exynos5-dt.c
··· 14 14 #include <linux/serial_core.h> 15 15 #include <linux/memblock.h> 16 16 #include <linux/io.h> 17 + #include <linux/clocksource.h> 17 18 18 19 #include <asm/mach/arch.h> 19 20 #include <mach/map.h> ··· 217 216 .map_io = exynos5_dt_map_io, 218 217 .init_machine = exynos5_dt_machine_init, 219 218 .init_late = exynos_init_late, 220 - .init_time = exynos4_timer_init, 219 + .init_time = clocksource_of_init, 221 220 .dt_compat = exynos5_dt_compat, 222 221 .restart = exynos5_restart, 223 222 .reserve = exynos5_reserve,
+1 -1
arch/arm/mach-exynos/mach-nuri.c
··· 1380 1380 .map_io = nuri_map_io, 1381 1381 .init_machine = nuri_machine_init, 1382 1382 .init_late = exynos_init_late, 1383 - .init_time = exynos4_timer_init, 1383 + .init_time = mct_init, 1384 1384 .reserve = &nuri_reserve, 1385 1385 .restart = exynos4_restart, 1386 1386 MACHINE_END
+1 -1
arch/arm/mach-exynos/mach-origen.c
··· 815 815 .map_io = origen_map_io, 816 816 .init_machine = origen_machine_init, 817 817 .init_late = exynos_init_late, 818 - .init_time = exynos4_timer_init, 818 + .init_time = mct_init, 819 819 .reserve = &origen_reserve, 820 820 .restart = exynos4_restart, 821 821 MACHINE_END
+2 -2
arch/arm/mach-exynos/mach-smdk4x12.c
··· 376 376 .init_irq = exynos4_init_irq, 377 377 .map_io = smdk4x12_map_io, 378 378 .init_machine = smdk4x12_machine_init, 379 - .init_time = exynos4_timer_init, 379 + .init_time = mct_init, 380 380 .restart = exynos4_restart, 381 381 .reserve = &smdk4x12_reserve, 382 382 MACHINE_END ··· 390 390 .map_io = smdk4x12_map_io, 391 391 .init_machine = smdk4x12_machine_init, 392 392 .init_late = exynos_init_late, 393 - .init_time = exynos4_timer_init, 393 + .init_time = mct_init, 394 394 .restart = exynos4_restart, 395 395 .reserve = &smdk4x12_reserve, 396 396 MACHINE_END
+2 -2
arch/arm/mach-exynos/mach-smdkv310.c
··· 423 423 .init_irq = exynos4_init_irq, 424 424 .map_io = smdkv310_map_io, 425 425 .init_machine = smdkv310_machine_init, 426 - .init_time = exynos4_timer_init, 426 + .init_time = mct_init, 427 427 .reserve = &smdkv310_reserve, 428 428 .restart = exynos4_restart, 429 429 MACHINE_END ··· 436 436 .map_io = smdkv310_map_io, 437 437 .init_machine = smdkv310_machine_init, 438 438 .init_late = exynos_init_late, 439 - .init_time = exynos4_timer_init, 439 + .init_time = mct_init, 440 440 .reserve = &smdkv310_reserve, 441 441 .restart = exynos4_restart, 442 442 MACHINE_END
+136 -65
arch/arm/mach-exynos/mct.c drivers/clocksource/exynos_mct.c
··· 20 20 #include <linux/delay.h> 21 21 #include <linux/percpu.h> 22 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 27 #include <asm/arch_timer.h> 25 28 #include <asm/localtimer.h> ··· 31 28 32 29 #include <mach/map.h> 33 30 #include <mach/irqs.h> 34 - #include <mach/regs-mct.h> 35 31 #include <asm/mach/time.h> 32 + 33 + #define EXYNOS4_MCTREG(x) (x) 34 + #define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100) 35 + #define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104) 36 + #define EXYNOS4_MCT_G_CNT_WSTAT EXYNOS4_MCTREG(0x110) 37 + #define EXYNOS4_MCT_G_COMP0_L EXYNOS4_MCTREG(0x200) 38 + #define EXYNOS4_MCT_G_COMP0_U EXYNOS4_MCTREG(0x204) 39 + #define EXYNOS4_MCT_G_COMP0_ADD_INCR EXYNOS4_MCTREG(0x208) 40 + #define EXYNOS4_MCT_G_TCON EXYNOS4_MCTREG(0x240) 41 + #define EXYNOS4_MCT_G_INT_CSTAT EXYNOS4_MCTREG(0x244) 42 + #define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248) 43 + #define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C) 44 + #define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300) 45 + #define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x)) 46 + #define EXYNOS4_MCT_L_MASK (0xffffff00) 47 + 48 + #define MCT_L_TCNTB_OFFSET (0x00) 49 + #define MCT_L_ICNTB_OFFSET (0x08) 50 + #define MCT_L_TCON_OFFSET (0x20) 51 + #define MCT_L_INT_CSTAT_OFFSET (0x30) 52 + #define MCT_L_INT_ENB_OFFSET (0x34) 53 + #define MCT_L_WSTAT_OFFSET (0x40) 54 + #define MCT_G_TCON_START (1 << 8) 55 + #define MCT_G_TCON_COMP0_AUTO_INC (1 << 1) 56 + #define MCT_G_TCON_COMP0_ENABLE (1 << 0) 57 + #define MCT_L_TCON_INTERVAL_MODE (1 << 2) 58 + #define MCT_L_TCON_INT_START (1 << 1) 59 + #define MCT_L_TCON_TIMER_START (1 << 0) 36 60 37 61 #define TICK_BASE_CNT 1 38 62 ··· 68 38 MCT_INT_PPI 69 39 }; 70 40 41 + enum { 42 + MCT_G0_IRQ, 43 + MCT_G1_IRQ, 44 + MCT_G2_IRQ, 45 + MCT_G3_IRQ, 46 + MCT_L0_IRQ, 47 + MCT_L1_IRQ, 48 + MCT_L2_IRQ, 49 + MCT_L3_IRQ, 50 + MCT_NR_IRQS, 51 + }; 52 + 53 + static void __iomem *reg_base; 71 54 static unsigned long clk_rate; 72 55 static unsigned int mct_int_type; 56 + static int mct_irqs[MCT_NR_IRQS]; 73 57 74 58 struct mct_clock_event_device { 75 59 struct clock_event_device *evt; 76 - void __iomem *base; 60 + unsigned long base; 77 61 char name[10]; 78 62 }; 79 63 80 - static void exynos4_mct_write(unsigned int value, void *addr) 64 + static void exynos4_mct_write(unsigned int value, unsigned long offset) 81 65 { 82 - void __iomem *stat_addr; 66 + unsigned long stat_addr; 83 67 u32 mask; 84 68 u32 i; 85 69 86 - __raw_writel(value, addr); 70 + __raw_writel(value, reg_base + offset); 87 71 88 - if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) { 89 - u32 base = (u32) addr & EXYNOS4_MCT_L_MASK; 90 - switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) { 91 - case (u32) MCT_L_TCON_OFFSET: 92 - stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET; 72 + if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { 73 + stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; 74 + switch (offset & EXYNOS4_MCT_L_MASK) { 75 + case MCT_L_TCON_OFFSET: 93 76 mask = 1 << 3; /* L_TCON write status */ 94 77 break; 95 - case (u32) MCT_L_ICNTB_OFFSET: 96 - stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET; 78 + case MCT_L_ICNTB_OFFSET: 97 79 mask = 1 << 1; /* L_ICNTB write status */ 98 80 break; 99 - case (u32) MCT_L_TCNTB_OFFSET: 100 - stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET; 81 + case MCT_L_TCNTB_OFFSET: 101 82 mask = 1 << 0; /* L_TCNTB write status */ 102 83 break; 103 84 default: 104 85 return; 105 86 } 106 87 } else { 107 - switch ((u32) addr) { 108 - case (u32) EXYNOS4_MCT_G_TCON: 88 + switch (offset) { 89 + case EXYNOS4_MCT_G_TCON: 109 90 stat_addr = EXYNOS4_MCT_G_WSTAT; 110 91 mask = 1 << 16; /* G_TCON write status */ 111 92 break; 112 - case (u32) EXYNOS4_MCT_G_COMP0_L: 93 + case EXYNOS4_MCT_G_COMP0_L: 113 94 stat_addr = EXYNOS4_MCT_G_WSTAT; 114 95 mask = 1 << 0; /* G_COMP0_L write status */ 115 96 break; 116 - case (u32) EXYNOS4_MCT_G_COMP0_U: 97 + case EXYNOS4_MCT_G_COMP0_U: 117 98 stat_addr = EXYNOS4_MCT_G_WSTAT; 118 99 mask = 1 << 1; /* G_COMP0_U write status */ 119 100 break; 120 - case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR: 101 + case EXYNOS4_MCT_G_COMP0_ADD_INCR: 121 102 stat_addr = EXYNOS4_MCT_G_WSTAT; 122 103 mask = 1 << 2; /* G_COMP0_ADD_INCR w status */ 123 104 break; 124 - case (u32) EXYNOS4_MCT_G_CNT_L: 105 + case EXYNOS4_MCT_G_CNT_L: 125 106 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 126 107 mask = 1 << 0; /* G_CNT_L write status */ 127 108 break; 128 - case (u32) EXYNOS4_MCT_G_CNT_U: 109 + case EXYNOS4_MCT_G_CNT_U: 129 110 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; 130 111 mask = 1 << 1; /* G_CNT_U write status */ 131 112 break; ··· 147 106 148 107 /* Wait maximum 1 ms until written values are applied */ 149 108 for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++) 150 - if (__raw_readl(stat_addr) & mask) { 151 - __raw_writel(mask, stat_addr); 109 + if (__raw_readl(reg_base + stat_addr) & mask) { 110 + __raw_writel(mask, reg_base + stat_addr); 152 111 return; 153 112 } 154 113 155 - panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr); 114 + panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset); 156 115 } 157 116 158 117 /* Clocksource handling */ ··· 163 122 exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L); 164 123 exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U); 165 124 166 - reg = __raw_readl(EXYNOS4_MCT_G_TCON); 125 + reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); 167 126 reg |= MCT_G_TCON_START; 168 127 exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); 169 128 } ··· 171 130 static cycle_t exynos4_frc_read(struct clocksource *cs) 172 131 { 173 132 unsigned int lo, hi; 174 - u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U); 133 + u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U); 175 134 176 135 do { 177 136 hi = hi2; 178 - lo = __raw_readl(EXYNOS4_MCT_G_CNT_L); 179 - hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U); 137 + lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L); 138 + hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U); 180 139 } while (hi != hi2); 181 140 182 141 return ((cycle_t)hi << 32) | lo; ··· 208 167 { 209 168 unsigned int tcon; 210 169 211 - tcon = __raw_readl(EXYNOS4_MCT_G_TCON); 170 + tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); 212 171 tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC); 213 172 214 173 exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON); ··· 221 180 unsigned int tcon; 222 181 cycle_t comp_cycle; 223 182 224 - tcon = __raw_readl(EXYNOS4_MCT_G_TCON); 183 + tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); 225 184 226 185 if (mode == CLOCK_EVT_MODE_PERIODIC) { 227 186 tcon |= MCT_G_TCON_COMP0_AUTO_INC; ··· 298 257 mct_comp_device.cpumask = cpumask_of(0); 299 258 clockevents_config_and_register(&mct_comp_device, clk_rate, 300 259 0xf, 0xffffffff); 301 - 302 - if (soc_is_exynos5250()) 303 - setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq); 304 - else 305 - setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq); 260 + setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq); 306 261 } 307 262 308 263 #ifdef CONFIG_LOCAL_TIMERS ··· 310 273 { 311 274 unsigned long tmp; 312 275 unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START; 313 - void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET; 276 + unsigned long offset = mevt->base + MCT_L_TCON_OFFSET; 314 277 315 - tmp = __raw_readl(addr); 278 + tmp = __raw_readl(reg_base + offset); 316 279 if (tmp & mask) { 317 280 tmp &= ~mask; 318 - exynos4_mct_write(tmp, addr); 281 + exynos4_mct_write(tmp, offset); 319 282 } 320 283 } 321 284 ··· 334 297 /* enable MCT tick interrupt */ 335 298 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); 336 299 337 - tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET); 300 + tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET); 338 301 tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | 339 302 MCT_L_TCON_INTERVAL_MODE; 340 303 exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); ··· 386 349 exynos4_mct_tick_stop(mevt); 387 350 388 351 /* Clear the MCT tick interrupt */ 389 - if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { 352 + if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { 390 353 exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); 391 354 return 1; 392 355 } else { ··· 422 385 { 423 386 struct mct_clock_event_device *mevt; 424 387 unsigned int cpu = smp_processor_id(); 425 - int mct_lx_irq; 426 388 427 389 mevt = this_cpu_ptr(&percpu_mct_tick); 428 390 mevt->evt = evt; ··· 442 406 443 407 if (mct_int_type == MCT_INT_SPI) { 444 408 if (cpu == 0) { 445 - mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 : 446 - EXYNOS5_IRQ_MCT_L0; 447 409 mct_tick0_event_irq.dev_id = mevt; 448 - evt->irq = mct_lx_irq; 449 - setup_irq(mct_lx_irq, &mct_tick0_event_irq); 410 + evt->irq = mct_irqs[MCT_L0_IRQ]; 411 + setup_irq(evt->irq, &mct_tick0_event_irq); 450 412 } else { 451 - mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 : 452 - EXYNOS5_IRQ_MCT_L1; 453 413 mct_tick1_event_irq.dev_id = mevt; 454 - evt->irq = mct_lx_irq; 455 - setup_irq(mct_lx_irq, &mct_tick1_event_irq); 456 - irq_set_affinity(mct_lx_irq, cpumask_of(1)); 414 + evt->irq = mct_irqs[MCT_L1_IRQ]; 415 + setup_irq(evt->irq, &mct_tick1_event_irq); 416 + irq_set_affinity(evt->irq, cpumask_of(1)); 457 417 } 458 418 } else { 459 - enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0); 419 + enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); 460 420 } 461 421 462 422 return 0; ··· 468 436 else 469 437 remove_irq(evt->irq, &mct_tick1_event_irq); 470 438 else 471 - disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER); 439 + disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); 472 440 } 473 441 474 442 static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { ··· 477 445 }; 478 446 #endif /* CONFIG_LOCAL_TIMERS */ 479 447 480 - static void __init exynos4_timer_resources(void) 448 + static void __init exynos4_timer_resources(void __iomem *base) 481 449 { 482 450 struct clk *mct_clk; 483 451 mct_clk = clk_get(NULL, "xtal"); 484 452 485 453 clk_rate = clk_get_rate(mct_clk); 486 454 455 + reg_base = base; 456 + if (!reg_base) 457 + panic("%s: unable to ioremap mct address space\n", __func__); 458 + 487 459 #ifdef CONFIG_LOCAL_TIMERS 488 460 if (mct_int_type == MCT_INT_PPI) { 489 461 int err; 490 462 491 - err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 463 + err = request_percpu_irq(mct_irqs[MCT_L0_IRQ], 492 464 exynos4_mct_tick_isr, "MCT", 493 465 &percpu_mct_tick); 494 466 WARN(err, "MCT: can't request IRQ %d (%d)\n", 495 - EXYNOS_IRQ_MCT_LOCALTIMER, err); 467 + mct_irqs[MCT_L0_IRQ], err); 496 468 } 497 469 498 470 local_timer_register(&exynos4_mct_tick_ops); 499 471 #endif /* CONFIG_LOCAL_TIMERS */ 500 472 } 501 473 502 - void __init exynos4_timer_init(void) 474 + void __init mct_init(void) 503 475 { 504 - if (soc_is_exynos5440()) { 505 - arch_timer_of_register(); 506 - return; 476 + if (soc_is_exynos4210()) { 477 + mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0; 478 + mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0; 479 + mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1; 480 + mct_int_type = MCT_INT_SPI; 481 + } else { 482 + panic("unable to determine mct controller type\n"); 507 483 } 508 484 509 - if ((soc_is_exynos4210()) || (soc_is_exynos5250())) 510 - mct_int_type = MCT_INT_SPI; 511 - else 512 - mct_int_type = MCT_INT_PPI; 513 - 514 - exynos4_timer_resources(); 485 + exynos4_timer_resources(S5P_VA_SYSTIMER); 515 486 exynos4_clocksource_init(); 516 487 exynos4_clockevent_init(); 517 488 } 489 + 490 + static void __init mct_init_dt(struct device_node *np, unsigned int int_type) 491 + { 492 + u32 nr_irqs, i; 493 + 494 + mct_int_type = int_type; 495 + 496 + /* This driver uses only one global timer interrupt */ 497 + mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ); 498 + 499 + /* 500 + * Find out the number of local irqs specified. The local 501 + * timer irqs are specified after the four global timer 502 + * irqs are specified. 503 + */ 504 + nr_irqs = of_irq_count(np); 505 + for (i = MCT_L0_IRQ; i < nr_irqs; i++) 506 + mct_irqs[i] = irq_of_parse_and_map(np, i); 507 + 508 + exynos4_timer_resources(of_iomap(np, 0)); 509 + exynos4_clocksource_init(); 510 + exynos4_clockevent_init(); 511 + } 512 + 513 + 514 + static void __init mct_init_spi(struct device_node *np) 515 + { 516 + return mct_init_dt(np, MCT_INT_SPI); 517 + } 518 + 519 + static void __init mct_init_ppi(struct device_node *np) 520 + { 521 + return mct_init_dt(np, MCT_INT_PPI); 522 + } 523 + CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi); 524 + CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
+5
drivers/clocksource/Kconfig
··· 70 70 def_bool y if METAG 71 71 help 72 72 This option enables support for the Meta per-thread timers. 73 + 74 + config CLKSRC_EXYNOS_MCT 75 + def_bool y if ARCH_EXYNOS 76 + help 77 + Support for Multi Core Timer controller on Exynos SoCs.
+2 -1
drivers/clocksource/Makefile
··· 19 19 obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o 20 20 obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o 21 21 obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o 22 - obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o 22 + obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o 23 + obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o 23 24 24 25 obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o 25 26 obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o