Introduce common timer functions
Many platforms duplicate pretty much the same timer code yet they all have a 32-bit freerunning counter register. Create a common implementation that minimally requires 2 or 3 defines to add timer support: CONFIG_SYS_TIMER_RATE - Clock rate of the timer counter CONFIG_SYS_TIMER_COUNTER - Address of 32-bit counter CONFIG_SYS_TIMER_COUNTS_DOWN - Define if counter counts down All functions are weak or ifdef'ed so they can still be overriden by any platform. Signed-off-by: Rob Herring <rob.herring@calxeda.com>
This commit is contained in:
		
							parent
							
								
									e32a268b6f
								
							
						
					
					
						commit
						8dfafdde88
					
				|  | @ -72,6 +72,8 @@ typedef struct global_data { | ||||||
| #if defined(CONFIG_SYS_I2C) | #if defined(CONFIG_SYS_I2C) | ||||||
| 	int		cur_i2c_bus;	/* current used i2c bus */ | 	int		cur_i2c_bus;	/* current used i2c bus */ | ||||||
| #endif | #endif | ||||||
|  | 	unsigned long timebase_h; | ||||||
|  | 	unsigned long timebase_l; | ||||||
| 	struct arch_global_data arch;	/* architecture-specific data */ | 	struct arch_global_data arch;	/* architecture-specific data */ | ||||||
| } gd_t; | } gd_t; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								lib/time.c
								
								
								
								
							
							
						
						
									
										73
									
								
								lib/time.c
								
								
								
								
							|  | @ -7,6 +7,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <watchdog.h> | #include <watchdog.h> | ||||||
|  | #include <div64.h> | ||||||
|  | #include <asm/io.h> | ||||||
| 
 | 
 | ||||||
| #if CONFIG_SYS_HZ != 1000 | #if CONFIG_SYS_HZ != 1000 | ||||||
| #warning "CONFIG_SYS_HZ must be 1000 and should not be defined by platforms" | #warning "CONFIG_SYS_HZ must be 1000 and should not be defined by platforms" | ||||||
|  | @ -16,6 +18,77 @@ | ||||||
| # define CONFIG_WD_PERIOD	(10 * 1000 * 1000)	/* 10 seconds default*/ | # define CONFIG_WD_PERIOD	(10 * 1000 * 1000)	/* 10 seconds default*/ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_SYS_TIMER_RATE | ||||||
|  | ulong notrace get_tbclk(void) | ||||||
|  | { | ||||||
|  | 	return CONFIG_SYS_TIMER_RATE; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_SYS_TIMER_COUNTER | ||||||
|  | unsigned long notrace timer_read_counter(void) | ||||||
|  | { | ||||||
|  | #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN | ||||||
|  | 	return ~readl(CONFIG_SYS_TIMER_COUNTER); | ||||||
|  | #else | ||||||
|  | 	return readl(CONFIG_SYS_TIMER_COUNTER); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | extern unsigned long timer_read_counter(void); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | unsigned long long __weak notrace get_ticks(void) | ||||||
|  | { | ||||||
|  | 	unsigned long now = timer_read_counter(); | ||||||
|  | 
 | ||||||
|  | 	/* increment tbu if tbl has rolled over */ | ||||||
|  | 	if (now < gd->timebase_l) | ||||||
|  | 		gd->timebase_h++; | ||||||
|  | 	gd->timebase_l = now; | ||||||
|  | 	return ((unsigned long long)gd->timebase_h << 32) | gd->timebase_l; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static unsigned long long notrace tick_to_time(unsigned long long tick) | ||||||
|  | { | ||||||
|  | 	unsigned int div = get_tbclk(); | ||||||
|  | 
 | ||||||
|  | 	tick *= CONFIG_SYS_HZ; | ||||||
|  | 	do_div(tick, div); | ||||||
|  | 	return tick; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ulong __weak get_timer(ulong base) | ||||||
|  | { | ||||||
|  | 	return tick_to_time(get_ticks()) - base; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | unsigned long __weak notrace timer_get_us(void) | ||||||
|  | { | ||||||
|  | 	return tick_to_time(get_ticks() * 1000); | ||||||
|  | } | ||||||
|  | static unsigned long long usec_to_tick(unsigned long usec) | ||||||
|  | { | ||||||
|  | 	unsigned long long tick = usec * get_tbclk(); | ||||||
|  | 	usec *= get_tbclk(); | ||||||
|  | 	do_div(tick, 1000000); | ||||||
|  | 	return tick; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void __weak __udelay(unsigned long usec) | ||||||
|  | { | ||||||
|  | 	unsigned long long tmp; | ||||||
|  | 	ulong tmo; | ||||||
|  | 
 | ||||||
|  | 	tmo = usec_to_tick(usec); | ||||||
|  | 	tmp = get_ticks() + tmo;	/* get current timestamp */ | ||||||
|  | 
 | ||||||
|  | 	while (get_ticks() < tmp)	/* loop till event */ | ||||||
|  | 		 /*NOP*/; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| void udelay(unsigned long usec) | void udelay(unsigned long usec) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue