* Patch by Josef Baumgartner, 25 May 2004:
[platform/kernel/u-boot.git] / 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_M5272
31 #include <asm/m5272.h>
32 #include <asm/immap_5272.h>
33 #endif
34
35 #ifdef  CONFIG_M5282
36 #include <asm/m5282.h>
37 #endif
38
39
40 static ulong timestamp;
41 #ifdef  CONFIG_M5282
42 static unsigned short lastinc;
43 #endif
44
45
46 #if defined(CONFIG_M5272)
47 /*
48  * We use timer 3 which is running with a period of 1 us
49  */
50 void udelay(unsigned long usec)
51 {
52         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
53         uint start, now, tmp;
54
55         while (usec > 0) {
56                 if (usec > 65000)
57                         tmp = 65000;
58                 else
59                         tmp = usec;
60                 usec = usec - tmp;
61
62                 /* Set up TIMER 3 as timebase clock */
63                 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
64                 timerp->timer_tcn = 0;
65                 /* set period to 1 us */
66                 timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
67                                      MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
68
69                 start = now = timerp->timer_tcn;
70                 while (now < start + tmp)
71                         now = timerp->timer_tcn;
72         }
73 }
74
75 void mcf_timer_interrupt (void * not_used){
76         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
77         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
78
79         /* check for timer 4 interrupts */
80         if ((intp->int_isr & 0x01000000) != 0) {
81                 return;
82         }
83
84         /* reset timer */
85         timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
86         timestamp ++;
87 }
88
89 void timer_init (void) {
90         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
91         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
92
93         timestamp = 0;
94
95         /* Set up TIMER 4 as clock */
96         timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
97
98         /* initialize and enable timer 4 interrupt */
99         irq_install_handler (72, mcf_timer_interrupt, 0);
100         intp->int_icr1 |= 0x0000000d;
101
102         timerp->timer_tcn = 0;
103         timerp->timer_trr = 1000;       /* Interrupt every ms */
104         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
105         timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
106                 MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
107 }
108
109 void reset_timer (void)
110 {
111         timestamp = 0;
112 }
113
114 ulong get_timer (ulong base)
115 {
116         return (timestamp - base);
117 }
118
119 void set_timer (ulong t)
120 {
121         timestamp = t;
122 }
123 #endif
124
125 #if defined(CONFIG_M5282)
126
127 void udelay(unsigned long usec)
128 {
129 }
130
131 void timer_init (void)
132 {
133         volatile unsigned short *timerp;
134
135         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
136         timestamp = 0;
137
138         /* Set up TIMER 4 as poll clock */
139         timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
140         timerp[MCFTIMER_PMR] = lastinc = 0;
141         timerp[MCFTIMER_PCSR] =
142                 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
143 }
144
145 void set_timer (ulong t)
146 {
147         volatile unsigned short *timerp;
148
149         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
150         timestamp = 0;
151         timerp[MCFTIMER_PMR] = lastinc = 0;
152 }
153
154 ulong get_timer (ulong base)
155 {
156         unsigned short now, diff;
157         volatile unsigned short *timerp;
158
159         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
160         now = timerp[MCFTIMER_PCNTR];
161         diff = -(now - lastinc);
162
163         timestamp += diff;
164         lastinc = now;
165         return timestamp - base;
166 }
167
168 void wait_ticks (unsigned long ticks)
169 {
170         set_timer (0);
171         while (get_timer (0) < ticks);
172 }
173 #endif
174
175
176 /*
177  * This function is derived from PowerPC code (read timebase as long long).
178  * On M68K it just returns the timer value.
179  */
180 unsigned long long get_ticks(void)
181 {
182         return get_timer(0);
183 }
184
185 /*
186  * This function is derived from PowerPC code (timebase clock frequency).
187  * On M68K it returns the number of timer ticks per second.
188  */
189 ulong get_tbclk (void)
190 {
191         ulong tbclk;
192         tbclk = CFG_HZ;
193         return tbclk;
194 }