diff options
Diffstat (limited to 'board/integratorap/integratorap.c')
-rw-r--r-- | board/integratorap/integratorap.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/board/integratorap/integratorap.c b/board/integratorap/integratorap.c index fb83c82..6140a7a 100644 --- a/board/integratorap/integratorap.c +++ b/board/integratorap/integratorap.c @@ -477,3 +477,140 @@ int dram_init (void) { return 0; } + +/* The Integrator/AP timer1 is clocked at 24MHz + * can be divided by 16 or 256 + * and is a 16-bit counter + */ +/* U-Boot expects a 32 bit timer running at CFG_HZ*/ +static ulong timestamp; /* U-Boot ticks since startup */ +static ulong total_count = 0; /* Total timer count */ +static ulong lastdec; /* Timer reading at last call */ +static ulong div_clock = 256; /* Divisor applied to the timer clock */ +static ulong div_timer = 1; /* Divisor to convert timer reading + * change to U-Boot ticks + */ +/* CFG_HZ = CFG_HZ_CLOCK/(div_clock * div_timer) */ + +#define TIMER_LOAD_VAL 0x0000FFFFL +#define READ_TIMER ((*(volatile ulong *)(CFG_TIMERBASE+4)) & 0x0000FFFFL) + +/* all function return values in U-Boot ticks i.e. (1/CFG_HZ) sec + * - unless otherwise stated + */ + +/* starts a counter + * - the Integrator/AP timer issues an interrupt + * each time it reaches zero + */ +int interrupt_init (void) +{ + /* Load timer with initial value */ + *(volatile ulong *)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be + * enabled 1 + * free-running 0 + * XX 00 + * divider 256 10 + * XX 00 + */ + *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x00000088; + total_count = 0; + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + div_timer = CFG_HZ_CLOCK / CFG_HZ; + div_timer /= div_clock; + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base_ticks) +{ + return get_timer_masked () - base_ticks; +} + +void set_timer (ulong ticks) +{ + timestamp = ticks; + total_count = ticks * div_timer; + reset_timer_masked(); +} + +/* delay x useconds */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec * CFG_HZ; + tmo /= (1000000L); + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* wake up timestamp */ + + while (get_timer_masked () < tmo)/* loop till event */ + { + /*NOP*/; + } +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capture current decrementer value */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +/* converts the timer reading to U-Boot ticks */ +/* the timestamp is the number of ticks since reset */ +/* This routine does not detect wraps unless called regularly + ASSUMES a call at least every 16 seconds to detect every reload */ +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current count */ + + if(now > lastdec) + { + /* Must have wrapped */ + total_count += lastdec + TIMER_LOAD_VAL + 1 - now; + } else { + total_count += lastdec - now; + } + lastdec = now; + timestamp = total_count/div_timer; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + udelay(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * Return the timebase clock frequency + * i.e. how often the timer decrements + */ +ulong get_tbclk (void) +{ + return CFG_HZ_CLOCK/div_clock; +} |