aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2013-10-03 10:13:51 -0400
committerDaniel Lezcano <daniel.lezcano@linaro.org>2013-10-03 10:13:51 -0400
commit191124efb4d6e5e47fe073b4b97350873523e88c (patch)
tree8fb9dbbff739e19aa1750c58fe5ec12ee6547e49 /arch/arm
parent68e90740284c69292881cd38c7ece6f09a18a58f (diff)
parent346e7480f1d4740b3d798da60f83f087ea6488b4 (diff)
Merge branch 'timer_evtstrm' of git://linux-arm.org/linux-skn into clockevents/3.13
Adds support to configure the rate and enable the event stream for architected timer. The event streams can be used to impose a timeout on a wfe, to safeguard against any programming error in case an expected event is not generated or even to implement wfe-based timeouts for userspace locking implementations. This feature can be disabled(enabled by default). Since the timer control register is reset to zero on warm boot, CPU PM notifier is added to save and restore the value. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/arch_timer.h36
-rw-r--r--arch/arm/include/uapi/asm/hwcap.h1
-rw-r--r--arch/arm/kernel/setup.c1
3 files changed, 33 insertions, 5 deletions
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 5665134bfa3e..0704e0cf5571 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -87,17 +87,43 @@ static inline u64 arch_counter_get_cntvct(void)
87 return cval; 87 return cval;
88} 88}
89 89
90static inline void arch_counter_set_user_access(void) 90static inline u32 arch_timer_get_cntkctl(void)
91{ 91{
92 u32 cntkctl; 92 u32 cntkctl;
93
94 asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); 93 asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
94 return cntkctl;
95}
95 96
96 /* disable user access to everything */ 97static inline void arch_timer_set_cntkctl(u32 cntkctl)
97 cntkctl &= ~((3 << 8) | (7 << 0)); 98{
98
99 asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); 99 asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
100} 100}
101
102static inline void arch_counter_set_user_access(void)
103{
104 u32 cntkctl = arch_timer_get_cntkctl();
105
106 /* Disable user access to both physical/virtual counters/timers */
107 /* Also disable virtual event stream */
108 cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
109 | ARCH_TIMER_USR_VT_ACCESS_EN
110 | ARCH_TIMER_VIRT_EVT_EN
111 | ARCH_TIMER_USR_VCT_ACCESS_EN
112 | ARCH_TIMER_USR_PCT_ACCESS_EN);
113 arch_timer_set_cntkctl(cntkctl);
114}
115
116static inline void arch_timer_evtstrm_enable(int divider)
117{
118 u32 cntkctl = arch_timer_get_cntkctl();
119 cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
120 /* Set the divider and enable virtual event stream */
121 cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
122 | ARCH_TIMER_VIRT_EVT_EN;
123 arch_timer_set_cntkctl(cntkctl);
124 elf_hwcap |= HWCAP_EVTSTRM;
125}
126
101#endif 127#endif
102 128
103#endif 129#endif
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index 6d34d080372a..7dcc10d67253 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -26,5 +26,6 @@
26#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ 26#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */
27#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) 27#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
28#define HWCAP_LPAE (1 << 20) 28#define HWCAP_LPAE (1 << 20)
29#define HWCAP_EVTSTRM (1 << 21)
29 30
30#endif /* _UAPI__ASMARM_HWCAP_H */ 31#endif /* _UAPI__ASMARM_HWCAP_H */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 0e1e2b3afa45..5d65438685d8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -975,6 +975,7 @@ static const char *hwcap_str[] = {
975 "idivt", 975 "idivt",
976 "vfpd32", 976 "vfpd32",
977 "lpae", 977 "lpae",
978 "evtstrm",
978 NULL 979 NULL
979}; 980};
980 981