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 static ulong timestamp;
52 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
53 static unsigned short lastinc;
56 #if defined(CONFIG_M5272)
58 * We use timer 3 which is running with a period of 1 us
60 void udelay(unsigned long usec)
62 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
72 /* Set up TIMER 3 as timebase clock */
73 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
74 timerp->timer_tcn = 0;
75 /* set period to 1 us */
77 (((CFG_CLK / 1000000) -
78 1) << 8) | MCFTIMER_TMR_CLK1 | MCFTIMER_TMR_FREERUN |
81 start = now = timerp->timer_tcn;
82 while (now < start + tmp)
83 now = timerp->timer_tcn;
87 void mcf_timer_interrupt(void *not_used)
89 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
90 volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
92 /* check for timer 4 interrupts */
93 if ((intp->int_isr & 0x01000000) != 0) {
98 timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
102 void timer_init(void)
104 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
105 volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
109 /* Set up TIMER 4 as clock */
110 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
112 /* initialize and enable timer 4 interrupt */
113 irq_install_handler(72, mcf_timer_interrupt, 0);
114 intp->int_icr1 |= 0x0000000d;
116 timerp->timer_tcn = 0;
117 timerp->timer_trr = 1000; /* Interrupt every ms */
118 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
120 (((CFG_CLK / 1000000) -
121 1) << 8) | MCFTIMER_TMR_CLK1 | MCFTIMER_TMR_RESTART |
122 MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
125 void reset_timer(void)
130 ulong get_timer(ulong base)
132 return (timestamp - base);
135 void set_timer(ulong t)
141 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
143 void udelay(unsigned long usec)
145 volatile unsigned short *timerp;
148 timerp = (volatile unsigned short *)(CFG_MBAR + MCFTIMER_BASE3);
157 /* Set up TIMER 3 as timebase clock */
158 timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
159 timerp[MCFTIMER_PMR] = 0;
160 /* set period to 1 us */
161 timerp[MCFTIMER_PCSR] =
163 (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
164 #else /* !CONFIG_M5271 */
165 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
166 #endif /* CONFIG_M5271 */
168 timerp[MCFTIMER_PMR] = tmp;
169 while (timerp[MCFTIMER_PCNTR] > 0) ;
173 void timer_init(void)
175 volatile unsigned short *timerp;
177 timerp = (volatile unsigned short *)(CFG_MBAR + MCFTIMER_BASE4);
180 /* Set up TIMER 4 as poll clock */
181 timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
182 timerp[MCFTIMER_PMR] = lastinc = 0;
183 timerp[MCFTIMER_PCSR] =
185 (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
186 #else /* !CONFIG_M5271 */
187 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
188 #endif /* CONFIG_M5271 */
191 void set_timer(ulong t)
193 volatile unsigned short *timerp;
195 timerp = (volatile unsigned short *)(CFG_MBAR + MCFTIMER_BASE4);
197 timerp[MCFTIMER_PMR] = lastinc = 0;
200 ulong get_timer(ulong base)
202 unsigned short now, diff;
203 volatile unsigned short *timerp;
205 timerp = (volatile unsigned short *)(CFG_MBAR + MCFTIMER_BASE4);
206 now = timerp[MCFTIMER_PCNTR];
207 diff = -(now - lastinc);
211 return timestamp - base;
214 void wait_ticks(unsigned long ticks)
217 while (get_timer(0) < ticks) ;
221 #if defined(CONFIG_M5249)
223 * We use timer 1 which is running with a period of 1 us
225 void udelay(unsigned long usec)
227 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE1);
228 uint start, now, tmp;
237 /* Set up TIMER 1 as timebase clock */
238 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
239 timerp->timer_tcn = 0;
240 /* set period to 1 us */
241 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
243 (((CFG_CLK / 2000000) -
244 1) << 8) | MCFTIMER_TMR_CLK1 | MCFTIMER_TMR_FREERUN |
247 start = now = timerp->timer_tcn;
248 while (now < start + tmp)
249 now = timerp->timer_tcn;
253 void mcf_timer_interrupt(void *not_used)
255 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
257 /* check for timer 2 interrupts */
258 if ((mbar_readLong(MCFSIM_IPR) & 0x00000400) == 0) {
263 timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
267 void timer_init(void)
269 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
273 /* Set up TIMER 2 as clock */
274 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
276 /* initialize and enable timer 2 interrupt */
277 irq_install_handler(31, mcf_timer_interrupt, 0);
278 mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
279 mbar_writeByte(MCFSIM_TIMER2ICR,
280 MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 |
283 timerp->timer_tcn = 0;
284 timerp->timer_trr = 1000; /* Interrupt every ms */
285 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
286 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
288 (((CFG_CLK / 2000000) -
289 1) << 8) | MCFTIMER_TMR_CLK1 | MCFTIMER_TMR_RESTART |
290 MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
293 void reset_timer(void)
298 ulong get_timer(ulong base)
300 return (timestamp - base);
303 void set_timer(ulong t)
309 #if defined(CONFIG_MCFTMR)
310 #ifndef CFG_UDELAY_BASE
311 # error "uDelay base not defined!"
314 #if !defined(CFG_TMR_BASE) || !defined(CFG_INTR_BASE) || !defined(CFG_TMRINTR_NO) || !defined(CFG_TMRINTR_MASK)
315 # error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
317 extern void dtimer_intr_setup(void);
319 void udelay(unsigned long usec)
321 volatile dtmr_t *timerp = (dtmr_t *) (CFG_UDELAY_BASE);
322 uint start, now, tmp;
331 /* Set up TIMER 3 as timebase clock */
332 timerp->tmr = DTIM_DTMR_RST_RST;
334 /* set period to 1 us */
336 CFG_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
339 start = now = timerp->tcn;
340 while (now < start + tmp)
345 void dtimer_interrupt(void *not_used)
347 volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
348 volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
350 /* check for timer interrupt asserted */
351 if ((intp->iprh0 & CFG_TMRINTR_MASK) == CFG_TMRINTR_MASK) {
352 timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
358 void timer_init(void)
360 volatile dtmr_t *timerp = (dtmr_t *) (CFG_TMR_BASE);
367 /* Set up TIMER 4 as clock */
368 timerp->tmr = DTIM_DTMR_RST_RST;
370 /* initialize and enable timer interrupt */
371 irq_install_handler(CFG_TMRINTR_NO, dtimer_interrupt, 0);
374 timerp->trr = 1000; /* Interrupt every ms */
378 /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
379 timerp->tmr = CFG_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
380 DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
383 void reset_timer(void)
388 ulong get_timer(ulong base)
390 return (timestamp - base);
393 void set_timer(ulong t)
397 #endif /* CONFIG_MCFTMR */
399 #if defined(CONFIG_MCFPIT)
400 #if !defined(CFG_PIT_BASE)
401 # error "CFG_PIT_BASE not defined!"
404 static unsigned short lastinc;
406 void udelay(unsigned long usec)
408 volatile pit_t *timerp = (pit_t *) (CFG_UDELAY_BASE);
418 /* Set up TIMER 3 as timebase clock */
419 timerp->pcsr = PIT_PCSR_OVW;
421 /* set period to 1 us */
422 timerp->pcsr |= PIT_PCSR_PRE(CFG_PIT_PRESCALE) | PIT_PCSR_EN;
425 while (timerp->pcntr > 0) ;
429 void timer_init(void)
431 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
434 /* Set up TIMER 4 as poll clock */
435 timerp->pcsr = PIT_PCSR_OVW;
436 timerp->pmr = lastinc = 0;
437 timerp->pcsr |= PIT_PCSR_PRE(CFG_PIT_PRESCALE) | PIT_PCSR_EN;
440 void set_timer(ulong t)
442 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
445 timerp->pmr = lastinc = 0;
448 ulong get_timer(ulong base)
450 unsigned short now, diff;
451 volatile pit_t *timerp = (pit_t *) (CFG_PIT_BASE);
454 diff = -(now - lastinc);
458 return timestamp - base;
461 void wait_ticks(unsigned long ticks)
464 while (get_timer(0) < ticks) ;
466 #endif /* CONFIG_MCFPIT */
469 * This function is derived from PowerPC code (read timebase as long long).
470 * On M68K it just returns the timer value.
472 unsigned long long get_ticks(void)
478 * This function is derived from PowerPC code (timebase clock frequency).
479 * On M68K it returns the number of timer ticks per second.
481 ulong get_tbclk(void)