1*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* 2*576afd4fSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 3*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 4*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Marius Groeger <mgroeger@sysgo.de> 5*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 6*576afd4fSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 7*576afd4fSJean-Christophe PLAGNIOL-VILLARD * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> 8*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 9*576afd4fSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2003 10*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Texas Instruments, <www.ti.com> 11*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Kshitij Gupta <Kshitij@ti.com> 12*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 13*576afd4fSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2004 14*576afd4fSJean-Christophe PLAGNIOL-VILLARD * ARM Ltd. 15*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Philippe Robin, <philippe.robin@arm.com> 16*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 17*576afd4fSJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 18*576afd4fSJean-Christophe PLAGNIOL-VILLARD * project. 19*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 20*576afd4fSJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 21*576afd4fSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 22*576afd4fSJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 23*576afd4fSJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 24*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 25*576afd4fSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 26*576afd4fSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 27*576afd4fSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28*576afd4fSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 29*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 30*576afd4fSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 31*576afd4fSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 32*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 33*576afd4fSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 34*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 35*576afd4fSJean-Christophe PLAGNIOL-VILLARD 36*576afd4fSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 37*576afd4fSJean-Christophe PLAGNIOL-VILLARD #include <div64.h> 38*576afd4fSJean-Christophe PLAGNIOL-VILLARD 39*576afd4fSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_ARCH_CINTEGRATOR 40*576afd4fSJean-Christophe PLAGNIOL-VILLARD #define DIV_CLOCK_INIT 1 41*576afd4fSJean-Christophe PLAGNIOL-VILLARD #define TIMER_LOAD_VAL 0xFFFFFFFFL 42*576afd4fSJean-Christophe PLAGNIOL-VILLARD #else 43*576afd4fSJean-Christophe PLAGNIOL-VILLARD #define DIV_CLOCK_INIT 256 44*576afd4fSJean-Christophe PLAGNIOL-VILLARD #define TIMER_LOAD_VAL 0x0000FFFFL 45*576afd4fSJean-Christophe PLAGNIOL-VILLARD #endif 46*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* The Integrator/CP timer1 is clocked at 1MHz 47*576afd4fSJean-Christophe PLAGNIOL-VILLARD * can be divided by 16 or 256 48*576afd4fSJean-Christophe PLAGNIOL-VILLARD * and can be set up as a 32-bit timer 49*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 50*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ */ 51*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Keep total timer count to avoid losing decrements < div_timer */ 52*576afd4fSJean-Christophe PLAGNIOL-VILLARD static unsigned long long total_count = 0; 53*576afd4fSJean-Christophe PLAGNIOL-VILLARD static unsigned long long lastdec; /* Timer reading at last call */ 54*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Divisor applied to timer clock */ 55*576afd4fSJean-Christophe PLAGNIOL-VILLARD static unsigned long long div_clock = DIV_CLOCK_INIT; 56*576afd4fSJean-Christophe PLAGNIOL-VILLARD static unsigned long long div_timer = 1; /* Divisor to convert timer reading 57*576afd4fSJean-Christophe PLAGNIOL-VILLARD * change to U-Boot ticks 58*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 59*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* CONFIG_SYS_HZ = CONFIG_SYS_HZ_CLOCK/(div_clock * div_timer) */ 60*576afd4fSJean-Christophe PLAGNIOL-VILLARD static ulong timestamp; /* U-Boot ticks since startup */ 61*576afd4fSJean-Christophe PLAGNIOL-VILLARD 62*576afd4fSJean-Christophe PLAGNIOL-VILLARD #define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4)) 63*576afd4fSJean-Christophe PLAGNIOL-VILLARD 64*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* all function return values in U-Boot ticks i.e. (1/CONFIG_SYS_HZ) sec 65*576afd4fSJean-Christophe PLAGNIOL-VILLARD * - unless otherwise stated 66*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 67*576afd4fSJean-Christophe PLAGNIOL-VILLARD 68*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* starts up a counter 69*576afd4fSJean-Christophe PLAGNIOL-VILLARD * - the Integrator/CP timer can be set up to issue an interrupt */ 70*576afd4fSJean-Christophe PLAGNIOL-VILLARD int timer_init (void) 71*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 72*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Load timer with initial value */ 73*576afd4fSJean-Christophe PLAGNIOL-VILLARD *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL; 74*576afd4fSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_ARCH_CINTEGRATOR 75*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Set timer to be 76*576afd4fSJean-Christophe PLAGNIOL-VILLARD * enabled 1 77*576afd4fSJean-Christophe PLAGNIOL-VILLARD * periodic 1 78*576afd4fSJean-Christophe PLAGNIOL-VILLARD * no interrupts 0 79*576afd4fSJean-Christophe PLAGNIOL-VILLARD * X 0 80*576afd4fSJean-Christophe PLAGNIOL-VILLARD * divider 1 00 == less rounding error 81*576afd4fSJean-Christophe PLAGNIOL-VILLARD * 32 bit 1 82*576afd4fSJean-Christophe PLAGNIOL-VILLARD * wrapping 0 83*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 84*576afd4fSJean-Christophe PLAGNIOL-VILLARD *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x000000C2; 85*576afd4fSJean-Christophe PLAGNIOL-VILLARD #else 86*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Set timer to be 87*576afd4fSJean-Christophe PLAGNIOL-VILLARD * enabled 1 88*576afd4fSJean-Christophe PLAGNIOL-VILLARD * free-running 0 89*576afd4fSJean-Christophe PLAGNIOL-VILLARD * XX 00 90*576afd4fSJean-Christophe PLAGNIOL-VILLARD * divider 256 10 91*576afd4fSJean-Christophe PLAGNIOL-VILLARD * XX 00 92*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 93*576afd4fSJean-Christophe PLAGNIOL-VILLARD *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x00000088; 94*576afd4fSJean-Christophe PLAGNIOL-VILLARD #endif 95*576afd4fSJean-Christophe PLAGNIOL-VILLARD 96*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* init the timestamp */ 97*576afd4fSJean-Christophe PLAGNIOL-VILLARD total_count = 0ULL; 98*576afd4fSJean-Christophe PLAGNIOL-VILLARD reset_timer_masked(); 99*576afd4fSJean-Christophe PLAGNIOL-VILLARD 100*576afd4fSJean-Christophe PLAGNIOL-VILLARD div_timer = CONFIG_SYS_HZ_CLOCK; 101*576afd4fSJean-Christophe PLAGNIOL-VILLARD do_div(div_timer, CONFIG_SYS_HZ); 102*576afd4fSJean-Christophe PLAGNIOL-VILLARD do_div(div_timer, div_clock); 103*576afd4fSJean-Christophe PLAGNIOL-VILLARD 104*576afd4fSJean-Christophe PLAGNIOL-VILLARD return (0); 105*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 106*576afd4fSJean-Christophe PLAGNIOL-VILLARD 107*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* 108*576afd4fSJean-Christophe PLAGNIOL-VILLARD * timer without interrupts 109*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 110*576afd4fSJean-Christophe PLAGNIOL-VILLARD void reset_timer (void) 111*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 112*576afd4fSJean-Christophe PLAGNIOL-VILLARD reset_timer_masked (); 113*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 114*576afd4fSJean-Christophe PLAGNIOL-VILLARD 115*576afd4fSJean-Christophe PLAGNIOL-VILLARD ulong get_timer (ulong base_ticks) 116*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 117*576afd4fSJean-Christophe PLAGNIOL-VILLARD return get_timer_masked () - base_ticks; 118*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 119*576afd4fSJean-Christophe PLAGNIOL-VILLARD 120*576afd4fSJean-Christophe PLAGNIOL-VILLARD void set_timer (ulong ticks) 121*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 122*576afd4fSJean-Christophe PLAGNIOL-VILLARD timestamp = ticks; 123*576afd4fSJean-Christophe PLAGNIOL-VILLARD total_count = ticks * div_timer; 124*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 125*576afd4fSJean-Christophe PLAGNIOL-VILLARD 126*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* delay usec useconds */ 127*576afd4fSJean-Christophe PLAGNIOL-VILLARD void udelay (unsigned long usec) 128*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 129*576afd4fSJean-Christophe PLAGNIOL-VILLARD ulong tmo, tmp; 130*576afd4fSJean-Christophe PLAGNIOL-VILLARD 131*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Convert to U-Boot ticks */ 132*576afd4fSJean-Christophe PLAGNIOL-VILLARD tmo = usec * CONFIG_SYS_HZ; 133*576afd4fSJean-Christophe PLAGNIOL-VILLARD tmo /= (1000000L); 134*576afd4fSJean-Christophe PLAGNIOL-VILLARD 135*576afd4fSJean-Christophe PLAGNIOL-VILLARD tmp = get_timer_masked(); /* get current timestamp */ 136*576afd4fSJean-Christophe PLAGNIOL-VILLARD tmo += tmp; /* form target timestamp */ 137*576afd4fSJean-Christophe PLAGNIOL-VILLARD 138*576afd4fSJean-Christophe PLAGNIOL-VILLARD while (get_timer_masked () < tmo) {/* loop till event */ 139*576afd4fSJean-Christophe PLAGNIOL-VILLARD /*NOP*/; 140*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 141*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 142*576afd4fSJean-Christophe PLAGNIOL-VILLARD 143*576afd4fSJean-Christophe PLAGNIOL-VILLARD void reset_timer_masked (void) 144*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 145*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* capure current decrementer value */ 146*576afd4fSJean-Christophe PLAGNIOL-VILLARD lastdec = READ_TIMER; 147*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* start "advancing" time stamp from 0 */ 148*576afd4fSJean-Christophe PLAGNIOL-VILLARD timestamp = 0L; 149*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 150*576afd4fSJean-Christophe PLAGNIOL-VILLARD 151*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* converts the timer reading to U-Boot ticks */ 152*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* the timestamp is the number of ticks since reset */ 153*576afd4fSJean-Christophe PLAGNIOL-VILLARD ulong get_timer_masked (void) 154*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 155*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* get current count */ 156*576afd4fSJean-Christophe PLAGNIOL-VILLARD unsigned long long now = READ_TIMER; 157*576afd4fSJean-Christophe PLAGNIOL-VILLARD 158*576afd4fSJean-Christophe PLAGNIOL-VILLARD if(now > lastdec) { 159*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Must have wrapped */ 160*576afd4fSJean-Christophe PLAGNIOL-VILLARD total_count += lastdec + TIMER_LOAD_VAL + 1 - now; 161*576afd4fSJean-Christophe PLAGNIOL-VILLARD } else { 162*576afd4fSJean-Christophe PLAGNIOL-VILLARD total_count += lastdec - now; 163*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 164*576afd4fSJean-Christophe PLAGNIOL-VILLARD lastdec = now; 165*576afd4fSJean-Christophe PLAGNIOL-VILLARD 166*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* Reuse "now" */ 167*576afd4fSJean-Christophe PLAGNIOL-VILLARD now = total_count; 168*576afd4fSJean-Christophe PLAGNIOL-VILLARD do_div(now, div_timer); 169*576afd4fSJean-Christophe PLAGNIOL-VILLARD timestamp = now; 170*576afd4fSJean-Christophe PLAGNIOL-VILLARD 171*576afd4fSJean-Christophe PLAGNIOL-VILLARD return timestamp; 172*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 173*576afd4fSJean-Christophe PLAGNIOL-VILLARD 174*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* waits specified delay value and resets timestamp */ 175*576afd4fSJean-Christophe PLAGNIOL-VILLARD void udelay_masked (unsigned long usec) 176*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 177*576afd4fSJean-Christophe PLAGNIOL-VILLARD udelay(usec); 178*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 179*576afd4fSJean-Christophe PLAGNIOL-VILLARD 180*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* 181*576afd4fSJean-Christophe PLAGNIOL-VILLARD * This function is derived from PowerPC code (read timebase as long long). 182*576afd4fSJean-Christophe PLAGNIOL-VILLARD * On ARM it just returns the timer value. 183*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 184*576afd4fSJean-Christophe PLAGNIOL-VILLARD unsigned long long get_ticks(void) 185*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 186*576afd4fSJean-Christophe PLAGNIOL-VILLARD return get_timer(0); 187*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 188*576afd4fSJean-Christophe PLAGNIOL-VILLARD 189*576afd4fSJean-Christophe PLAGNIOL-VILLARD /* 190*576afd4fSJean-Christophe PLAGNIOL-VILLARD * Return the timebase clock frequency 191*576afd4fSJean-Christophe PLAGNIOL-VILLARD * i.e. how often the timer decrements 192*576afd4fSJean-Christophe PLAGNIOL-VILLARD */ 193*576afd4fSJean-Christophe PLAGNIOL-VILLARD ulong get_tbclk (void) 194*576afd4fSJean-Christophe PLAGNIOL-VILLARD { 195*576afd4fSJean-Christophe PLAGNIOL-VILLARD unsigned long long tmp = CONFIG_SYS_HZ_CLOCK; 196*576afd4fSJean-Christophe PLAGNIOL-VILLARD 197*576afd4fSJean-Christophe PLAGNIOL-VILLARD do_div(tmp, div_clock); 198*576afd4fSJean-Christophe PLAGNIOL-VILLARD 199*576afd4fSJean-Christophe PLAGNIOL-VILLARD return tmp; 200*576afd4fSJean-Christophe PLAGNIOL-VILLARD } 201