]> git.sur5r.net Git - u-boot/blob - lib_m68k/time.c
Added M5329AFEE and M5329BFEE Platforms
[u-boot] / lib_m68k / time.c
1 /*
2  * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
3  *
4  * (C) Copyright 2000
5  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27
28 #include <asm/mcftimer.h>
29
30 #ifdef  CONFIG_M5271
31 #include <asm/m5271.h>
32 #include <asm/immap_5271.h>
33 #endif
34
35 #ifdef  CONFIG_M5272
36 #include <asm/m5272.h>
37 #include <asm/immap_5272.h>
38 #endif
39
40 #ifdef  CONFIG_M5282
41 #include <asm/m5282.h>
42 #endif
43
44 #ifdef  CONFIG_M5249
45 #include <asm/m5249.h>
46 #include <asm/immap_5249.h>
47 #endif
48
49 static ulong timestamp;
50 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
51 static unsigned short lastinc;
52 #endif
53
54 #if defined(CONFIG_M5272)
55 /*
56  * We use timer 3 which is running with a period of 1 us
57  */
58 void udelay(unsigned long usec)
59 {
60         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
61         uint start, now, tmp;
62
63         while (usec > 0) {
64                 if (usec > 65000)
65                         tmp = 65000;
66                 else
67                         tmp = usec;
68                 usec = usec - tmp;
69
70                 /* Set up TIMER 3 as timebase clock */
71                 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
72                 timerp->timer_tcn = 0;
73                 /* set period to 1 us */
74                 timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
75                                      MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
76
77                 start = now = timerp->timer_tcn;
78                 while (now < start + tmp)
79                         now = timerp->timer_tcn;
80         }
81 }
82
83 void mcf_timer_interrupt (void * not_used){
84         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
85         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
86
87         /* check for timer 4 interrupts */
88         if ((intp->int_isr & 0x01000000) != 0) {
89                 return;
90         }
91
92         /* reset timer */
93         timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
94         timestamp ++;
95 }
96
97 void timer_init (void) {
98         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
99         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
100
101         timestamp = 0;
102
103         /* Set up TIMER 4 as clock */
104         timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
105
106         /* initialize and enable timer 4 interrupt */
107         irq_install_handler (72, mcf_timer_interrupt, 0);
108         intp->int_icr1 |= 0x0000000d;
109
110         timerp->timer_tcn = 0;
111         timerp->timer_trr = 1000;       /* Interrupt every ms */
112         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
113         timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
114                 MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
115 }
116
117 void reset_timer (void)
118 {
119         timestamp = 0;
120 }
121
122 ulong get_timer (ulong base)
123 {
124         return (timestamp - base);
125 }
126
127 void set_timer (ulong t)
128 {
129         timestamp = t;
130 }
131 #endif
132
133 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
134
135 void udelay(unsigned long usec)
136 {
137         volatile unsigned short *timerp;
138         uint tmp;
139
140         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE3);
141
142         while (usec > 0) {
143                 if (usec > 65000)
144                         tmp = 65000;
145                 else
146                         tmp = usec;
147                 usec = usec - tmp;
148
149                 /* Set up TIMER 3 as timebase clock */
150                 timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
151                 timerp[MCFTIMER_PMR] = 0;
152                 /* set period to 1 us */
153                 timerp[MCFTIMER_PCSR] =
154 #ifdef CONFIG_M5271
155                         (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
156 #else /* !CONFIG_M5271 */
157                         (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
158 #endif /* CONFIG_M5271 */
159
160                 timerp[MCFTIMER_PMR] = tmp;
161                 while (timerp[MCFTIMER_PCNTR] > 0);
162         }
163 }
164
165 void timer_init (void)
166 {
167         volatile unsigned short *timerp;
168
169         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
170         timestamp = 0;
171
172         /* Set up TIMER 4 as poll clock */
173         timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
174         timerp[MCFTIMER_PMR] = lastinc = 0;
175         timerp[MCFTIMER_PCSR] =
176 #ifdef CONFIG_M5271
177                 (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
178 #else /* !CONFIG_M5271 */
179                 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
180 #endif /* CONFIG_M5271 */
181 }
182
183 void set_timer (ulong t)
184 {
185         volatile unsigned short *timerp;
186
187         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
188         timestamp = 0;
189         timerp[MCFTIMER_PMR] = lastinc = 0;
190 }
191
192 ulong get_timer (ulong base)
193 {
194         unsigned short now, diff;
195         volatile unsigned short *timerp;
196
197         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
198         now = timerp[MCFTIMER_PCNTR];
199         diff = -(now - lastinc);
200
201         timestamp += diff;
202         lastinc = now;
203         return timestamp - base;
204 }
205
206 void wait_ticks (unsigned long ticks)
207 {
208         set_timer (0);
209         while (get_timer (0) < ticks);
210 }
211 #endif
212
213
214 #if defined(CONFIG_M5249)
215 /*
216  * We use timer 1 which is running with a period of 1 us
217  */
218 void udelay(unsigned long usec)
219 {
220         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE1);
221         uint start, now, tmp;
222
223         while (usec > 0) {
224                 if (usec > 65000)
225                         tmp = 65000;
226                 else
227                         tmp = usec;
228                 usec = usec - tmp;
229
230                 /* Set up TIMER 1 as timebase clock */
231                 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
232                 timerp->timer_tcn = 0;
233                 /* set period to 1 us */
234                 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
235                 timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
236                                      MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
237
238                 start = now = timerp->timer_tcn;
239                 while (now < start + tmp)
240                         now = timerp->timer_tcn;
241         }
242 }
243
244 void mcf_timer_interrupt (void * not_used){
245         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
246
247         /* check for timer 2 interrupts */
248         if ((mbar_readLong(MCFSIM_IPR) & 0x00000400) == 0) {
249                 return;
250         }
251
252         /* reset timer */
253         timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
254         timestamp ++;
255 }
256
257 void timer_init (void) {
258         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
259
260         timestamp = 0;
261
262         /* Set up TIMER 2 as clock */
263         timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
264
265         /* initialize and enable timer 2 interrupt */
266         irq_install_handler (31, mcf_timer_interrupt, 0);
267         mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
268         mbar_writeByte(MCFSIM_TIMER2ICR, MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3);
269
270         timerp->timer_tcn = 0;
271         timerp->timer_trr = 1000;       /* Interrupt every ms */
272         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
273         /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
274         timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
275                 MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
276 }
277
278 void reset_timer (void)
279 {
280         timestamp = 0;
281 }
282
283 ulong get_timer (ulong base)
284 {
285         return (timestamp - base);
286 }
287
288 void set_timer (ulong t)
289 {
290         timestamp = t;
291 }
292 #endif
293
294 #if defined(CONFIG_MCFTMR)
295 #ifndef CFG_UDELAY_BASE
296 #       error   "uDelay base not defined!"
297 #endif
298
299 #if !defined(CFG_TMR_BASE) || !defined(CFG_INTR_BASE) || !defined(CFG_TMRINTR_NO) || !defined(CFG_TMRINTR_MASK)
300 #       error   "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
301 #endif
302
303 #include <asm/immap_5329.h>
304
305 extern void dtimer_interrupt(void *not_used);
306 extern void dtimer_interrupt_setup(void);
307 extern void dtimer_interrupt_enable(void);
308
309 void udelay(unsigned long usec)
310 {
311         volatile dtmr_t *timerp = (dtmr_t *) (CFG_UDELAY_BASE);
312         uint start, now, tmp;
313
314         while (usec > 0) {
315                 if (usec > 65000)
316                         tmp = 65000;
317                 else
318                         tmp = usec;
319                 usec = usec - tmp;
320
321                 /* Set up TIMER 3 as timebase clock */
322                 timerp->tmr = DTIM_DTMR_RST_RST;
323                 timerp->tcn = 0;
324                 /* set period to 1 us */
325                 timerp->tmr =
326                     (((CFG_CLK / 1000000) -
327                       1) << 8) | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR | DTIM_DTMR_RST_EN;
328
329                 start = now = timerp->tcn;
330                 while (now < start + tmp)
331                         now = timerp->tcn;
332         }
333 }
334
335 void dtimer_interrupt(void *not_used)
336 {
337         volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
338         volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
339
340         /* check for timer interrupt asserted */
341         if ((intp->iprh0 & CFG_TMRINTR_MASK) == CFG_TMRINTR_MASK) {
342                 timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
343                 timestamp++;
344                 return;
345         }
346 }
347
348 void timer_init(void)
349 {
350         volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
351         volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
352
353         timestamp = 0;
354
355         timerp->tcn = 0;
356         timerp->trr = 0;
357
358         /* Set up TIMER 4 as clock */
359         timerp->tmr = DTIM_DTMR_RST_RST;
360
361         /* initialize and enable timer 4 interrupt */
362         irq_install_handler(CFG_TMRINTR_NO, dtimer_interrupt, 0);
363         intp->icr0[CFG_TMRINTR_NO] = CFG_TMRINTR_PRI;
364
365         timerp->tcn = 0;
366         timerp->trr = 1000;     /* Interrupt every ms */
367
368         intp->imrh0 &= ~CFG_TMRINTR_MASK;
369
370         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
371         timerp->tmr = CFG_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
372             DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
373 }
374
375 void reset_timer(void)
376 {
377         timestamp = 0;
378 }
379
380 ulong get_timer(ulong base)
381 {
382         return (timestamp - base);
383 }
384
385 void set_timer(ulong t)
386 {
387         timestamp = t;
388 }
389 #endif                          /* CONFIG_MCFTMR */
390
391 #if defined(CONFIG_MCFPIT)
392 #if !defined(CFG_PIT_BASE)
393 #       error   "CFG_PIT_BASE not defined!"
394 #endif
395
396 static unsigned short lastinc;
397
398 void udelay(unsigned long usec)
399 {
400         volatile pit_t *timerp = (pit_t *) (CFG_UDELAY_BASE);
401         uint tmp;
402
403         while (usec > 0) {
404                 if (usec > 65000)
405                         tmp = 65000;
406                 else
407                         tmp = usec;
408                 usec = usec - tmp;
409
410                 /* Set up TIMER 3 as timebase clock */
411                 timerp->pcsr = PIT_PCSR_OVW;
412                 timerp->pmr = 0;
413                 /* set period to 1 us */
414                 timerp->pcsr |= PIT_PCSR_PRE(CFG_PIT_PRESCALE) | PIT_PCSR_EN;
415
416                 timerp->pmr = tmp;
417                 while (timerp->pcntr > 0) ;
418         }
419 }
420
421 void timer_init(void)
422 {
423         volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
424         timestamp = 0;
425
426         /* Set up TIMER 4 as poll clock */
427         timerp->pcsr = PIT_PCSR_OVW;
428         timerp->pmr = lastinc = 0;
429         timerp->pcsr |= PIT_PCSR_PRE(CFG_PIT_PRESCALE) | PIT_PCSR_EN;
430 }
431
432 void set_timer(ulong t)
433 {
434         volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
435
436         timestamp = 0;
437         timerp->pmr = lastinc = 0;
438 }
439
440 ulong get_timer(ulong base)
441 {
442         unsigned short now, diff;
443         volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
444
445         now = timerp->pcntr;
446         diff = -(now - lastinc);
447
448         timestamp += diff;
449         lastinc = now;
450         return timestamp - base;
451 }
452
453 void wait_ticks(unsigned long ticks)
454 {
455         set_timer(0);
456         while (get_timer(0) < ticks) ;
457 }
458 #endif                          /* CONFIG_MCFPIT */
459
460 /*
461  * This function is derived from PowerPC code (read timebase as long long).
462  * On M68K it just returns the timer value.
463  */
464 unsigned long long get_ticks(void)
465 {
466         return get_timer(0);
467 }
468
469 /*
470  * This function is derived from PowerPC code (timebase clock frequency).
471  * On M68K it returns the number of timer ticks per second.
472  */
473 ulong get_tbclk (void)
474 {
475         ulong tbclk;
476         tbclk = CFG_HZ;
477         return tbclk;
478 }