1/* 2 * (C) Copyright 2004 3 * Texas Instruments 4 * Richard Woodruff <r-woodruff2@ti.com> 5 * 6 * (C) Copyright 2002 7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 8 * Marius Groeger <mgroeger@sysgo.de> 9 * Alex Zuepke <azu@sysgo.de> 10 * 11 * (C) Copyright 2002 12 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> 13 * 14 * See file CREDITS for list of people who contributed to this 15 * project. 16 * 17 * This program is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU General Public License as 19 * published by the Free Software Foundation; either version 2 of 20 * the License, or (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 30 * MA 02111-1307 USA 31 */ 32 33#include <common.h> 34#include <asm/arch/bits.h> 35#include <asm/arch/omap2420.h> 36 37#define TIMER_LOAD_VAL 0 38 39/* macro to read the 32 bit timer */ 40#define READ_TIMER (*((volatile ulong *)(CONFIG_SYS_TIMERBASE+TCRR))) 41 42DECLARE_GLOBAL_DATA_PTR; 43 44int timer_init (void) 45{ 46 int32_t val; 47 48 /* Start the counter ticking up */ 49 *((int32_t *) (CONFIG_SYS_TIMERBASE + TLDR)) = TIMER_LOAD_VAL; /* reload value on overflow*/ 50 val = (CONFIG_SYS_PTV << 2) | BIT5 | BIT1 | BIT0; /* mask to enable timer*/ 51 *((int32_t *) (CONFIG_SYS_TIMERBASE + TCLR)) = val; /* start timer */ 52 53 reset_timer_masked(); /* init the timestamp and lastinc value */ 54 55 return(0); 56} 57/* 58 * timer without interrupts 59 */ 60void reset_timer (void) 61{ 62 reset_timer_masked (); 63} 64 65ulong get_timer (ulong base) 66{ 67 return get_timer_masked () - base; 68} 69 70void set_timer (ulong t) 71{ 72 gd->tbl = t; 73} 74 75/* delay x useconds AND preserve advance timestamp value */ 76void __udelay (unsigned long usec) 77{ 78 ulong tmo, tmp; 79 80 if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ 81 tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ 82 tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */ 83 tmo /= 1000; /* finish normalize. */ 84 } else { /* else small number, don't kill it prior to HZ multiply */ 85 tmo = usec * CONFIG_SYS_HZ; 86 tmo /= (1000*1000); 87 } 88 89 tmp = get_timer (0); /* get current timestamp */ 90 if ( (tmo + tmp + 1) < tmp ) /* if setting this forward will roll time stamp */ 91 reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastinc value */ 92 else 93 tmo += tmp; /* else, set advancing stamp wake up time */ 94 while (get_timer_masked () < tmo)/* loop till event */ 95 /*NOP*/; 96} 97 98void reset_timer_masked (void) 99{ 100 /* reset time */ 101 gd->lastinc = READ_TIMER; /* capture current incrementer value time */ 102 gd->tbl = 0; /* start "advancing" time stamp from 0 */ 103} 104 105ulong get_timer_masked (void) 106{ 107 ulong now = READ_TIMER; /* current tick value */ 108 109 if (now >= gd->lastinc) /* normal mode (non roll) */ 110 gd->tbl += (now - gd->lastinc); /* move stamp fordward with absoulte diff ticks */ 111 else /* we have rollover of incrementer */ 112 gd->tbl += (0xFFFFFFFF - gd->lastinc) + now; 113 gd->lastinc = now; 114 return gd->tbl; 115} 116 117/* waits specified delay value and resets timestamp */ 118void udelay_masked (unsigned long usec) 119{ 120 ulong tmo; 121 ulong endtime; 122 signed long diff; 123 124 if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ 125 tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ 126 tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */ 127 tmo /= 1000; /* finish normalize. */ 128 } else { /* else small number, don't kill it prior to HZ multiply */ 129 tmo = usec * CONFIG_SYS_HZ; 130 tmo /= (1000*1000); 131 } 132 endtime = get_timer_masked () + tmo; 133 134 do { 135 ulong now = get_timer_masked (); 136 diff = endtime - now; 137 } while (diff >= 0); 138} 139 140/* 141 * This function is derived from PowerPC code (read timebase as long long). 142 * On ARM it just returns the timer value. 143 */ 144unsigned long long get_ticks(void) 145{ 146 return get_timer(0); 147} 148/* 149 * This function is derived from PowerPC code (timebase clock frequency). 150 * On ARM it returns the number of timer ticks per second. 151 */ 152ulong get_tbclk (void) 153{ 154 ulong tbclk; 155 tbclk = CONFIG_SYS_HZ; 156 return tbclk; 157} 158