1/* 2 * (C) Copyright 2002 3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 4 * Marius Groeger <mgroeger@sysgo.de> 5 * 6 * (C) Copyright 2002 7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 8 * Alex Zuepke <azu@sysgo.de> 9 * 10 * (C) Copyright 2002 11 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> 12 * 13 * See file CREDITS for list of people who contributed to this 14 * project. 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 29 * MA 02111-1307 USA 30 */ 31 32#include <common.h> 33#ifdef CONFIG_S3C24X0 34 35#include <asm/io.h> 36#include <asm/arch/s3c24x0_cpu.h> 37 38int timer_load_val = 0; 39static ulong timer_clk; 40 41/* macro to read the 16 bit timer */ 42static inline ulong READ_TIMER(void) 43{ 44 struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); 45 46 return readl(&timers->TCNTO4) & 0xffff; 47} 48 49static ulong timestamp; 50static ulong lastdec; 51 52int timer_init(void) 53{ 54 struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); 55 ulong tmr; 56 57 /* use PWM Timer 4 because it has no output */ 58 /* prescaler for Timer 4 is 16 */ 59 writel(0x0f00, &timers->TCFG0); 60 if (timer_load_val == 0) { 61 /* 62 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 63 * (default) and prescaler = 16. Should be 10390 64 * @33.25MHz and 15625 @ 50 MHz 65 */ 66 timer_load_val = get_PCLK() / (2 * 16 * 100); 67 timer_clk = get_PCLK() / (2 * 16); 68 } 69 /* load value for 10 ms timeout */ 70 lastdec = timer_load_val; 71 writel(timer_load_val, &timers->TCNTB4); 72 /* auto load, manual update of Timer 4 */ 73 tmr = (readl(&timers->TCON) & ~0x0700000) | 0x0600000; 74 writel(tmr, &timers->TCON); 75 /* auto load, start Timer 4 */ 76 tmr = (tmr & ~0x0700000) | 0x0500000; 77 writel(tmr, &timers->TCON); 78 timestamp = 0; 79 80 return (0); 81} 82 83/* 84 * timer without interrupts 85 */ 86 87void reset_timer(void) 88{ 89 reset_timer_masked(); 90} 91 92ulong get_timer(ulong base) 93{ 94 return get_timer_masked() - base; 95} 96 97void set_timer(ulong t) 98{ 99 timestamp = t; 100} 101 102void __udelay (unsigned long usec) 103{ 104 ulong tmo; 105 ulong start = get_ticks(); 106 107 tmo = usec / 1000; 108 tmo *= (timer_load_val * 100); 109 tmo /= 1000; 110 111 while ((ulong) (get_ticks() - start) < tmo) 112 /*NOP*/; 113} 114 115void reset_timer_masked(void) 116{ 117 /* reset time */ 118 lastdec = READ_TIMER(); 119 timestamp = 0; 120} 121 122ulong get_timer_masked(void) 123{ 124 ulong tmr = get_ticks(); 125 126 return tmr / (timer_clk / CONFIG_SYS_HZ); 127} 128 129void udelay_masked(unsigned long usec) 130{ 131 ulong tmo; 132 ulong endtime; 133 signed long diff; 134 135 if (usec >= 1000) { 136 tmo = usec / 1000; 137 tmo *= (timer_load_val * 100); 138 tmo /= 1000; 139 } else { 140 tmo = usec * (timer_load_val * 100); 141 tmo /= (1000 * 1000); 142 } 143 144 endtime = get_ticks() + tmo; 145 146 do { 147 ulong now = get_ticks(); 148 diff = endtime - now; 149 } while (diff >= 0); 150} 151 152/* 153 * This function is derived from PowerPC code (read timebase as long long). 154 * On ARM it just returns the timer value. 155 */ 156unsigned long long get_ticks(void) 157{ 158 ulong now = READ_TIMER(); 159 160 if (lastdec >= now) { 161 /* normal mode */ 162 timestamp += lastdec - now; 163 } else { 164 /* we have an overflow ... */ 165 timestamp += lastdec + timer_load_val - now; 166 } 167 lastdec = now; 168 169 return timestamp; 170} 171 172/* 173 * This function is derived from PowerPC code (timebase clock frequency). 174 * On ARM it returns the number of timer ticks per second. 175 */ 176ulong get_tbclk(void) 177{ 178 ulong tbclk; 179 180#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB) 181 tbclk = timer_load_val * 100; 182#elif defined(CONFIG_SBC2410X) || \ 183 defined(CONFIG_SMDK2410) || \ 184 defined(CONFIG_VCMA9) 185 tbclk = CONFIG_SYS_HZ; 186#else 187# error "tbclk not configured" 188#endif 189 190 return tbclk; 191} 192 193/* 194 * reset the cpu by setting up the watchdog timer and let him time out 195 */ 196void reset_cpu(ulong ignored) 197{ 198 struct s3c24x0_watchdog *watchdog; 199 200#ifdef CONFIG_TRAB 201 extern void disable_vfd(void); 202 203 disable_vfd(); 204#endif 205 206 watchdog = s3c24x0_get_base_watchdog(); 207 208 /* Disable watchdog */ 209 writel(0x0000, &watchdog->WTCON); 210 211 /* Initialize watchdog timer count register */ 212 writel(0x0001, &watchdog->WTCNT); 213 214 /* Enable watchdog timer; assert reset at timer timeout */ 215 writel(0x0021, &watchdog->WTCON); 216 217 while (1) 218 /* loop forever and wait for reset to happen */; 219 220 /*NOTREACHED*/ 221} 222 223#endif /* CONFIG_S3C24X0 */ 224