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_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) 153 /* disable all interrupts */ 154 IO_INTMR1 = 0; 155 156 /* operate timer 1 in prescale mode */ 157 IO_SYSCON1 |= SYSCON1_TC1M; 158 159 /* select 2kHz clock source for timer 1 */ 160 IO_SYSCON1 &= ~SYSCON1_TC1S; 161 162 /* set timer 1 counter */ 163 lastdec = IO_TC1D = TIMER_LOAD_VAL; 164 #elif defined(CONFIG_S3C4510B) 165 /* configure free running timer 0 */ 166 PUT_REG( REG_TMOD, 0x0); 167 /* Stop timer 0 */ 168 CLR_REG( REG_TMOD, TM0_RUN); 169 170 /* Configure for interval mode */ 171 CLR_REG( REG_TMOD, TM1_TOGGLE); 172 173 /* 174 * Load Timer data register with count down value. 175 * count_down_val = CONFIG_SYS_SYS_CLK_FREQ/CONFIG_SYS_HZ 176 */ 177 PUT_REG( REG_TDATA0, (CONFIG_SYS_SYS_CLK_FREQ / CONFIG_SYS_HZ)); 178 179 /* 180 * Enable global interrupt 181 * Enable timer0 interrupt 182 */ 183 CLR_REG( REG_INTMASK, ((1<<INT_GLOBAL) | (1<<INT_TIMER0))); 184 185 /* Start timer */ 186 SET_REG( REG_TMOD, TM0_RUN); 187 #elif defined(CONFIG_LPC2292) 188 PUT32(T0IR, 0); /* disable all timer0 interrupts */ 189 PUT32(T0TCR, 0); /* disable timer0 */ 190 PUT32(T0PR, CONFIG_SYS_SYS_CLK_FREQ / CONFIG_SYS_HZ); 191 PUT32(T0MCR, 0); 192 PUT32(T0TC, 0); 193 PUT32(T0TCR, 1); /* enable timer0 */ 194 195 #else 196 #error No timer_init() defined for this CPU type 197 #endif 198 timestamp = 0; 199 200 return (0); 201 } 202 203 #endif /* ! IntegratorAP */ 204 205 /* 206 * timer without interrupts 207 */ 208 209 210 #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_NETARM) || defined(CONFIG_ARMADILLO) || defined(CONFIG_LPC2292) 211 212 ulong get_timer (ulong base) 213 { 214 return get_timer_masked () - base; 215 } 216 217 void __udelay (unsigned long usec) 218 { 219 ulong tmo; 220 221 tmo = usec / 1000; 222 tmo *= CONFIG_SYS_HZ; 223 tmo /= 1000; 224 225 tmo += get_timer (0); 226 227 while (get_timer_masked () < tmo) 228 #ifdef CONFIG_LPC2292 229 /* GJ - not sure whether this is really needed or a misunderstanding */ 230 __asm__ __volatile__(" nop"); 231 #else 232 /*NOP*/; 233 #endif 234 } 235 236 ulong get_timer_masked (void) 237 { 238 ulong now = READ_TIMER; 239 240 if (lastdec >= now) { 241 /* normal mode */ 242 timestamp += lastdec - now; 243 } else { 244 /* we have an overflow ... */ 245 timestamp += lastdec + TIMER_LOAD_VAL - now; 246 } 247 lastdec = now; 248 249 return timestamp; 250 } 251 252 void udelay_masked (unsigned long usec) 253 { 254 ulong tmo; 255 ulong endtime; 256 signed long diff; 257 258 if (usec >= 1000) { 259 tmo = usec / 1000; 260 tmo *= CONFIG_SYS_HZ; 261 tmo /= 1000; 262 } else { 263 tmo = usec * CONFIG_SYS_HZ; 264 tmo /= (1000*1000); 265 } 266 267 endtime = get_timer_masked () + tmo; 268 269 do { 270 ulong now = get_timer_masked (); 271 diff = endtime - now; 272 } while (diff >= 0); 273 } 274 275 #elif defined(CONFIG_S3C4510B) 276 277 ulong get_timer (ulong base) 278 { 279 return timestamp - base; 280 } 281 282 void __udelay (unsigned long usec) 283 { 284 u32 ticks; 285 286 ticks = (usec * CONFIG_SYS_HZ) / 1000000; 287 288 ticks += get_timer (0); 289 290 while (get_timer (0) < ticks) 291 /*NOP*/; 292 293 } 294 295 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 296 /* No timer routines for IntegratorAP/CM720T as yet */ 297 #else 298 #error Timer routines not defined for this CPU type 299 #endif 300