drivers: clocksource: add support for ARM architected timer event stream
authorWill Deacon <will.deacon@arm.com>
Fri, 23 Aug 2013 14:32:29 +0000 (15:32 +0100)
committerMark Brown <broonie@linaro.org>
Mon, 5 May 2014 23:10:04 +0000 (16:10 -0700)
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>
(cherry picked from commit 037f637767a82907efedda78d3ff405c34020075)
Signed-off-by: Alex Shi <alex.shi@linaro.org>
Conflicts:
drivers/clocksource/Kconfig
drivers/clocksource/arm_arch_timer.c

drivers/clocksource/Kconfig
drivers/clocksource/arm_arch_timer.c
include/clocksource/arm_arch_timer.h

index f151c6cf27c336ffa756c68a69dc2d4dd20dfb8f..593485b02ee534bab01446ccdcc4d5c3c07c2801 100644 (file)
@@ -67,6 +67,21 @@ config ARM_ARCH_TIMER
        bool
        select CLKSRC_OF if OF
 
+config ARM_ARCH_TIMER_EVTSTREAM
+       bool "Support for ARM architected timer event stream generation"
+       default y if ARM_ARCH_TIMER
+       help
+         This option enables support for event stream generation based on
+         the ARM architected timer. It is used for waking up CPUs executing
+         the wfe instruction at a frequency represented as a power-of-2
+         divisor of the clock rate.
+         The main use of the event stream is wfe-based timeouts of userspace
+         locking implementations. It might also be useful for imposing timeout
+         on wfe to safeguard against any programming errors in case an expected
+         event is not generated.
+         This must be disabled for hardware validation purposes to detect any
+         hardware anomalies of missing events.
+
 config CLKSRC_METAG_GENERIC
        def_bool y if METAG
        help
index a2b25418978244d1ae129cf74f031020951f35d4..9d8d0efc0f462e73130f2879d3c88715d380e634 100644 (file)
@@ -123,6 +123,19 @@ static int arch_timer_set_next_event_phys(unsigned long evt,
        return 0;
 }
 
+static void arch_timer_configure_evtstream(void)
+{
+       int evt_stream_div, pos;
+
+       /* Find the closest power of two to the divisor */
+       evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ;
+       pos = fls(evt_stream_div);
+       if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
+               pos--;
+       /* enable event stream */
+       arch_timer_evtstrm_enable(min(pos, 15));
+}
+
 static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
 {
        clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP;
@@ -154,6 +167,8 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
        }
 
        arch_counter_set_user_access();
+       if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
+               arch_timer_configure_evtstream();
 
        return 0;
 }
index 62e30d721ef2cfbc25613abf1579bee11fab706f..63131fdfe0ff1ba29c80e2b61c3b3a1430483824 100644 (file)
@@ -37,6 +37,8 @@
 #define ARCH_TIMER_USR_VT_ACCESS_EN    (1 << 8) /* virtual timer registers */
 #define ARCH_TIMER_USR_PT_ACCESS_EN    (1 << 9) /* physical timer registers */
 
+#define ARCH_TIMER_EVT_STREAM_FREQ     10000   /* 100us */
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);