]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - lib_m68k/time.c
VOH405 board update
[karo-tx-uboot.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 #ifdef  CONFIG_M5249
40 #include <asm/m5249.h>
41 #include <asm/immap_5249.h>
42 #endif
43
44
45 static ulong timestamp;
46 #ifdef  CONFIG_M5282
47 static unsigned short lastinc;
48 #endif
49
50
51 #if defined(CONFIG_M5272)
52 /*
53  * We use timer 3 which is running with a period of 1 us
54  */
55 void udelay(unsigned long usec)
56 {
57         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE3);
58         uint start, now, tmp;
59
60         while (usec > 0) {
61                 if (usec > 65000)
62                         tmp = 65000;
63                 else
64                         tmp = usec;
65                 usec = usec - tmp;
66
67                 /* Set up TIMER 3 as timebase clock */
68                 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
69                 timerp->timer_tcn = 0;
70                 /* set period to 1 us */
71                 timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
72                                      MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
73
74                 start = now = timerp->timer_tcn;
75                 while (now < start + tmp)
76                         now = timerp->timer_tcn;
77         }
78 }
79
80 void mcf_timer_interrupt (void * not_used){
81         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
82         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
83
84         /* check for timer 4 interrupts */
85         if ((intp->int_isr & 0x01000000) != 0) {
86                 return;
87         }
88
89         /* reset timer */
90         timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
91         timestamp ++;
92 }
93
94 void timer_init (void) {
95         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE4);
96         volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
97
98         timestamp = 0;
99
100         /* Set up TIMER 4 as clock */
101         timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
102
103         /* initialize and enable timer 4 interrupt */
104         irq_install_handler (72, mcf_timer_interrupt, 0);
105         intp->int_icr1 |= 0x0000000d;
106
107         timerp->timer_tcn = 0;
108         timerp->timer_trr = 1000;       /* Interrupt every ms */
109         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
110         timerp->timer_tmr = (((CFG_CLK / 1000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
111                 MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
112 }
113
114 void reset_timer (void)
115 {
116         timestamp = 0;
117 }
118
119 ulong get_timer (ulong base)
120 {
121         return (timestamp - base);
122 }
123
124 void set_timer (ulong t)
125 {
126         timestamp = t;
127 }
128 #endif
129
130 #if defined(CONFIG_M5282)
131
132 void udelay(unsigned long usec)
133 {
134 }
135
136 void timer_init (void)
137 {
138         volatile unsigned short *timerp;
139
140         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
141         timestamp = 0;
142
143         /* Set up TIMER 4 as poll clock */
144         timerp[MCFTIMER_PCSR] = MCFTIMER_PCSR_OVW;
145         timerp[MCFTIMER_PMR] = lastinc = 0;
146         timerp[MCFTIMER_PCSR] =
147                 (5 << 8) | MCFTIMER_PCSR_EN | MCFTIMER_PCSR_OVW;
148 }
149
150 void set_timer (ulong t)
151 {
152         volatile unsigned short *timerp;
153
154         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
155         timestamp = 0;
156         timerp[MCFTIMER_PMR] = lastinc = 0;
157 }
158
159 ulong get_timer (ulong base)
160 {
161         unsigned short now, diff;
162         volatile unsigned short *timerp;
163
164         timerp = (volatile unsigned short *) (CFG_MBAR + MCFTIMER_BASE4);
165         now = timerp[MCFTIMER_PCNTR];
166         diff = -(now - lastinc);
167
168         timestamp += diff;
169         lastinc = now;
170         return timestamp - base;
171 }
172
173 void wait_ticks (unsigned long ticks)
174 {
175         set_timer (0);
176         while (get_timer (0) < ticks);
177 }
178 #endif
179
180
181 #if defined(CONFIG_M5249)
182 /*
183  * We use timer 1 which is running with a period of 1 us
184  */
185 void udelay(unsigned long usec)
186 {
187         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE1);
188         uint start, now, tmp;
189
190         while (usec > 0) {
191                 if (usec > 65000)
192                         tmp = 65000;
193                 else
194                         tmp = usec;
195                 usec = usec - tmp;
196
197                 /* Set up TIMER 1 as timebase clock */
198                 timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
199                 timerp->timer_tcn = 0;
200                 /* set period to 1 us */
201                 /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
202                 timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
203                                      MCFTIMER_TMR_FREERUN | MCFTIMER_TMR_ENABLE;
204
205                 start = now = timerp->timer_tcn;
206                 while (now < start + tmp)
207                         now = timerp->timer_tcn;
208         }
209 }
210
211 void mcf_timer_interrupt (void * not_used){
212         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
213
214         /* check for timer 2 interrupts */
215         if ((mbar_readLong(MCFSIM_IPR) & 0x00000400) == 0) {
216                 return;
217         }
218
219         /* reset timer */
220         timerp->timer_ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
221         timestamp ++;
222 }
223
224 void timer_init (void) {
225         volatile timer_t *timerp = (timer_t *) (CFG_MBAR + MCFTIMER_BASE2);
226
227         timestamp = 0;
228
229         /* Set up TIMER 2 as clock */
230         timerp->timer_tmr = MCFTIMER_TMR_DISABLE;
231
232         /* initialize and enable timer 2 interrupt */
233         irq_install_handler (31, mcf_timer_interrupt, 0);
234         mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
235         mbar_writeByte(MCFSIM_TIMER2ICR, MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3);
236
237         timerp->timer_tcn = 0;
238         timerp->timer_trr = 1000;       /* Interrupt every ms */
239         /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
240         /* on m5249 the system clock is (cpu_clk / 2) -> divide by 2000000 */
241         timerp->timer_tmr = (((CFG_CLK / 2000000) - 1)  << 8) | MCFTIMER_TMR_CLK1 |
242                 MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENORI | MCFTIMER_TMR_ENABLE;
243 }
244
245 void reset_timer (void)
246 {
247         timestamp = 0;
248 }
249
250 ulong get_timer (ulong base)
251 {
252         return (timestamp - base);
253 }
254
255 void set_timer (ulong t)
256 {
257         timestamp = t;
258 }
259 #endif
260
261
262 /*
263  * This function is derived from PowerPC code (read timebase as long long).
264  * On M68K it just returns the timer value.
265  */
266 unsigned long long get_ticks(void)
267 {
268         return get_timer(0);
269 }
270
271 /*
272  * This function is derived from PowerPC code (timebase clock frequency).
273  * On M68K it returns the number of timer ticks per second.
274  */
275 ulong get_tbclk (void)
276 {
277         ulong tbclk;
278         tbclk = CFG_HZ;
279         return tbclk;
280 }