Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
8ec46b97
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
8ec46b97
编写于
3月 09, 2013
作者:
K
Kukjin Kim
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next/mct-exynos' into next/clk-exynos
Conflicts: arch/arm/mach-exynos/mach-exynos4-dt.c
上级
b85b64cc
6938d75a
变更
23
隐藏空白更改
内联
并排
Showing
23 changed file
with
309 addition
and
149 deletion
+309
-149
Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
...tion/devicetree/bindings/timer/samsung,exynos4210-mct.txt
+68
-0
arch/arm/Kconfig
arch/arm/Kconfig
+1
-1
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4210.dtsi
+22
-0
arch/arm/boot/dts/exynos4212.dtsi
arch/arm/boot/dts/exynos4212.dtsi
+22
-0
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos4412.dtsi
+24
-0
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5250.dtsi
+22
-0
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Kconfig
+2
-6
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/Makefile
+0
-2
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.c
+0
-5
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/common.h
+1
-1
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/irqs.h
+0
-6
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/map.h
+0
-1
arch/arm/mach-exynos/include/mach/regs-mct.h
arch/arm/mach-exynos/include/mach/regs-mct.h
+0
-53
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-armlex4210.c
+1
-1
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos4-dt.c
+2
-1
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
+2
-1
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-nuri.c
+1
-1
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-origen.c
+1
-1
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdk4x12.c
+2
-2
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-smdkv310.c
+2
-2
drivers/clocksource/Kconfig
drivers/clocksource/Kconfig
+5
-0
drivers/clocksource/Makefile
drivers/clocksource/Makefile
+1
-0
drivers/clocksource/exynos_mct.c
drivers/clocksource/exynos_mct.c
+130
-65
未找到文件。
Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
0 → 100644
浏览文件 @
8ec46b97
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>;
};
};
arch/arm/Kconfig
浏览文件 @
8ec46b97
...
...
@@ -1655,7 +1655,7 @@ config LOCAL_TIMERS
bool "Use local timer interrupts"
depends on SMP
default y
select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !
EXYNOS4
_MCT)
select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !
CLKSRC_EXYNOS
_MCT)
help
Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system
...
...
arch/arm/boot/dts/exynos4210.dtsi
浏览文件 @
8ec46b97
...
...
@@ -47,6 +47,28 @@
<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 {
compatible = "samsung,exynos4210-pinctrl";
reg = <0x11400000 0x1000>;
...
...
arch/arm/boot/dts/exynos4212.dtsi
浏览文件 @
8ec46b97
...
...
@@ -25,4 +25,26 @@
gic:interrupt-controller@10490000 {
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>;
};
};
};
arch/arm/boot/dts/exynos4412.dtsi
浏览文件 @
8ec46b97
...
...
@@ -25,4 +25,28 @@
gic:interrupt-controller@10490000 {
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>;
};
};
};
arch/arm/boot/dts/exynos5250.dtsi
浏览文件 @
8ec46b97
...
...
@@ -79,6 +79,28 @@
<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 {
compatible = "samsung,s3c2410-wdt";
reg = <0x101D0000 0x100>;
...
...
arch/arm/mach-exynos/Kconfig
浏览文件 @
8ec46b97
...
...
@@ -80,12 +80,6 @@ config SOC_EXYNOS5440
help
Enable EXYNOS5440 SoC support
config EXYNOS4_MCT
bool
default y
help
Use MCT (Multi Core Timer) as kernel timers
config EXYNOS_DEV_DMA
bool
help
...
...
@@ -407,6 +401,7 @@ config MACH_EXYNOS4_DT
bool "Samsung Exynos4 Machine using device tree"
depends on ARCH_EXYNOS4
select ARM_AMBA
select CLKSRC_OF
select CPU_EXYNOS4210
select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
select PINCTRL
...
...
@@ -424,6 +419,7 @@ config MACH_EXYNOS5_DT
default y
depends on ARCH_EXYNOS5
select ARM_AMBA
select CLKSRC_OF
select USE_OF
help
Machine support for Samsung EXYNOS5 machine with device tree enabled.
...
...
arch/arm/mach-exynos/Makefile
浏览文件 @
8ec46b97
...
...
@@ -26,8 +26,6 @@ obj-$(CONFIG_ARCH_EXYNOS) += pmu.o
obj-$(CONFIG_SMP)
+=
platsmp.o headsmp.o
obj-$(CONFIG_EXYNOS4_MCT)
+=
mct.o
obj-$(CONFIG_HOTPLUG_CPU)
+=
hotplug.o
# machine support
...
...
arch/arm/mach-exynos/common.c
浏览文件 @
8ec46b97
...
...
@@ -256,11 +256,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
.
pfn
=
__phys_to_pfn
(
EXYNOS5_PA_SROMC
),
.
length
=
SZ_4K
,
.
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
,
.
pfn
=
__phys_to_pfn
(
EXYNOS5_PA_SYSRAM
),
...
...
arch/arm/mach-exynos/common.h
浏览文件 @
8ec46b97
...
...
@@ -12,7 +12,7 @@
#ifndef __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
;
void
exynos_init_io
(
struct
map_desc
*
mach_desc
,
int
size
);
...
...
arch/arm/mach-exynos/include/mach/irqs.h
浏览文件 @
8ec46b97
...
...
@@ -30,8 +30,6 @@
/* For EXYNOS4 and EXYNOS5 */
#define EXYNOS_IRQ_MCT_LOCALTIMER IRQ_PPI(12)
#define EXYNOS_IRQ_EINT16_31 IRQ_SPI(32)
/* For EXYNOS4 SoCs */
...
...
@@ -323,8 +321,6 @@
#define EXYNOS5_IRQ_CEC IRQ_SPI(114)
#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_MDMA1 IRQ_SPI(124)
#define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125)
...
...
@@ -419,8 +415,6 @@
#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(22, 4)
#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_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1)
...
...
arch/arm/mach-exynos/include/mach/map.h
浏览文件 @
8ec46b97
...
...
@@ -65,7 +65,6 @@
#define EXYNOS5_PA_CMU 0x10010000
#define EXYNOS4_PA_SYSTIMER 0x10050000
#define EXYNOS5_PA_SYSTIMER 0x101C0000
#define EXYNOS4_PA_WATCHDOG 0x10060000
#define EXYNOS5_PA_WATCHDOG 0x101D0000
...
...
arch/arm/mach-exynos/include/mach/regs-mct.h
已删除
100644 → 0
浏览文件 @
b85b64cc
/* 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 */
arch/arm/mach-exynos/mach-armlex4210.c
浏览文件 @
8ec46b97
...
...
@@ -202,6 +202,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
.
map_io
=
armlex4210_map_io
,
.
init_machine
=
armlex4210_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
restart
=
exynos4_restart
,
MACHINE_END
arch/arm/mach-exynos/mach-exynos4-dt.c
浏览文件 @
8ec46b97
...
...
@@ -15,6 +15,7 @@
#include <linux/of_fdt.h>
#include <linux/serial_core.h>
#include <linux/memblock.h>
#include <linux/clocksource.h>
#include <asm/mach/arch.h>
#include <mach/map.h>
...
...
@@ -158,7 +159,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
.
map_io
=
exynos4_dt_map_io
,
.
init_machine
=
exynos4_dt_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
clocksource_of
_init
,
.
dt_compat
=
exynos4_dt_compat
,
.
restart
=
exynos4_restart
,
.
reserve
=
exynos4_reserve
,
...
...
arch/arm/mach-exynos/mach-exynos5-dt.c
浏览文件 @
8ec46b97
...
...
@@ -14,6 +14,7 @@
#include <linux/serial_core.h>
#include <linux/memblock.h>
#include <linux/io.h>
#include <linux/clocksource.h>
#include <asm/mach/arch.h>
#include <mach/map.h>
...
...
@@ -217,7 +218,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
.
map_io
=
exynos5_dt_map_io
,
.
init_machine
=
exynos5_dt_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
clocksource_of
_init
,
.
dt_compat
=
exynos5_dt_compat
,
.
restart
=
exynos5_restart
,
.
reserve
=
exynos5_reserve
,
...
...
arch/arm/mach-exynos/mach-nuri.c
浏览文件 @
8ec46b97
...
...
@@ -1380,7 +1380,7 @@ MACHINE_START(NURI, "NURI")
.
map_io
=
nuri_map_io
,
.
init_machine
=
nuri_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
reserve
=
&
nuri_reserve
,
.
restart
=
exynos4_restart
,
MACHINE_END
arch/arm/mach-exynos/mach-origen.c
浏览文件 @
8ec46b97
...
...
@@ -815,7 +815,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
.
map_io
=
origen_map_io
,
.
init_machine
=
origen_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
reserve
=
&
origen_reserve
,
.
restart
=
exynos4_restart
,
MACHINE_END
arch/arm/mach-exynos/mach-smdk4x12.c
浏览文件 @
8ec46b97
...
...
@@ -376,7 +376,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
.
init_irq
=
exynos4_init_irq
,
.
map_io
=
smdk4x12_map_io
,
.
init_machine
=
smdk4x12_machine_init
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
restart
=
exynos4_restart
,
.
reserve
=
&
smdk4x12_reserve
,
MACHINE_END
...
...
@@ -390,7 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
.
map_io
=
smdk4x12_map_io
,
.
init_machine
=
smdk4x12_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
restart
=
exynos4_restart
,
.
reserve
=
&
smdk4x12_reserve
,
MACHINE_END
arch/arm/mach-exynos/mach-smdkv310.c
浏览文件 @
8ec46b97
...
...
@@ -423,7 +423,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
.
init_irq
=
exynos4_init_irq
,
.
map_io
=
smdkv310_map_io
,
.
init_machine
=
smdkv310_machine_init
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
reserve
=
&
smdkv310_reserve
,
.
restart
=
exynos4_restart
,
MACHINE_END
...
...
@@ -436,7 +436,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
.
map_io
=
smdkv310_map_io
,
.
init_machine
=
smdkv310_machine_init
,
.
init_late
=
exynos_init_late
,
.
init_time
=
exynos4_timer
_init
,
.
init_time
=
mct
_init
,
.
reserve
=
&
smdkv310_reserve
,
.
restart
=
exynos4_restart
,
MACHINE_END
drivers/clocksource/Kconfig
浏览文件 @
8ec46b97
...
...
@@ -67,3 +67,8 @@ config CLKSRC_METAG_GENERIC
def_bool y if METAG
help
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.
drivers/clocksource/Makefile
浏览文件 @
8ec46b97
...
...
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
obj-$(CONFIG_SUNXI_TIMER)
+=
sunxi_timer.o
obj-$(CONFIG_ARCH_TEGRA)
+=
tegra20_timer.o
obj-$(CONFIG_VT8500_TIMER)
+=
vt8500_timer.o
obj-$(CONFIG_CLKSRC_EXYNOS_MCT)
+=
exynos_mct.o
obj-$(CONFIG_ARM_ARCH_TIMER)
+=
arm_arch_timer.o
obj-$(CONFIG_CLKSRC_METAG_GENERIC)
+=
metag_generic.o
arch/arm/mach-exynos/
mct.c
→
drivers/clocksource/exynos_
mct.c
浏览文件 @
8ec46b97
...
...
@@ -20,6 +20,9 @@
#include <linux/delay.h>
#include <linux/percpu.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/localtimer.h>
...
...
@@ -28,9 +31,36 @@
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/regs-mct.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
enum
{
...
...
@@ -38,64 +68,75 @@ enum {
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
int
mct_int_type
;
static
int
mct_irqs
[
MCT_NR_IRQS
];
struct
mct_clock_event_device
{
struct
clock_event_device
*
evt
;
void
__iomem
*
base
;
unsigned
long
base
;
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
i
;
__raw_writel
(
value
,
addr
);
__raw_writel
(
value
,
reg_base
+
offset
);
if
(
likely
(
addr
>=
EXYNOS4_MCT_L_BASE
(
0
)))
{
u32
base
=
(
u32
)
addr
&
EXYNOS4_MCT_L_MASK
;
switch
((
u32
)
addr
&
~
EXYNOS4_MCT_L_MASK
)
{
case
(
u32
)
MCT_L_TCON_OFFSET
:
stat_addr
=
(
void
__iomem
*
)
base
+
MCT_L_WSTAT_OFFSET
;
if
(
likely
(
offset
>=
EXYNOS4_MCT_L_BASE
(
0
)))
{
stat_addr
=
(
offset
&
~
EXYNOS4_MCT_L_MASK
)
+
MCT_L_WSTAT_OFFSET
;
switch
(
offset
&
EXYNOS4_MCT_L_MASK
)
{
case
MCT_L_TCON_OFFSET
:
mask
=
1
<<
3
;
/* L_TCON write status */
break
;
case
(
u32
)
MCT_L_ICNTB_OFFSET
:
stat_addr
=
(
void
__iomem
*
)
base
+
MCT_L_WSTAT_OFFSET
;
case
MCT_L_ICNTB_OFFSET
:
mask
=
1
<<
1
;
/* L_ICNTB write status */
break
;
case
(
u32
)
MCT_L_TCNTB_OFFSET
:
stat_addr
=
(
void
__iomem
*
)
base
+
MCT_L_WSTAT_OFFSET
;
case
MCT_L_TCNTB_OFFSET
:
mask
=
1
<<
0
;
/* L_TCNTB write status */
break
;
default:
return
;
}
}
else
{
switch
(
(
u32
)
addr
)
{
case
(
u32
)
EXYNOS4_MCT_G_TCON
:
switch
(
offset
)
{
case
EXYNOS4_MCT_G_TCON
:
stat_addr
=
EXYNOS4_MCT_G_WSTAT
;
mask
=
1
<<
16
;
/* G_TCON write status */
break
;
case
(
u32
)
EXYNOS4_MCT_G_COMP0_L
:
case
EXYNOS4_MCT_G_COMP0_L
:
stat_addr
=
EXYNOS4_MCT_G_WSTAT
;
mask
=
1
<<
0
;
/* G_COMP0_L write status */
break
;
case
(
u32
)
EXYNOS4_MCT_G_COMP0_U
:
case
EXYNOS4_MCT_G_COMP0_U
:
stat_addr
=
EXYNOS4_MCT_G_WSTAT
;
mask
=
1
<<
1
;
/* G_COMP0_U write status */
break
;
case
(
u32
)
EXYNOS4_MCT_G_COMP0_ADD_INCR
:
case
EXYNOS4_MCT_G_COMP0_ADD_INCR
:
stat_addr
=
EXYNOS4_MCT_G_WSTAT
;
mask
=
1
<<
2
;
/* G_COMP0_ADD_INCR w status */
break
;
case
(
u32
)
EXYNOS4_MCT_G_CNT_L
:
case
EXYNOS4_MCT_G_CNT_L
:
stat_addr
=
EXYNOS4_MCT_G_CNT_WSTAT
;
mask
=
1
<<
0
;
/* G_CNT_L write status */
break
;
case
(
u32
)
EXYNOS4_MCT_G_CNT_U
:
case
EXYNOS4_MCT_G_CNT_U
:
stat_addr
=
EXYNOS4_MCT_G_CNT_WSTAT
;
mask
=
1
<<
1
;
/* G_CNT_U write status */
break
;
...
...
@@ -106,12 +147,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
/* Wait maximum 1 ms until written values are applied */
for
(
i
=
0
;
i
<
loops_per_jiffy
/
1000
*
HZ
;
i
++
)
if
(
__raw_readl
(
stat_addr
)
&
mask
)
{
__raw_writel
(
mask
,
stat_addr
);
if
(
__raw_readl
(
reg_base
+
stat_addr
)
&
mask
)
{
__raw_writel
(
mask
,
reg_base
+
stat_addr
);
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 */
...
...
@@ -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
(
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
;
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
)
{
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
{
hi
=
hi2
;
lo
=
__raw_readl
(
EXYNOS4_MCT_G_CNT_L
);
hi2
=
__raw_readl
(
EXYNOS4_MCT_G_CNT_U
);
lo
=
__raw_readl
(
reg_base
+
EXYNOS4_MCT_G_CNT_L
);
hi2
=
__raw_readl
(
reg_base
+
EXYNOS4_MCT_G_CNT_U
);
}
while
(
hi
!=
hi2
);
return
((
cycle_t
)
hi
<<
32
)
|
lo
;
...
...
@@ -167,7 +208,7 @@ static void exynos4_mct_comp0_stop(void)
{
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
);
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
;
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
)
{
tcon
|=
MCT_G_TCON_COMP0_AUTO_INC
;
...
...
@@ -257,11 +298,7 @@ static void exynos4_clockevent_init(void)
mct_comp_device
.
cpumask
=
cpumask_of
(
0
);
clockevents_config_and_register
(
&
mct_comp_device
,
clk_rate
,
0xf
,
0xffffffff
);
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
);
setup_irq
(
mct_irqs
[
MCT_G0_IRQ
],
&
mct_comp_event_irq
);
}
#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
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
)
{
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 */
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
|
MCT_L_TCON_INTERVAL_MODE
;
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
);
/* 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
);
return
1
;
}
else
{
...
...
@@ -385,7 +422,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
{
struct
mct_clock_event_device
*
mevt
;
unsigned
int
cpu
=
smp_processor_id
();
int
mct_lx_irq
;
mevt
=
this_cpu_ptr
(
&
percpu_mct_tick
);
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
(
cpu
==
0
)
{
mct_lx_irq
=
soc_is_exynos4210
()
?
EXYNOS4_IRQ_MCT_L0
:
EXYNOS5_IRQ_MCT_L0
;
mct_tick0_event_irq
.
dev_id
=
mevt
;
evt
->
irq
=
mct_
lx_irq
;
setup_irq
(
mct_lx_
irq
,
&
mct_tick0_event_irq
);
evt
->
irq
=
mct_
irqs
[
MCT_L0_IRQ
]
;
setup_irq
(
evt
->
irq
,
&
mct_tick0_event_irq
);
}
else
{
mct_lx_irq
=
soc_is_exynos4210
()
?
EXYNOS4_IRQ_MCT_L1
:
EXYNOS5_IRQ_MCT_L1
;
mct_tick1_event_irq
.
dev_id
=
mevt
;
evt
->
irq
=
mct_
lx_irq
;
setup_irq
(
mct_lx_
irq
,
&
mct_tick1_event_irq
);
irq_set_affinity
(
mct_lx_
irq
,
cpumask_of
(
1
));
evt
->
irq
=
mct_
irqs
[
MCT_L1_IRQ
]
;
setup_irq
(
evt
->
irq
,
&
mct_tick1_event_irq
);
irq_set_affinity
(
evt
->
irq
,
cpumask_of
(
1
));
}
}
else
{
enable_percpu_irq
(
EXYNOS_IRQ_MCT_LOCALTIMER
,
0
);
enable_percpu_irq
(
mct_irqs
[
MCT_L0_IRQ
]
,
0
);
}
return
0
;
...
...
@@ -436,7 +468,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
else
remove_irq
(
evt
->
irq
,
&
mct_tick1_event_irq
);
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
=
{
...
...
@@ -445,41 +477,74 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
};
#endif
/* CONFIG_LOCAL_TIMERS */
static
void
__init
exynos4_timer_resources
(
void
)
static
void
__init
exynos4_timer_resources
(
struct
device_node
*
np
)
{
struct
clk
*
mct_clk
;
mct_clk
=
clk_get
(
NULL
,
"xtal"
);
clk_rate
=
clk_get_rate
(
mct_clk
);
reg_base
=
np
?
of_iomap
(
np
,
0
)
:
S5P_VA_SYSTIMER
;
if
(
!
reg_base
)
panic
(
"%s: unable to ioremap mct address space
\n
"
,
__func__
);
#ifdef CONFIG_LOCAL_TIMERS
if
(
mct_int_type
==
MCT_INT_PPI
)
{
int
err
;
err
=
request_percpu_irq
(
EXYNOS_IRQ_MCT_LOCALTIMER
,
err
=
request_percpu_irq
(
mct_irqs
[
MCT_L0_IRQ
]
,
exynos4_mct_tick_isr
,
"MCT"
,
&
percpu_mct_tick
);
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
);
#endif
/* CONFIG_LOCAL_TIMERS */
}
void
__init
exynos4_timer_init
(
void
)
{
if
(
soc_is_exynos5440
())
{
arch_timer_of_register
();
return
;
}
static
const
struct
of_device_id
exynos_mct_ids
[]
=
{
{
.
compatible
=
"samsung,exynos4210-mct"
,
.
data
=
(
void
*
)
MCT_INT_SPI
},
{
.
compatible
=
"samsung,exynos4412-mct"
,
.
data
=
(
void
*
)
MCT_INT_PPI
},
};
if
((
soc_is_exynos4210
())
||
(
soc_is_exynos5250
()))
void
__init
mct_init
(
void
)
{
struct
device_node
*
np
=
NULL
;
const
struct
of_device_id
*
match
;
u32
nr_irqs
,
i
;
#ifdef CONFIG_OF
np
=
of_find_matching_node_and_match
(
NULL
,
exynos_mct_ids
,
&
match
);
#endif
if
(
np
)
{
mct_int_type
=
(
u32
)(
match
->
data
);
/* 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.
*/
#ifdef CONFIG_OF
nr_irqs
=
of_irq_count
(
np
);
#endif
for
(
i
=
MCT_L0_IRQ
;
i
<
nr_irqs
;
i
++
)
mct_irqs
[
i
]
=
irq_of_parse_and_map
(
np
,
i
);
}
else
if
(
soc_is_exynos4210
())
{
mct_irqs
[
MCT_G0_IRQ
]
=
EXYNOS4_IRQ_MCT_G0
;
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
mct_int_type
=
MCT_INT_PPI
;
}
else
{
panic
(
"unable to determine mct controller type
\n
"
);
}
exynos4_timer_resources
();
exynos4_timer_resources
(
np
);
exynos4_clocksource_init
();
exynos4_clockevent_init
();
}
CLOCKSOURCE_OF_DECLARE
(
exynos4210
,
"samsung,exynos4210-mct"
,
mct_init
)
CLOCKSOURCE_OF_DECLARE
(
exynos4412
,
"samsung,exynos4412-mct"
,
mct_init
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录