Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 037f6377 authored by Will Deacon's avatar Will Deacon Committed by Sudeep Holla
Browse files

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: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarOlof Johansson <olof@lixom.net>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
[sudeep: moving ARM/ARM64 changes into separate patches
         and adding Kconfig option]
Signed-off-by: default avatarSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
parent 46efe547
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -74,6 +74,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 ARM_GLOBAL_TIMER
	bool
	select CLKSRC_OF if OF
+15 −0
Original line number Diff line number Diff line
@@ -294,6 +294,19 @@ static void __arch_timer_setup(unsigned type,
	clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
}

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 arch_timer_setup(struct clock_event_device *clk)
{
	__arch_timer_setup(ARCH_CP15_TIMER, clk);
@@ -307,6 +320,8 @@ static int 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;
}
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ enum arch_timer_reg {
#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);