]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
4 | * Marius Groeger <[email protected]> | |
5 | * | |
6 | * (C) Copyright 2002 | |
7 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
8 | * Alex Zuepke <[email protected]> | |
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 | |
cd0a9de6 | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
c609719b WD |
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> | |
c609719b | 31 | #include <asm/proc-armv/ptrace.h> |
39539887 | 32 | #include <asm/hardware.h> |
c609719b | 33 | |
2d1a537d | 34 | #ifndef CONFIG_NETARM |
c609719b WD |
35 | /* we always count down the max. */ |
36 | #define TIMER_LOAD_VAL 0xffff | |
c609719b WD |
37 | /* macro to read the 16 bit timer */ |
38 | #define READ_TIMER (IO_TC1D & 0xffff) | |
6bd2447e GJ |
39 | |
40 | #ifdef CONFIG_LPC2292 | |
41 | #undef READ_TIMER | |
42 | #define READ_TIMER (0xFFFFFFFF - GET32(T0TC)) | |
43 | #endif | |
44 | ||
2d1a537d WD |
45 | #else |
46 | #define IRQEN (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_INTR_ENABLE)) | |
cd0a9de6 WD |
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)) | |
2d1a537d WD |
49 | #define TIMER_LOAD_VAL NETARM_GEN_TSTAT_CTC_MASK |
50 | #define READ_TIMER (TM2STAT & NETARM_GEN_TSTAT_CTC_MASK) | |
51 | #endif | |
c609719b | 52 | |
a1f4a3dd WD |
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 | ||
c609719b | 62 | #ifdef CONFIG_USE_IRQ |
c609719b WD |
63 | void do_irq (struct pt_regs *pt_regs) |
64 | { | |
6d0943a6 | 65 | #if defined(CONFIG_S3C4510B) |
a1f4a3dd WD |
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 | } | |
87cb6862 WD |
74 | #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) |
75 | /* No do_irq() for IntegratorAP/CM720T as yet */ | |
6bd2447e GJ |
76 | #elif defined(CONFIG_LPC2292) |
77 | ||
78 | void (*pfnct)(void); | |
79 | ||
80 | pfnct = (void (*)(void))VICVectAddr; | |
81 | ||
82 | (*pfnct)(); | |
a1f4a3dd WD |
83 | #else |
84 | #error do_irq() not defined for this CPU type | |
85 | #endif | |
86 | } | |
6d0943a6 | 87 | #endif |
a1f4a3dd WD |
88 | |
89 | #ifdef CONFIG_S3C4510B | |
90 | static void default_isr( void *data) { | |
91 | printf ("default_isr(): called for IRQ %d\n", (int)data); | |
c609719b WD |
92 | } |
93 | ||
a1f4a3dd WD |
94 | static void timer_isr( void *data) { |
95 | unsigned int *pTime = (unsigned int *)data; | |
96 | ||
97 | (*pTime)++; | |
98 | if ( !(*pTime % (CFG_HZ/4))) { | |
99 | /* toggle LED 0 */ | |
100 | PUT_REG( REG_IOPDATA, GET_REG(REG_IOPDATA) ^ 0x1); | |
101 | } | |
102 | ||
103 | } | |
104 | #endif | |
105 | ||
87cb6862 WD |
106 | #if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) |
107 | /* Use IntegratorAP routines in board/integratorap.c */ | |
108 | #else | |
109 | ||
96782c63 WD |
110 | static ulong timestamp; |
111 | static ulong lastdec; | |
112 | ||
c609719b WD |
113 | int interrupt_init (void) |
114 | { | |
39539887 WD |
115 | |
116 | #if defined(CONFIG_NETARM) | |
cd0a9de6 | 117 | /* disable all interrupts */ |
2d1a537d WD |
118 | IRQEN = 0; |
119 | ||
120 | /* operate timer 2 in non-prescale mode */ | |
121 | TM2CTRL = ( NETARM_GEN_TIMER_SET_HZ(CFG_HZ) | | |
122 | NETARM_GEN_TCTL_ENABLE | | |
123 | NETARM_GEN_TCTL_INIT_COUNT(TIMER_LOAD_VAL)); | |
124 | ||
125 | /* set timer 2 counter */ | |
126 | lastdec = TIMER_LOAD_VAL; | |
c570b2fd | 127 | #elif defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) |
c609719b WD |
128 | /* disable all interrupts */ |
129 | IO_INTMR1 = 0; | |
130 | ||
131 | /* operate timer 1 in prescale mode */ | |
132 | IO_SYSCON1 |= SYSCON1_TC1M; | |
133 | ||
134 | /* select 2kHz clock source for timer 1 */ | |
135 | IO_SYSCON1 &= ~SYSCON1_TC1S; | |
136 | ||
137 | /* set timer 1 counter */ | |
138 | lastdec = IO_TC1D = TIMER_LOAD_VAL; | |
39539887 | 139 | #elif defined(CONFIG_S3C4510B) |
a1f4a3dd WD |
140 | int i; |
141 | ||
142 | /* install default interrupt handlers */ | |
143 | for ( i = 0; i < N_IRQS; i++) { | |
144 | IRQ_HANDLER[i].m_data = (void *)i; | |
145 | IRQ_HANDLER[i].m_func = default_isr; | |
146 | } | |
147 | ||
148 | /* configure interrupts for IRQ mode */ | |
149 | PUT_REG( REG_INTMODE, 0x0); | |
150 | /* clear any pending interrupts */ | |
151 | PUT_REG( REG_INTPEND, 0x1FFFFF); | |
152 | ||
39539887 | 153 | lastdec = 0; |
a1f4a3dd WD |
154 | |
155 | /* install interrupt handler for timer */ | |
156 | IRQ_HANDLER[INT_TIMER0].m_data = (void *)×tamp; | |
157 | IRQ_HANDLER[INT_TIMER0].m_func = timer_isr; | |
158 | ||
159 | /* configure free running timer 0 */ | |
160 | PUT_REG( REG_TMOD, 0x0); | |
161 | /* Stop timer 0 */ | |
162 | CLR_REG( REG_TMOD, TM0_RUN); | |
163 | ||
164 | /* Configure for interval mode */ | |
165 | CLR_REG( REG_TMOD, TM1_TOGGLE); | |
166 | ||
167 | /* | |
168 | * Load Timer data register with count down value. | |
169 | * count_down_val = CFG_SYS_CLK_FREQ/CFG_HZ | |
170 | */ | |
171 | PUT_REG( REG_TDATA0, (CFG_SYS_CLK_FREQ / CFG_HZ)); | |
172 | ||
173 | /* | |
174 | * Enable global interrupt | |
175 | * Enable timer0 interrupt | |
176 | */ | |
177 | CLR_REG( REG_INTMASK, ((1<<INT_GLOBAL) | (1<<INT_TIMER0))); | |
178 | ||
179 | /* Start timer */ | |
180 | SET_REG( REG_TMOD, TM0_RUN); | |
6bd2447e GJ |
181 | #elif defined(CONFIG_LPC2292) |
182 | PUT32(T0IR, 0); /* disable all timer0 interrupts */ | |
183 | PUT32(T0TCR, 0); /* disable timer0 */ | |
184 | PUT32(T0PR, CFG_SYS_CLK_FREQ / CFG_HZ); | |
53677ef1 | 185 | PUT32(T0MCR, 0); |
6bd2447e GJ |
186 | PUT32(T0TC, 0); |
187 | PUT32(T0TCR, 1); /* enable timer0 */ | |
a1f4a3dd | 188 | |
39539887 WD |
189 | #else |
190 | #error No interrupt_init() defined for this CPU type | |
2d1a537d | 191 | #endif |
c609719b WD |
192 | timestamp = 0; |
193 | ||
194 | return (0); | |
195 | } | |
196 | ||
87cb6862 WD |
197 | #endif /* ! IntegratorAP */ |
198 | ||
c609719b WD |
199 | /* |
200 | * timer without interrupts | |
201 | */ | |
202 | ||
39539887 | 203 | |
6bd2447e | 204 | #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_NETARM) || defined(CONFIG_ARMADILLO) || defined(CONFIG_LPC2292) |
39539887 | 205 | |
c609719b WD |
206 | void reset_timer (void) |
207 | { | |
208 | reset_timer_masked (); | |
209 | } | |
210 | ||
211 | ulong get_timer (ulong base) | |
212 | { | |
213 | return get_timer_masked () - base; | |
214 | } | |
215 | ||
216 | void set_timer (ulong t) | |
217 | { | |
218 | timestamp = t; | |
219 | } | |
220 | ||
221 | void udelay (unsigned long usec) | |
222 | { | |
223 | ulong tmo; | |
224 | ||
225 | tmo = usec / 1000; | |
226 | tmo *= CFG_HZ; | |
227 | tmo /= 1000; | |
228 | ||
229 | tmo += get_timer (0); | |
230 | ||
231 | while (get_timer_masked () < tmo) | |
6bd2447e GJ |
232 | #ifdef CONFIG_LPC2292 |
233 | /* GJ - not sure whether this is really needed or a misunderstanding */ | |
234 | __asm__ __volatile__(" nop"); | |
235 | #else | |
c609719b | 236 | /*NOP*/; |
6bd2447e | 237 | #endif |
c609719b WD |
238 | } |
239 | ||
240 | void reset_timer_masked (void) | |
241 | { | |
242 | /* reset time */ | |
243 | lastdec = READ_TIMER; | |
244 | timestamp = 0; | |
245 | } | |
246 | ||
247 | ulong get_timer_masked (void) | |
248 | { | |
249 | ulong now = READ_TIMER; | |
250 | ||
251 | if (lastdec >= now) { | |
252 | /* normal mode */ | |
253 | timestamp += lastdec - now; | |
254 | } else { | |
255 | /* we have an overflow ... */ | |
256 | timestamp += lastdec + TIMER_LOAD_VAL - now; | |
257 | } | |
258 | lastdec = now; | |
259 | ||
260 | return timestamp; | |
261 | } | |
262 | ||
263 | void udelay_masked (unsigned long usec) | |
264 | { | |
265 | ulong tmo; | |
101e8dfa WD |
266 | ulong endtime; |
267 | signed long diff; | |
c609719b | 268 | |
101e8dfa WD |
269 | if (usec >= 1000) { |
270 | tmo = usec / 1000; | |
271 | tmo *= CFG_HZ; | |
272 | tmo /= 1000; | |
273 | } else { | |
274 | tmo = usec * CFG_HZ; | |
275 | tmo /= (1000*1000); | |
276 | } | |
c609719b | 277 | |
101e8dfa | 278 | endtime = get_timer_masked () + tmo; |
c609719b | 279 | |
101e8dfa WD |
280 | do { |
281 | ulong now = get_timer_masked (); | |
282 | diff = endtime - now; | |
283 | } while (diff >= 0); | |
c609719b | 284 | } |
39539887 WD |
285 | |
286 | #elif defined(CONFIG_S3C4510B) | |
287 | ||
a1f4a3dd WD |
288 | ulong get_timer (ulong base) |
289 | { | |
290 | return timestamp - base; | |
291 | } | |
39539887 WD |
292 | |
293 | void udelay (unsigned long usec) | |
294 | { | |
a1f4a3dd | 295 | u32 ticks; |
39539887 | 296 | |
a1f4a3dd | 297 | ticks = (usec * CFG_HZ) / 1000000; |
39539887 | 298 | |
a1f4a3dd | 299 | ticks += get_timer (0); |
39539887 | 300 | |
a1f4a3dd WD |
301 | while (get_timer (0) < ticks) |
302 | /*NOP*/; | |
39539887 | 303 | |
39539887 WD |
304 | } |
305 | ||
87cb6862 WD |
306 | #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) |
307 | /* No timer routines for IntegratorAP/CM720T as yet */ | |
39539887 WD |
308 | #else |
309 | #error Timer routines not defined for this CPU type | |
310 | #endif |