mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	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>
			
			
This commit is contained in:
		
							parent
							
								
									46efe547ac
								
							
						
					
					
						commit
						037f637767
					
				
					 3 changed files with 32 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue