diff options
author | Will Deacon <will.deacon@arm.com> | 2013-08-23 10:32:29 -0400 |
---|---|---|
committer | Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com> | 2013-09-26 04:48:00 -0400 |
commit | 037f637767a82907efedda78d3ff405c34020075 (patch) | |
tree | 4478cc520fe744be36b559182bd36cbf8f61e705 /drivers/clocksource/arm_arch_timer.c | |
parent | 46efe547aca8498d51b64460c02366ae4032ca32 (diff) |
drivers: clocksource: add support for ARM architected timer event stream
The ARM architected timer can generate events (used for waking up
CPUs executing the wfe instruction) at a frequency represented as a
power-of-2 divisor of the clock rate.
An event stream might be used:
- To implement wfe-based timeouts for userspace locking implementations.
- To impose a timeout on a wfe for safeguarding against any programming
error in case an expected event is not generated.
This patch computes the event stream frequency aiming for a period
of 100us between events. It uses ARM/ARM64 specific backends to configure
and enable the event stream.
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Will Deacon <will.deacon@arm.com>
[sudeep: moving ARM/ARM64 changes into separate patches
and adding Kconfig option]
Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 15 |
1 files changed, 15 insertions, 0 deletions
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 | ||
297 | static 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 | |||
297 | static int arch_timer_setup(struct clock_event_device *clk) | 310 | static 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 | } |