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 #else 184 #error No timer_init() defined for this CPU type 185 #endif 186 timestamp = 0; 187 188 return (0); 189 } 190 191 #endif /* ! IntegratorAP */ 192 193 /* 194 * timer without interrupts 195 */ 196 197 198 #if defined(CONFIG_NETARM) || defined(CONFIG_LPC2292) 199 200 ulong get_timer (ulong base) 201 { 202 return get_timer_masked () - base; 203 } 204 205 void __udelay (unsigned long usec) 206 { 207 ulong tmo; 208 209 tmo = usec / 1000; 210 tmo *= CONFIG_SYS_HZ; 211 tmo /= 1000; 212 213 tmo += get_timer (0); 214 215 while (get_timer_masked () < tmo) 216 #ifdef CONFIG_LPC2292 217 /* GJ - not sure whether this is really needed or a misunderstanding */ 218 __asm__ __volatile__(" nop"); 219 #else 220 /*NOP*/; 221 #endif 222 } 223 224 ulong get_timer_masked (void) 225 { 226 ulong now = READ_TIMER; 227 228 if (lastdec >= now) { 229 /* normal mode */ 230 timestamp += lastdec - now; 231 } else { 232 /* we have an overflow ... */ 233 timestamp += lastdec + TIMER_LOAD_VAL - now; 234 } 235 lastdec = now; 236 237 return timestamp; 238 } 239 240 void udelay_masked (unsigned long usec) 241 { 242 ulong tmo; 243 ulong endtime; 244 signed long diff; 245 246 if (usec >= 1000) { 247 tmo = usec / 1000; 248 tmo *= CONFIG_SYS_HZ; 249 tmo /= 1000; 250 } else { 251 tmo = usec * CONFIG_SYS_HZ; 252 tmo /= (1000*1000); 253 } 254 255 endtime = get_timer_masked () + tmo; 256 257 do { 258 ulong now = get_timer_masked (); 259 diff = endtime - now; 260 } while (diff >= 0); 261 } 262 263 #elif defined(CONFIG_S3C4510B) 264 265 ulong get_timer (ulong base) 266 { 267 return timestamp - base; 268 } 269 270 void __udelay (unsigned long usec) 271 { 272 u32 ticks; 273 274 ticks = (usec * CONFIG_SYS_HZ) / 1000000; 275 276 ticks += get_timer (0); 277 278 while (get_timer (0) < ticks) 279 /*NOP*/; 280 281 } 282 283 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 284 /* No timer routines for IntegratorAP/CM720T as yet */ 285 #else 286 #error Timer routines not defined for this CPU type 287 #endif 288