]>
git.ipfire.org Git - people/ms/u-boot.git/blob - lib_m68k/time.c
2 * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * See file CREDITS for list of people who contributed to this
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.
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.
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,
28 #include <asm/mcftimer.h>
29 #include <asm/timer.h>
30 #include <asm/immap.h>
33 #include <asm/m5271.h>
34 #include <asm/immap_5271.h>
38 #include <asm/m5272.h>
39 #include <asm/immap_5272.h>
43 #include <asm/m5282.h>
47 #include <asm/m5249.h>
48 #include <asm/immap_5249.h>
51 DECLARE_GLOBAL_DATA_PTR
;
53 static ulong timestamp
;
54 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
55 static unsigned short lastinc
;
58 #if defined(CONFIG_M5272)
60 * We use timer 3 which is running with a period of 1 us
62 void udelay(unsigned long usec
)
64 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE3
);
74 /* Set up TIMER 3 as timebase clock */
75 timerp
->timer_tmr
= MCFTIMER_TMR_DISABLE
;
76 timerp
->timer_tcn
= 0;
77 /* set period to 1 us */
79 (((CFG_CLK
/ 1000000) -
80 1) << 8) | MCFTIMER_TMR_CLK1
| MCFTIMER_TMR_FREERUN
|
83 start
= now
= timerp
->timer_tcn
;
84 while (now
< start
+ tmp
)
85 now
= timerp
->timer_tcn
;
89 void mcf_timer_interrupt(void *not_used
)
91 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE4
);
92 volatile intctrl_t
*intp
= (intctrl_t
*) (CFG_MBAR
+ MCFSIM_ICR1
);
94 /* check for timer 4 interrupts */
95 if ((intp
->int_isr
& 0x01000000) != 0) {
100 timerp
->timer_ter
= MCFTIMER_TER_CAP
| MCFTIMER_TER_REF
;
104 void timer_init(void)
106 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE4
);
107 volatile intctrl_t
*intp
= (intctrl_t
*) (CFG_MBAR
+ MCFSIM_ICR1
);
111 /* Set up TIMER 4 as clock */
112 timerp
->timer_tmr
= MCFTIMER_TMR_DISABLE
;
114 /* initialize and enable timer 4 interrupt */
115 irq_install_handler(72, mcf_timer_interrupt
, 0);
116 intp
->int_icr1
|= 0x0000000d;
118 timerp
->timer_tcn
= 0;
119 timerp
->timer_trr
= 1000; /* Interrupt every ms */
120 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
122 (((CFG_CLK
/ 1000000) -
123 1) << 8) | MCFTIMER_TMR_CLK1
| MCFTIMER_TMR_RESTART
|
124 MCFTIMER_TMR_ENORI
| MCFTIMER_TMR_ENABLE
;
127 void reset_timer(void)
132 ulong
get_timer(ulong base
)
134 return (timestamp
- base
);
137 void set_timer(ulong t
)
143 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
145 void udelay(unsigned long usec
)
147 volatile unsigned short *timerp
;
150 timerp
= (volatile unsigned short *)(CFG_MBAR
+ MCFTIMER_BASE3
);
159 /* Set up TIMER 3 as timebase clock */
160 timerp
[MCFTIMER_PCSR
] = MCFTIMER_PCSR_OVW
;
161 timerp
[MCFTIMER_PMR
] = 0;
162 /* set period to 1 us */
163 timerp
[MCFTIMER_PCSR
] =
165 (6 << 8) | MCFTIMER_PCSR_EN
| MCFTIMER_PCSR_OVW
;
166 #else /* !CONFIG_M5271 */
167 (5 << 8) | MCFTIMER_PCSR_EN
| MCFTIMER_PCSR_OVW
;
168 #endif /* CONFIG_M5271 */
170 timerp
[MCFTIMER_PMR
] = tmp
;
171 while (timerp
[MCFTIMER_PCNTR
] > 0) ;
175 void timer_init(void)
177 volatile unsigned short *timerp
;
179 timerp
= (volatile unsigned short *)(CFG_MBAR
+ MCFTIMER_BASE4
);
182 /* Set up TIMER 4 as poll clock */
183 timerp
[MCFTIMER_PCSR
] = MCFTIMER_PCSR_OVW
;
184 timerp
[MCFTIMER_PMR
] = lastinc
= 0;
185 timerp
[MCFTIMER_PCSR
] =
187 (6 << 8) | MCFTIMER_PCSR_EN
| MCFTIMER_PCSR_OVW
;
188 #else /* !CONFIG_M5271 */
189 (5 << 8) | MCFTIMER_PCSR_EN
| MCFTIMER_PCSR_OVW
;
190 #endif /* CONFIG_M5271 */
193 void set_timer(ulong t
)
195 volatile unsigned short *timerp
;
197 timerp
= (volatile unsigned short *)(CFG_MBAR
+ MCFTIMER_BASE4
);
199 timerp
[MCFTIMER_PMR
] = lastinc
= 0;
202 ulong
get_timer(ulong base
)
204 unsigned short now
, diff
;
205 volatile unsigned short *timerp
;
207 timerp
= (volatile unsigned short *)(CFG_MBAR
+ MCFTIMER_BASE4
);
208 now
= timerp
[MCFTIMER_PCNTR
];
209 diff
= -(now
- lastinc
);
213 return timestamp
- base
;
216 void wait_ticks(unsigned long ticks
)
219 while (get_timer(0) < ticks
) ;
223 #if defined(CONFIG_M5249)
225 * We use timer 1 which is running with a period of 1 us
227 void udelay(unsigned long usec
)
229 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE1
);
230 uint start
, now
, tmp
;
239 /* Set up TIMER 1 as timebase clock */
240 timerp
->timer_tmr
= MCFTIMER_TMR_DISABLE
;
241 timerp
->timer_tcn
= 0;
242 /* set period to 1 us */
243 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
245 (((CFG_CLK
/ 2000000) -
246 1) << 8) | MCFTIMER_TMR_CLK1
| MCFTIMER_TMR_FREERUN
|
249 start
= now
= timerp
->timer_tcn
;
250 while (now
< start
+ tmp
)
251 now
= timerp
->timer_tcn
;
255 void mcf_timer_interrupt(void *not_used
)
257 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE2
);
259 /* check for timer 2 interrupts */
260 if ((mbar_readLong(MCFSIM_IPR
) & 0x00000400) == 0) {
265 timerp
->timer_ter
= MCFTIMER_TER_CAP
| MCFTIMER_TER_REF
;
269 void timer_init(void)
271 volatile timer_t
*timerp
= (timer_t
*) (CFG_MBAR
+ MCFTIMER_BASE2
);
275 /* Set up TIMER 2 as clock */
276 timerp
->timer_tmr
= MCFTIMER_TMR_DISABLE
;
278 /* initialize and enable timer 2 interrupt */
279 irq_install_handler(31, mcf_timer_interrupt
, 0);
280 mbar_writeLong(MCFSIM_IMR
, mbar_readLong(MCFSIM_IMR
) & ~0x00000400);
281 mbar_writeByte(MCFSIM_TIMER2ICR
,
282 MCFSIM_ICR_AUTOVEC
| MCFSIM_ICR_LEVEL7
|
285 timerp
->timer_tcn
= 0;
286 timerp
->timer_trr
= 1000; /* Interrupt every ms */
287 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
288 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
290 (((CFG_CLK
/ 2000000) -
291 1) << 8) | MCFTIMER_TMR_CLK1
| MCFTIMER_TMR_RESTART
|
292 MCFTIMER_TMR_ENORI
| MCFTIMER_TMR_ENABLE
;
295 void reset_timer(void)
300 ulong
get_timer(ulong base
)
302 return (timestamp
- base
);
305 void set_timer(ulong t
)
311 #if defined(CONFIG_MCFTMR)
312 #ifndef CFG_UDELAY_BASE
313 # error "uDelay base not defined!"
316 #if !defined(CFG_TMR_BASE) || !defined(CFG_INTR_BASE) || !defined(CFG_TMRINTR_NO) || !defined(CFG_TMRINTR_MASK)
317 # error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
319 extern void dtimer_intr_setup(void);
321 void udelay(unsigned long usec
)
323 volatile dtmr_t
*timerp
= (dtmr_t
*) (CFG_UDELAY_BASE
);
324 uint start
, now
, tmp
;
333 /* Set up TIMER 3 as timebase clock */
334 timerp
->tmr
= DTIM_DTMR_RST_RST
;
336 /* set period to 1 us */
338 CFG_TIMER_PRESCALER
| DTIM_DTMR_CLK_DIV1
| DTIM_DTMR_FRR
|
341 start
= now
= timerp
->tcn
;
342 while (now
< start
+ tmp
)
347 void dtimer_interrupt(void *not_used
)
349 volatile dtmr_t
*timerp
= (dtmr_t
*) (CFG_TMR_BASE
);
350 volatile int0_t
*intp
= (int0_t
*) (CFG_INTR_BASE
);
352 /* check for timer interrupt asserted */
353 if ((intp
->iprh0
& CFG_TMRINTR_MASK
) == CFG_TMRINTR_MASK
) {
354 timerp
->ter
= (DTIM_DTER_CAP
| DTIM_DTER_REF
);
360 void timer_init(void)
362 volatile dtmr_t
*timerp
= (dtmr_t
*) (CFG_TMR_BASE
);
369 /* Set up TIMER 4 as clock */
370 timerp
->tmr
= DTIM_DTMR_RST_RST
;
372 /* initialize and enable timer interrupt */
373 irq_install_handler(CFG_TMRINTR_NO
, dtimer_interrupt
, 0);
376 timerp
->trr
= 1000; /* Interrupt every ms */
380 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
381 timerp
->tmr
= CFG_TIMER_PRESCALER
| DTIM_DTMR_CLK_DIV1
|
382 DTIM_DTMR_FRR
| DTIM_DTMR_ORRI
| DTIM_DTMR_RST_EN
;
385 void reset_timer(void)
390 ulong
get_timer(ulong base
)
392 return (timestamp
- base
);
395 void set_timer(ulong t
)
399 #endif /* CONFIG_MCFTMR */
401 #if defined(CONFIG_MCFPIT)
402 #if !defined(CFG_PIT_BASE)
403 # error "CFG_PIT_BASE not defined!"
406 static unsigned short lastinc
;
408 void udelay(unsigned long usec
)
410 volatile pit_t
*timerp
= (pit_t
*) (CFG_UDELAY_BASE
);
420 /* Set up TIMER 3 as timebase clock */
421 timerp
->pcsr
= PIT_PCSR_OVW
;
423 /* set period to 1 us */
424 timerp
->pcsr
|= PIT_PCSR_PRE(CFG_PIT_PRESCALE
) | PIT_PCSR_EN
;
427 while (timerp
->pcntr
> 0) ;
431 void timer_init(void)
433 volatile pit_t
*timerp
= (pit_t
*) (CFG_PIT_BASE
);
436 /* Set up TIMER 4 as poll clock */
437 timerp
->pcsr
= PIT_PCSR_OVW
;
438 timerp
->pmr
= lastinc
= 0;
439 timerp
->pcsr
|= PIT_PCSR_PRE(CFG_PIT_PRESCALE
) | PIT_PCSR_EN
;
442 void set_timer(ulong t
)
444 volatile pit_t
*timerp
= (pit_t
*) (CFG_PIT_BASE
);
447 timerp
->pmr
= lastinc
= 0;
450 ulong
get_timer(ulong base
)
452 unsigned short now
, diff
;
453 volatile pit_t
*timerp
= (pit_t
*) (CFG_PIT_BASE
);
456 diff
= -(now
- lastinc
);
460 return timestamp
- base
;
463 void wait_ticks(unsigned long ticks
)
466 while (get_timer(0) < ticks
) ;
468 #endif /* CONFIG_MCFPIT */
471 * This function is derived from PowerPC code (read timebase as long long).
472 * On M68K it just returns the timer value.
474 unsigned long long get_ticks(void)
480 * This function is derived from PowerPC code (timebase clock frequency).
481 * On M68K it returns the number of timer ticks per second.
483 ulong
get_tbclk(void)