blob: 0e4efa473c792047edf7ce2417ecf7829112b6c1 [file] [log] [blame]
wdenk4e5ca3e2003-12-08 01:34:36 +00001/*
wdenkbf9e3b32004-02-12 00:47:09 +00002 * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
3 *
4 * (C) Copyright 2000
wdenk4e5ca3e2003-12-08 01:34:36 +00005 * 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
wdenkbf9e3b32004-02-12 00:47:09 +000017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenk4e5ca3e2003-12-08 01:34:36 +000018 * 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
wdenkbf9e3b32004-02-12 00:47:09 +000028#include <asm/mcftimer.h>
wdenk4e5ca3e2003-12-08 01:34:36 +000029
Zachary P. Landaueacbd312006-01-26 17:35:56 -050030#ifdef CONFIG_M5271
31#include <asm/m5271.h>
32#include <asm/immap_5271.h>
33#endif
34
wdenkbf9e3b32004-02-12 00:47:09 +000035#ifdef CONFIG_M5272
36#include <asm/m5272.h>
37#include <asm/immap_5272.h>
38#endif
wdenk4e5ca3e2003-12-08 01:34:36 +000039
wdenkbf9e3b32004-02-12 00:47:09 +000040#ifdef CONFIG_M5282
41#include <asm/m5282.h>
42#endif
43
stroesecd42dee2004-12-16 17:56:09 +000044#ifdef CONFIG_M5249
45#include <asm/m5249.h>
46#include <asm/immap_5249.h>
47#endif
48
wdenkbf9e3b32004-02-12 00:47:09 +000049static ulong timestamp;
Zachary P. Landaueacbd312006-01-26 17:35:56 -050050#if defined(CONFIG_M5282) || defined(CONFIG_M5271)
wdenkbf9e3b32004-02-12 00:47:09 +000051static unsigned short lastinc;
52#endif
53
wdenkbf9e3b32004-02-12 00:47:09 +000054#if defined(CONFIG_M5272)
wdenk4e5ca3e2003-12-08 01:34:36 +000055/*
wdenkbf9e3b32004-02-12 00:47:09 +000056 * We use timer 3 which is running with a period of 1 us
wdenk4e5ca3e2003-12-08 01:34:36 +000057 */
58void udelay(unsigned long usec)
59{
wdenkbf9e3b32004-02-12 00:47:09 +000060 volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
61 uint start, now, tmp;
wdenk4e5ca3e2003-12-08 01:34:36 +000062
wdenkbf9e3b32004-02-12 00:47:09 +000063 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 }
wdenk4e5ca3e2003-12-08 01:34:36 +000081}
82
wdenkbf9e3b32004-02-12 00:47:09 +000083void 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);
wdenk4e5ca3e2003-12-08 01:34:36 +000086
wdenkbf9e3b32004-02-12 00:47:09 +000087 /* 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
97void 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
117void reset_timer (void)
wdenk4e5ca3e2003-12-08 01:34:36 +0000118{
wdenkbf9e3b32004-02-12 00:47:09 +0000119 timestamp = 0;
wdenk4e5ca3e2003-12-08 01:34:36 +0000120}
121
wdenkbf9e3b32004-02-12 00:47:09 +0000122ulong get_timer (ulong base)
wdenk4e5ca3e2003-12-08 01:34:36 +0000123{
wdenkbf9e3b32004-02-12 00:47:09 +0000124 return (timestamp - base);
wdenk4e5ca3e2003-12-08 01:34:36 +0000125}
126
wdenkbf9e3b32004-02-12 00:47:09 +0000127void set_timer (ulong t)
128{
129 timestamp = t;
130}
131#endif
132
Zachary P. Landaueacbd312006-01-26 17:35:56 -0500133#if defined(CONFIG_M5282) || defined(CONFIG_M5271)
wdenkbf9e3b32004-02-12 00:47:09 +0000134
135void udelay(unsigned long usec)
136{
wdenk50712ba2005-04-03 23:35:57 +0000137 volatile unsigned short *timerp;
138 uint tmp;
139
140 timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE3);
wdenk3c2b3d42005-04-05 23:32:21 +0000141
wdenk50712ba2005-04-03 23:35:57 +0000142 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] =
Bartlomiej Siekadaa6e412006-12-20 00:27:32 +0100154#ifdef CONFIG_M5271
155 (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
156#else /* !CONFIG_M5271 */
wdenk50712ba2005-04-03 23:35:57 +0000157 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
Bartlomiej Siekadaa6e412006-12-20 00:27:32 +0100158#endif /* CONFIG_M5271 */
wdenk50712ba2005-04-03 23:35:57 +0000159
wdenk3c2b3d42005-04-05 23:32:21 +0000160 timerp[MCFTIMER_PMR] = tmp;
wdenk50712ba2005-04-03 23:35:57 +0000161 while (timerp[MCFTIMER_PCNTR] > 0);
162 }
wdenkbf9e3b32004-02-12 00:47:09 +0000163}
164
165void 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] =
Bartlomiej Siekadaa6e412006-12-20 00:27:32 +0100176#ifdef CONFIG_M5271
177 (6 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
178#else /* !CONFIG_M5271 */
wdenkbf9e3b32004-02-12 00:47:09 +0000179 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
Bartlomiej Siekadaa6e412006-12-20 00:27:32 +0100180#endif /* CONFIG_M5271 */
wdenkbf9e3b32004-02-12 00:47:09 +0000181}
182
183void 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
192ulong 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
206void wait_ticks (unsigned long ticks)
207{
208 set_timer (0);
209 while (get_timer (0) < ticks);
210}
211#endif
wdenk70f05ac2004-06-09 15:24:18 +0000212
213
stroesecd42dee2004-12-16 17:56:09 +0000214#if defined(CONFIG_M5249)
215/*
216 * We use timer 1 which is running with a period of 1 us
217 */
218void 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
244void 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
257void 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
278void reset_timer (void)
279{
280 timestamp = 0;
281}
282
283ulong get_timer (ulong base)
284{
285 return (timestamp - base);
286}
287
288void set_timer (ulong t)
289{
290 timestamp = t;
291}
292#endif
293
TsiChung Liew8e585f02007-06-18 13:50:13 -0500294#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
305extern void dtimer_interrupt(void *not_used);
306extern void dtimer_interrupt_setup(void);
307extern void dtimer_interrupt_enable(void);
308
309void 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
335void 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
348void 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
375void reset_timer(void)
376{
377 timestamp = 0;
378}
379
380ulong get_timer(ulong base)
381{
382 return (timestamp - base);
383}
384
385void 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
396static unsigned short lastinc;
397
398void 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
421void 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
432void 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
440ulong 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
453void wait_ticks(unsigned long ticks)
454{
455 set_timer(0);
456 while (get_timer(0) < ticks) ;
457}
458#endif /* CONFIG_MCFPIT */
stroesecd42dee2004-12-16 17:56:09 +0000459
wdenk70f05ac2004-06-09 15:24:18 +0000460/*
461 * This function is derived from PowerPC code (read timebase as long long).
462 * On M68K it just returns the timer value.
463 */
464unsigned 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 */
473ulong get_tbclk (void)
474{
475 ulong tbclk;
476 tbclk = CFG_HZ;
477 return tbclk;
478}