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 * See file CREDITS for list of people who contributed to this 11 * project. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 26 * MA 02111-1307 USA 27 */ 28 29 #include <common.h> 30 #include <clps7111.h> 31 #include <asm/proc-armv/ptrace.h> 32 #include <asm/hardware.h> 33 34 #ifndef CONFIG_NETARM 35 /* we always count down the max. */ 36 #define TIMER_LOAD_VAL 0xffff 37 /* macro to read the 16 bit timer */ 38 #define READ_TIMER (IO_TC1D & 0xffff) 39 40 #ifdef CONFIG_LPC2292 41 #undef READ_TIMER 42 #define READ_TIMER (0xFFFFFFFF - GET32(T0TC)) 43 #endif 44 45 #else 46 #define IRQEN (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_INTR_ENABLE)) 47 #define TM2CTRL (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_TIMER2_CONTROL)) 48 #define TM2STAT (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_TIMER2_STATUS)) 49 #define TIMER_LOAD_VAL NETARM_GEN_TSTAT_CTC_MASK 50 #define READ_TIMER (TM2STAT & NETARM_GEN_TSTAT_CTC_MASK) 51 #endif 52 53 #ifdef CONFIG_S3C4510B 54 /* require interrupts for the S3C4510B */ 55 # ifndef CONFIG_USE_IRQ 56 # error CONFIG_USE_IRQ _must_ be defined when using CONFIG_S3C4510B 57 # else 58 static struct _irq_handler IRQ_HANDLER[N_IRQS]; 59 # endif 60 #endif /* CONFIG_S3C4510B */ 61 62 #ifdef CONFIG_USE_IRQ 63 void do_irq (struct pt_regs *pt_regs) 64 { 65 #if defined(CONFIG_S3C4510B) 66 unsigned int pending; 67 68 while ( (pending = GET_REG( REG_INTOFFSET)) != 0x54) { /* sentinal value for no pending interrutps */ 69 IRQ_HANDLER[pending>>2].m_func( IRQ_HANDLER[pending>>2].m_data); 70 71 /* clear pending interrupt */ 72 PUT_REG( REG_INTPEND, (1<<(pending>>2))); 73 } 74 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 75 /* No do_irq() for IntegratorAP/CM720T as yet */ 76 #elif defined(CONFIG_LPC2292) 77 78 void (*pfnct)(void); 79 80 pfnct = (void (*)(void))VICVectAddr; 81 82 (*pfnct)(); 83 #else 84 #error do_irq() not defined for this CPU type 85 #endif 86 } 87 #endif 88 89 #ifdef CONFIG_S3C4510B 90 static void default_isr( void *data) { 91 printf ("default_isr(): called for IRQ %d\n", (int)data); 92 } 93 94 static void timer_isr( void *data) { 95 unsigned int *pTime = (unsigned int *)data; 96 97 (*pTime)++; 98 if ( !(*pTime % (CONFIG_SYS_HZ/4))) { 99 /* toggle LED 0 */ 100 PUT_REG( REG_IOPDATA, GET_REG(REG_IOPDATA) ^ 0x1); 101 } 102 103 } 104 #endif 105 106 #if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 107 /* Use IntegratorAP routines in board/integratorap.c */ 108 #else 109 110 static ulong timestamp; 111 static ulong lastdec; 112 113 #if defined(CONFIG_USE_IRQ) && defined(CONFIG_S3C4510B) 114 int arch_interrupt_init (void) 115 { 116 int i; 117 118 /* install default interrupt handlers */ 119 for ( i = 0; i < N_IRQS; i++) { 120 IRQ_HANDLER[i].m_data = (void *)i; 121 IRQ_HANDLER[i].m_func = default_isr; 122 } 123 124 /* configure interrupts for IRQ mode */ 125 PUT_REG( REG_INTMODE, 0x0); 126 /* clear any pending interrupts */ 127 PUT_REG( REG_INTPEND, 0x1FFFFF); 128 129 lastdec = 0; 130 131 /* install interrupt handler for timer */ 132 IRQ_HANDLER[INT_TIMER0].m_data = (void *)×tamp; 133 IRQ_HANDLER[INT_TIMER0].m_func = timer_isr; 134 135 return 0; 136 } 137 #endif 138 139 int timer_init (void) 140 { 141 #if defined(CONFIG_NETARM) 142 /* disable all interrupts */ 143 IRQEN = 0; 144 145 /* operate timer 2 in non-prescale mode */ 146 TM2CTRL = ( NETARM_GEN_TIMER_SET_HZ(CONFIG_SYS_HZ) | 147 NETARM_GEN_TCTL_ENABLE | 148 NETARM_GEN_TCTL_INIT_COUNT(TIMER_LOAD_VAL)); 149 150 /* set timer 2 counter */ 151 lastdec = TIMER_LOAD_VAL; 152 #elif defined(CONFIG_S3C4510B) 153 /* configure free running timer 0 */ 154 PUT_REG( REG_TMOD, 0x0); 155 /* Stop timer 0 */ 156 CLR_REG( REG_TMOD, TM0_RUN); 157 158 /* Configure for interval mode */ 159 CLR_REG( REG_TMOD, TM1_TOGGLE); 160 161 /* 162 * Load Timer data register with count down value. 163 * count_down_val = CONFIG_SYS_SYS_CLK_FREQ/CONFIG_SYS_HZ 164 */ 165 PUT_REG( REG_TDATA0, (CONFIG_SYS_SYS_CLK_FREQ / CONFIG_SYS_HZ)); 166 167 /* 168 * Enable global interrupt 169 * Enable timer0 interrupt 170 */ 171 CLR_REG( REG_INTMASK, ((1<<INT_GLOBAL) | (1<<INT_TIMER0))); 172 173 /* Start timer */ 174 SET_REG( REG_TMOD, TM0_RUN); 175 #elif defined(CONFIG_LPC2292) 176 PUT32(T0IR, 0); /* disable all timer0 interrupts */ 177 PUT32(T0TCR, 0); /* disable timer0 */ 178 PUT32(T0PR, CONFIG_SYS_SYS_CLK_FREQ / CONFIG_SYS_HZ); 179 PUT32(T0MCR, 0); 180 PUT32(T0TC, 0); 181 PUT32(T0TCR, 1); /* enable timer0 */ 182 183 #elif defined(CONFIG_TEGRA) 184 /* No timer routines for tegra as yet */ 185 lastdec = 0; 186 #else 187 #error No timer_init() defined for this CPU type 188 #endif 189 timestamp = 0; 190 191 return (0); 192 } 193 194 #endif /* ! IntegratorAP */ 195 196 /* 197 * timer without interrupts 198 */ 199 200 201 #if defined(CONFIG_NETARM) || defined(CONFIG_LPC2292) 202 203 ulong get_timer (ulong base) 204 { 205 return get_timer_masked () - base; 206 } 207 208 void __udelay (unsigned long usec) 209 { 210 ulong tmo; 211 212 tmo = usec / 1000; 213 tmo *= CONFIG_SYS_HZ; 214 tmo /= 1000; 215 216 tmo += get_timer (0); 217 218 while (get_timer_masked () < tmo) 219 #ifdef CONFIG_LPC2292 220 /* GJ - not sure whether this is really needed or a misunderstanding */ 221 __asm__ __volatile__(" nop"); 222 #else 223 /*NOP*/; 224 #endif 225 } 226 227 ulong get_timer_masked (void) 228 { 229 ulong now = READ_TIMER; 230 231 if (lastdec >= now) { 232 /* normal mode */ 233 timestamp += lastdec - now; 234 } else { 235 /* we have an overflow ... */ 236 timestamp += lastdec + TIMER_LOAD_VAL - now; 237 } 238 lastdec = now; 239 240 return timestamp; 241 } 242 243 void udelay_masked (unsigned long usec) 244 { 245 ulong tmo; 246 ulong endtime; 247 signed long diff; 248 249 if (usec >= 1000) { 250 tmo = usec / 1000; 251 tmo *= CONFIG_SYS_HZ; 252 tmo /= 1000; 253 } else { 254 tmo = usec * CONFIG_SYS_HZ; 255 tmo /= (1000*1000); 256 } 257 258 endtime = get_timer_masked () + tmo; 259 260 do { 261 ulong now = get_timer_masked (); 262 diff = endtime - now; 263 } while (diff >= 0); 264 } 265 266 #elif defined(CONFIG_S3C4510B) 267 268 ulong get_timer (ulong base) 269 { 270 return timestamp - base; 271 } 272 273 void __udelay (unsigned long usec) 274 { 275 u32 ticks; 276 277 ticks = (usec * CONFIG_SYS_HZ) / 1000000; 278 279 ticks += get_timer (0); 280 281 while (get_timer (0) < ticks) 282 /*NOP*/; 283 284 } 285 286 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 287 /* No timer routines for IntegratorAP/CM720T as yet */ 288 #elif defined(CONFIG_TEGRA) 289 /* No timer routines for tegra as yet */ 290 #else 291 #error Timer routines not defined for this CPU type 292 #endif 293