forked from mirrors/linux
		
	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
	
	 Will Deacon
						Will Deacon