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>
31 #include <asm/m5271.h>
32 #include <asm/immap_5271.h>
36 #include <asm/m5272.h>
37 #include <asm/immap_5272.h>
41 #include <asm/m5282.h>
45 #include <asm/m5249.h>
46 #include <asm/immap_5249.h>
49 static ulong timestamp;
50 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
51 static unsigned short lastinc;
54 #if defined(CONFIG_M5272)
56 * We use timer 3 which is running with a period of 1 us
58 void udelay(unsigned long usec)
60 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
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;
77 start = now = timerp->timer_tcn;
78 while (now < start + tmp)
79 now = timerp->timer_tcn;
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);
87 /* check for timer 4 interrupts */
88 if ((intp->int_isr & 0x01000000) != 0) {
93 timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
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);
103 /* Set up TIMER 4 as clock */
104 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
106 /* initialize and enable timer 4 interrupt */
107 irq_install_handler (72, mcf_timer_interrupt, 0);
108 intp->int_icr1 |= 0x0000000d;
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;
117 void reset_timer (void)
122 ulong get_timer (ulong base)
124 return (timestamp - base);
127 void set_timer (ulong t)
133 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
135 void udelay(unsigned long usec)
137 volatile unsigned short *timerp;
140 timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE3);
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] =
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 */
160 timerp[MCFTIMER_PMR] = tmp;
161 while (timerp[MCFTIMER_PCNTR] > 0);
165 void timer_init (void)
167 volatile unsigned short *timerp;
169 timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
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] =
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 */
183 void set_timer (ulong t)
185 volatile unsigned short *timerp;
187 timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
189 timerp[MCFTIMER_PMR] = lastinc = 0;
192 ulong get_timer (ulong base)
194 unsigned short now, diff;
195 volatile unsigned short *timerp;
197 timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
198 now = timerp[MCFTIMER_PCNTR];
199 diff = -(now - lastinc);
203 return timestamp - base;
206 void wait_ticks (unsigned long ticks)
209 while (get_timer (0) < ticks);
214 #if defined(CONFIG_M5249)
216 * We use timer 1 which is running with a period of 1 us
218 void udelay(unsigned long usec)
220 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE1);
221 uint start, now, tmp;
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;
238 start = now = timerp->timer_tcn;
239 while (now < start + tmp)
240 now = timerp->timer_tcn;
244 void mcf_timer_interrupt (void * not_used){
245 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
247 /* check for timer 2 interrupts */
248 if ((mbar_readLong(MCFSIM_IPR) & 0x00000400) == 0) {
253 timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
257 void timer_init (void) {
258 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
262 /* Set up TIMER 2 as clock */
263 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
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);
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;
278 void reset_timer (void)
283 ulong get_timer (ulong base)
285 return (timestamp - base);
288 void set_timer (ulong t)
294 #if defined(CONFIG_MCFTMR)
295 #ifndef CFG_UDELAY_BASE
296 # error "uDelay base not defined!"
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!"
303 #include <asm/immap_5329.h>
305 extern void dtimer_interrupt(void *not_used);
306 extern void dtimer_interrupt_setup(void);
307 extern void dtimer_interrupt_enable(void);
309 void udelay(unsigned long usec)
311 volatile dtmr_t *timerp = (dtmr_t *) (CFG_UDELAY_BASE);
312 uint start, now, tmp;
321 /* Set up TIMER 3 as timebase clock */
322 timerp->tmr = DTIM_DTMR_RST_RST;
324 /* set period to 1 us */
326 (((CFG_CLK / 1000000) -
327 1) << 8) | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR | DTIM_DTMR_RST_EN;
329 start = now = timerp->tcn;
330 while (now < start + tmp)
335 void dtimer_interrupt(void *not_used)
337 volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
338 volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
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);
348 void timer_init(void)
350 volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
351 volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
358 /* Set up TIMER 4 as clock */
359 timerp->tmr = DTIM_DTMR_RST_RST;
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;
366 timerp->trr = 1000; /* Interrupt every ms */
368 intp->imrh0 &= ~CFG_TMRINTR_MASK;
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;
375 void reset_timer(void)
380 ulong get_timer(ulong base)
382 return (timestamp - base);
385 void set_timer(ulong t)
389 #endif /* CONFIG_MCFTMR */
391 #if defined(CONFIG_MCFPIT)
392 #if !defined(CFG_PIT_BASE)
393 # error "CFG_PIT_BASE not defined!"
396 static unsigned short lastinc;
398 void udelay(unsigned long usec)
400 volatile pit_t *timerp = (pit_t *) (CFG_UDELAY_BASE);
410 /* Set up TIMER 3 as timebase clock */
411 timerp->pcsr = PIT_PCSR_OVW;
413 /* set period to 1 us */
414 timerp->pcsr |= PIT_PCSR_PRE(CFG_PIT_PRESCALE) | PIT_PCSR_EN;
417 while (timerp->pcntr > 0) ;
421 void timer_init(void)
423 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
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;
432 void set_timer(ulong t)
434 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
437 timerp->pmr = lastinc = 0;
440 ulong get_timer(ulong base)
442 unsigned short now, diff;
443 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
446 diff = -(now - lastinc);
450 return timestamp - base;
453 void wait_ticks(unsigned long ticks)
456 while (get_timer(0) < ticks) ;
458 #endif /* CONFIG_MCFPIT */
461 * This function is derived from PowerPC code (read timebase as long long).
462 * On M68K it just returns the timer value.
464 unsigned long long get_ticks(void)
470 * This function is derived from PowerPC code (timebase clock frequency).
471 * On M68K it returns the number of timer ticks per second.
473 ulong get_tbclk (void)