aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clocksource/Kconfig15
-rw-r--r--drivers/clocksource/arm_arch_timer.c15
-rw-r--r--include/clocksource/arm_arch_timer.h2
3 files changed, 32 insertions, 0 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 41c69469ce20..559d80335446 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -74,6 +74,21 @@ config ARM_ARCH_TIMER
74 bool 74 bool
75 select CLKSRC_OF if OF 75 select CLKSRC_OF if OF
76 76
77config ARM_ARCH_TIMER_EVTSTREAM
78 bool "Support for ARM architected timer event stream generation"
79 default y if ARM_ARCH_TIMER
80 help
81 This option enables support for event stream generation based on
82 the ARM architected timer. It is used for waking up CPUs executing
83 the wfe instruction at a frequency represented as a power-of-2
84 divisor of the clock rate.
85 The main use of the event stream is wfe-based timeouts of userspace
86 locking implementations. It might also be useful for imposing timeout
87 on wfe to safeguard against any programming errors in case an expected
88 event is not generated.
89 This must be disabled for hardware validation purposes to detect any
90 hardware anomalies of missing events.
91
77config ARM_GLOBAL_TIMER 92config ARM_GLOBAL_TIMER
78 bool 93 bool
79 select CLKSRC_OF if OF 94 select CLKSRC_OF if OF
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index fbd9ccd5e114..105f8ffa66a8 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -294,6 +294,19 @@ static void __arch_timer_setup(unsigned type,
294 clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); 294 clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
295} 295}
296 296
297static void arch_timer_configure_evtstream(void)
298{
299 int evt_stream_div, pos;
300
301 /* Find the closest power of two to the divisor */
302 evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ;
303 pos = fls(evt_stream_div);
304 if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
305 pos--;
306 /* enable event stream */
307 arch_timer_evtstrm_enable(min(pos, 15));
308}
309
297static int arch_timer_setup(struct clock_event_device *clk) 310static int arch_timer_setup(struct clock_event_device *clk)
298{ 311{
299 __arch_timer_setup(ARCH_CP15_TIMER, clk); 312 __arch_timer_setup(ARCH_CP15_TIMER, clk);
@@ -307,6 +320,8 @@ static int arch_timer_setup(struct clock_event_device *clk)
307 } 320 }
308 321
309 arch_counter_set_user_access(); 322 arch_counter_set_user_access();
323 if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
324 arch_timer_configure_evtstream();
310 325
311 return 0; 326 return 0;
312} 327}
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 8707dae4cee2..6d26b40cbf5d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -41,6 +41,8 @@ enum arch_timer_reg {
41#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */ 41#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */
42#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */ 42#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */
43 43
44#define ARCH_TIMER_EVT_STREAM_FREQ 10000 /* 100us */
45
44#ifdef CONFIG_ARM_ARCH_TIMER 46#ifdef CONFIG_ARM_ARCH_TIMER
45 47
46extern u32 arch_timer_get_rate(void); 48extern u32 arch_timer_get_rate(void);