@ -25,7 +25,14 @@
# include <common.h>
# include <asm/io.h>
# include <div64.h>
# include <asm/arch/imx-regs.h>
# include <asm/arch/clock.h>
DECLARE_GLOBAL_DATA_PTR ;
# define timestamp (gd->tbl)
# define lastinc (gd->lastinc)
/* General purpose timers bitfields */
# define GPTCR_SWR (1<<15) /* Software reset */
@ -33,7 +40,24 @@
# define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */
# define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */
# define GPTCR_TEN (1) /* Timer enable */
# define GPTPR_VAL (66)
# define TIMER_FREQ_HZ mxc_get_clock(MXC_IPG_CLK)
static inline unsigned long long tick_to_time ( unsigned long long tick )
{
tick * = CONFIG_SYS_HZ ;
do_div ( tick , TIMER_FREQ_HZ ) ;
return tick ;
}
static inline unsigned long long us_to_tick ( unsigned long long usec )
{
usec * = TIMER_FREQ_HZ ;
do_div ( usec , 1000000 ) ;
return usec ;
}
int timer_init ( void )
{
@ -45,7 +69,7 @@ int timer_init(void)
for ( i = 0 ; i < 100 ; i + + )
writel ( 0 , & gpt - > ctrl ) ; /* We have no udelay by now */
writel ( GPTPR_VAL , & gpt - > pre ) ;
writel ( 0 , & gpt - > pre ) ;
/* Freerun Mode, PERCLK1 input */
writel ( readl ( & gpt - > ctrl ) |
GPTCR_CLKSOURCE_IPG | GPTCR_TEN ,
@ -54,58 +78,59 @@ int timer_init(void)
return 0 ;
}
void reset_timer_masked ( void )
unsigned long long get_ticks ( void )
{
struct gpt_regs * gpt = ( struct gpt_regs * ) GPT1_BASE_ADDR ;
writel ( 0 , & gpt - > ctrl ) ;
/* Freerun Mode, PERCLK1 input */
writel ( GPTCR_CLKSOURCE_IPG | GPTCR_TEN ,
& gpt - > ctrl ) ;
ulong now = readl ( & gpt - > counter ) ; /* current tick value */
if ( now > = lastinc ) {
/*
* normal mode ( non roll )
* move stamp forward with absolut diff ticks
*/
timestamp + = ( now - lastinc ) ;
} else {
/* we have rollover of incrementer */
timestamp + = ( 0xFFFFFFFF - lastinc ) + now ;
}
lastinc = now ;
return timestamp ;
}
inline ulong get_timer_masked ( void )
ulong get_timer_masked ( void )
{
struct gpt_regs * gpt = ( struct gpt_regs * ) GPT1_BASE_ADDR ;
ulong val = readl ( & gpt - > counter ) ;
return val ;
/*
* get_ticks ( ) returns a long long ( 64 bit ) , it wraps in
* 2 ^ 64 / CONFIG_MX25_CLK32 = 2 ^ 64 / 2 ^ 15 = 2 ^ 49 ~ 5 * 10 ^ 14 ( s ) ~
* 5 * 10 ^ 9 days . . . and get_ticks ( ) * CONFIG_SYS_HZ wraps in
* 5 * 10 ^ 6 days - long enough .
*/
return tick_to_time ( get_ticks ( ) ) ;
}
ulong get_timer ( ulong base )
{
ulong tmp ;
return get_timer_masked ( ) - base ;
}
tmp = get_timer_masked ( ) ;
/* delay x useconds AND preserve advance timstamp value */
void __udelay ( unsigned long usec )
{
unsigned long long tmp ;
ulong tmo ;
if ( tmp < = ( base * 1000 ) ) {
/* Overflow */
tmp + = ( 0xffffffff - base ) ;
}
tmo = us_to_tick ( usec ) ;
tmp = get_ticks ( ) + tmo ; /* get current timestamp */
return ( tmp / 1000 ) - base ;
while ( get_ticks ( ) < tmp ) /* loop till event */
/*NOP*/ ;
}
/*
* delay x useconds AND preserve advance timstamp value
* GPTCNT is now supposed to tick 1 by 1 us .
* This function is derived from PowerPC code ( timebase clock frequency ) .
* On ARM it returns the number of timer ticks per second .
*/
void __udelay ( unsigned long usec )
ulong get_tbclk ( void )
{
ulong tmp ;
tmp = get_timer_masked ( ) ; /* get current timestamp */
/* if setting this forward will roll time stamp */
if ( ( usec + tmp + 1 ) < tmp ) {
/* reset "advancing" timestamp to 0, set lastinc value */
reset_timer_masked ( ) ;
} else {
/* else, set advancing stamp wake up time */
tmp + = usec ;
}
while ( get_timer_masked ( ) < tmp ) /* loop till event */
/*NOP*/ ;
return TIMER_FREQ_HZ ;
}