1 /*
2  *   Copyright (C) 2004 by Green Hills Software,Inc.
3  *
4  *  This program is the property of Green Hills Software, Inc,
5  *  its contents are proprietary information and no part of it
6  *  is to be disclosed to anyone except employees of Green Hills
7  *  Software, Inc., or as agreed in writing signed by the President
8  *  of Green Hills Software, Inc.
9  */
10 /***
11  * ColdFire timer support.
12  * Set SYSTEM_CLOCK to the appropriate value.
13  * Check that the memory mapped register positions are correct
14  * for your board.
15  * If your code makes use of MBAR or ACR0, modify the TIMER_INIT
16  * code appropriately.
17  * Make sure no other interrupts use the same priority and level
18  * as the timer interrupt.
19  *
20  * Recompile libsys with the appropriate cpu selected.
21  */
22 #define MBARx	0x10000000
23 
24 /*
25    M5407C3	50Mhz
26    M5307C3	45Mhz
27    M5272C3	66Mhz
28    M5249C3	70Mhz
29 */
30 #define SYSTEM_CLOCK (50000000) /* 50Mhz timer clock */
31 
32 
33 #if defined(__MCF5407) || defined(__MCF5307)
34 
35 #define TIMER0	(MBARx+0x140)  	/* timer0 base */
36 #define ICR1 	(MBARx+0x04D)  	/* timer0 interrupt control register */
37 #define IMR	(MBARx+0x044)	/* interrupt mask register */
38 
39 #elif defined(__MCF5272)
40 
41 #define TIMER0	(MBARx+0x200)
42 #define ICR1	(MBARx+0x020)	/* external interrupts 1-4 and timers */
43 
44 #elif defined(__MCF5282)
45 
46 /* Default system clock frequency to 64 MHz */
47 #undef SYSTEM_CLOCK
48 #define SYSTEM_CLOCK (64000000)
49 
50 #define IPSBAR   0x40000000
51 #define TIMER0 (IPSBAR + 0x00150000)
52 
53 #elif defined(__MCF5213)
54 
55 /* Default system clock frequency to 48 MHz */
56 #undef SYSTEM_CLOCK
57 #define SYSTEM_CLOCK (48000000)
58 
59 #define IPSBAR   0x40000000
60 #define TIMER0 (IPSBAR + 0x00150000)
61 
62 #else /* older ColdFire V2 cores */
63 
64 #define TIMER0	(MBARx+0x100)	/* timer 0 base */
65 #define ICR1 	(MBARx+0x01C)  	/* timer0 interrupt control register */
66 #define IMR	(MBARx+0x04D)	/* interrupt mask register */
67 
68 #endif
69 
70 #if defined(__MCF5282) || defined(__MCF5213)
71 struct __ghs_coldfire_timer
72 {
73     uint16_t pcsr;  /* PIT Control and Status Register (PCSR) */
74     uint16_t pmr;   /* PIT Modulus Register (PMR) */
75     uint16_t pcntr; /* PIT Count Register (PCNTR) */
76 };
77 #else /* Other ColdFire cores */
78 struct __ghs_coldfire_timer
79 {
80     uint16_t tmr; /* timer mode register */
81     uint16_t pad0;
82     uint16_t trr; /* timer reference register */
83     uint16_t pad1;
84     uint16_t tcr; /* timer capture register */
85     uint16_t pad2;
86     uint16_t tcn; /* timer counter register */
87     uint16_t pad3;
88     uint8_t pad4;
89     uint8_t ter; /* timer event register */
90 };
91 #endif
92 
93 /* TICKS_PER_SEC: on some targets you may be able to read or
94  * compute this value. If so, define a function called
95  * __ghs_manprf_timer_ticks_per_sec that returns the timer
96  * frequency. Otherwise, you'll want to set this value here.
97  */
98 #pragma weak __ghs_manprf_timer_ticks_per_sec
99 unsigned int __ghs_manprf_timer_ticks_per_sec(void);
TICKS_PER_SEC(void)100 unsigned int TICKS_PER_SEC(void) {
101     if(__ghs_manprf_timer_ticks_per_sec) {
102         return __ghs_manprf_timer_ticks_per_sec();
103     } else {
104         /* We scale the timer source by 256 to compensate for 16 bit timers */
105 	return (SYSTEM_CLOCK/256);
106     }
107 }
108 
109 
110 uint32_t __ghs_exception_pc;
111 void __ghs_manprf_timer_coldfire_handler(void);
112 
113 /* Wrapper for __ghs_manprf_timer_handler so we can
114    disable interrupts and store the exception pc/sr
115  */
116 #pragma asm
117 __ghs_manprf_timer_coldfire_handler:
118          MOVE.W #0x2700,%SR   ; disable interrupts
119 	 MOVE.L %D0,-(%A7)    ; save D0
120          ; save exception info to global variables
121 	 MOVE.L 8(%A7),%D0
122 	 MOVE.L %D0,__ghs_exception_pc
123 	 MOVE.L (%A7)+,%D0    ;restore D0 and A7
124 	 JMP __ghs_manprf_timer_handler
125 
126 	 FSIZE	__ghs_manprf_timer_coldfire_handler,4
127 	 SCALL	__ghs_manprf_timer_coldfire_handler,__ghs_manprf_timer_handler
128 	 TYPE	__ghs_manprf_timer_coldfire_handler,@function
129 	 SIZE	__ghs_manprf_timer_coldfire_handler,.-__ghs_manprf_timer_coldfire_handler
130 
131 #pragma endasm
132 
133 #if defined(__MCF5272)
134 
135 /* locate the interrupt handler at the correct exception vector */
136 #pragma asm
137 	 ; position this handler at autovector 5
138 	 ORG 0x114
139 	 DC.L __ghs_manprf_timer_coldfire_handler
140 	 previous
141 #pragma endasm
142 
143 
setup_timer_interrupt()144 static void setup_timer_interrupt()
145 {
146     volatile uint32_t *icr1 = (uint32_t*)ICR1;
147 
148     /* enable timer interrupts with priority 6*/
149     *icr1 |= 0xe000;
150 }
151 
152 #elif defined(__MCF5282)
153 
154 /* Declare a pointer to the start of the vector table section */
155 extern char *__ghsbegin_vector;
156 
157 static void setup_timer_interrupt()
158 {
159     volatile uint32_t *icr55 = (uint32_t*)(IPSBAR + 0xc74);
160 
161     /* Interrupt level (1-7) and priority (0-7) must be unique.
162        For simplicity, just assume we'll use values
163        in the following pattern:
164        ICR8  level 1, priority 0
165        ...
166        ICR15 level 1, priority 7
167        ICR16 level 2, priority 0
168        ...
169        ICR63 level 7, priority 7
170      */
171 
172     /* Write the ICR55 value to set a unique level and priority */
173     *icr55 =
174         0x28 |          /* Level 5 */
175         0x03;           /* Priority 3 */
176 
177     /* Store the interrupt handler function into the vector table */
178     *(volatile uint32_t *)(__ghsbegin_vector + (64+55) * 4) =
179         (uint32_t)__ghs_manprf_timer_coldfire_handler;
180 
181     /* Write Interrupt Mask Register High (IMRL) for INTC0
182        to clear bit 0, to prevent masking all interrupts */
183     *(volatile uint32_t *)(IPSBAR + 0xc08) &= (uint32_t)(~1);
184 
185     /* Write Interrupt Mask Register High (IMRH) for INTC0
186        to clear bit 23, unmasking source 55 (PIT0) interrupts */
187     *(volatile uint32_t *)(IPSBAR + 0xc08) &= (uint32_t)(~(1 << 23));
188     /* unmask the PIT0 interrupt */
189 
190 }
191 
192 #elif defined(__MCF5213)
193 
194 /* Declare a pointer to the start of the vector table section */
195 extern char *__ghsbegin_vector;
196 
197 static void setup_timer_interrupt()
198 {
199     volatile uint32_t *icr55 = (uint32_t*)(IPSBAR + 0xc74);
200 
201     /* Interrupt level (1-7) and priority (0-7) must be unique.
202        For simplicity, just assume we'll use values
203        in the following pattern:
204        ICR8  level 1, priority 0
205        ...
206        ICR15 level 1, priority 7
207        ICR16 level 2, priority 0
208        ...
209        ICR63 level 7, priority 7
210      */
211 
212     /* Write the ICR55 value to set a unique level and priority */
213     *icr55 =
214         0x28 |          /* Level 5 */
215         0x03;           /* Priority 3 */
216 
217     /* Store the interrupt handler function into the vector table */
218     *(volatile uint32_t *)(__ghsbegin_vector + (64+55) * 4) =
219         (uint32_t)__ghs_manprf_timer_coldfire_handler;
220 
221     /* Write Interrupt Mask Register High (IMRL) for INTC0
222        to clear bit 0, to prevent masking all interrupts */
223     *(volatile uint32_t *)(IPSBAR + 0xc08) &= (uint32_t)(~1);
224 
225     /* Write Interrupt Mask Register High (IMRH) for INTC0
226        to clear bit 23, unmasking source 55 (PIT0) interrupts */
227     *(volatile uint32_t *)(IPSBAR + 0xc08) &= (uint32_t)(~(1 << 23));
228     /* unmask the PIT0 interrupt */
229 
230 }
231 
232 #else /* chips that use autovectored timer interrupts */
233 
234 /* locate the interrupt handler at the correct exception vector */
235 #pragma asm
236 	 ; position this handler at autovector 5
237 	 ORG 0x74
238 	 DC.L __ghs_manprf_timer_coldfire_handler
239 	 previous
240 #pragma endasm
241 
242 static void setup_timer_interrupt()
243 {
244     volatile uint8_t *icr1 = (uint8_t*)ICR1; /* interrupt controller for timer0 */
245     volatile uint32_t *imr = (uint32_t*)IMR; /* interrupt mask register */
246 
247     /* give timer0 level 5, priority 3 (autovector at 5) */
248     *icr1 = 0x80 | 0x17;
249     /* unmask the timer0 interrupt */
250     *imr &= ~(0x200);
251 }
252 
253 #endif
254 
255 #if defined(__MCF5282)
256 
257 /* Initialize the timer.  This will overwrite MBAR and ACR0 */
TIMER_INIT(unsigned int count)258 void TIMER_INIT(unsigned int count)
259 {
260     volatile struct __ghs_coldfire_timer *timer =
261 	(struct __ghs_coldfire_timer*)(TIMER0);
262 
263     /* Setup Internal Perepheral System Base Address register (IPSBAR)	 */
264     *(volatile uint32_t *)(0x40000000) = IPSBAR | 1;
265 
266     setup_timer_interrupt();
267 
268     /* Write to PIT0 Control and Status Register (PCSR) to initialize
269        the timer.
270        Set Overwrite (OVW) so the value written to PMR is immediately
271        loaded into the PCNTR. */
272     timer->pcsr = 0x0010;
273 
274     /* Write to PIT0 Modulus Register (PMR) to set the reload value */
275     timer->pmr = count;
276 
277     /* Write to PIT0 Control and Status Register (PCSR) to initialize
278        the timer.
279        */
280     timer->pcsr =
281 	0x0700 |        /* Prescaler (PRE) = 0b0111 to divide system clock by 256 */
282 	0x0020 |        /* Halted (HALTED) stops timer in halted mode */
283 	0x0008 |        /* PIT Interrupt Enable (PIE) to enable PIT interrupts */
284 	0x0002 |        /* Reload (RLD) */
285 	0x0001;         /* PIT Enable (EN) */
286 }
287 
288 /* Clear the timer interrupt and reset the timer
289    Interrupts will be enabled with RTE restores the status register.
290    */
CLEAR_TIMER_INTERRUPT()291 void CLEAR_TIMER_INTERRUPT()
292 {
293     volatile struct __ghs_coldfire_timer *timer =
294 	(struct __ghs_coldfire_timer*)(TIMER0);
295 
296     /* Write to PIT0 Control and Status Register (PCSR) PIT Interrupt
297        Flag (PIF) to clear the PIT interrupt
298        */
299     timer->pcsr =
300 	0x0700 |        /* Prescaler (PRE) = 0b0111 to divide system clock by 256 */
301 	0x0020 |        /* Halted (HALTED) stops timer in halted mode */
302 	0x0008 |        /* PIT Interrupt Enable (PIE) to enable PIT interrupts */
303 	0x0004 |        /* PIT Interrupt Flag (PIF) to clear the PIT interrupt */
304 	0x0002 |        /* Reload (RLD) */
305 	0x0001;         /* PIT Enable (EN) */
306 }
307 
308 #elif defined(__MCF5213)
309 
310 /* Initialize the timer.  This will overwrite MBAR and ACR0 */
TIMER_INIT(unsigned int count)311 void TIMER_INIT(unsigned int count)
312 {
313     volatile struct __ghs_coldfire_timer *timer =
314 	(struct __ghs_coldfire_timer*)(TIMER0);
315 
316     /* Setup Internal Peripheral System Base Address register (IPSBAR)	 */
317     *(volatile uint32_t *)(0x40000000) = IPSBAR | 1;
318 
319     setup_timer_interrupt();
320 
321     /* Write to PIT0 Control and Status Register (PCSR) to initialize
322        the timer.
323        Set Overwrite (OVW) so the value written to PMR is immediately
324        loaded into the PCNTR. */
325     timer->pcsr = 0x0010;
326 
327     /* Write to PIT0 Modulus Register (PMR) to set the reload value */
328     timer->pmr = count;
329 
330     /* Write to PIT0 Control and Status Register (PCSR) to initialize
331        the timer.
332        */
333     timer->pcsr =
334 	0x0700 |        /* Prescaler (PRE) = 0b0111 to divide system clock by 256 */
335 	0x0020 |        /* Debug mode bit (DBG) stops timer in halted/debug mode */
336 	0x0008 |        /* PIT Interrupt Enable (PIE) to enable PIT interrupts */
337 	0x0002 |        /* Reload (RLD) */
338 	0x0001;         /* PIT Enable (EN) */
339 }
340 
341 /* Clear the timer interrupt and reset the timer
342    Interrupts will be enabled with RTE restores the status register.
343    */
CLEAR_TIMER_INTERRUPT()344 void CLEAR_TIMER_INTERRUPT()
345 {
346     volatile struct __ghs_coldfire_timer *timer =
347 	(struct __ghs_coldfire_timer*)(TIMER0);
348 
349     /* Write to PIT0 Control and Status Register (PCSR) PIT Interrupt
350        Flag (PIF) to clear the PIT interrupt
351        */
352     timer->pcsr =
353 	0x0700 |        /* Prescaler (PRE) = 0b0111 to divide system clock by 256 */
354 	0x0020 |        /* Debug mode bit (DBG) stops timer in halted/debug mode */
355 	0x0008 |        /* PIT Interrupt Enable (PIE) to enable PIT interrupts */
356 	0x0004 |        /* PIT Interrupt Flag (PIF) to clear the PIT interrupt */
357 	0x0002 |        /* Reload (RLD) */
358 	0x0001;         /* PIT Enable (EN) */
359 }
360 
361 #else
362 
363 /* Initialize the timer.  This will overwrite MBAR and ACR0 */
TIMER_INIT(unsigned int count)364 void TIMER_INIT(unsigned int count)
365 {
366     volatile struct __ghs_coldfire_timer *timer =
367 	(struct __ghs_coldfire_timer*)(TIMER0);
368 
369     __MOVEC_MBAR(MBARx|0x1);
370     __MOVEC_ACR0(MBARx|0xc040); /* do not cache memory mapped area */
371 
372     /* reset/disable timer */
373     timer->tmr = 0x0000;
374     timer->tcn = 0;
375     timer->trr = count;
376 
377     setup_timer_interrupt();
378 
379     /* set and enable tmr0 */
380     timer->tmr = 0xff13;
381 }
382 
383 /* Clear the timer interrupt and reset the timer
384    Interrupts will be enabled with RTE restores the status register.
385    */
CLEAR_TIMER_INTERRUPT()386 void CLEAR_TIMER_INTERRUPT()
387 {
388     volatile struct __ghs_coldfire_timer *timer =
389 	(struct __ghs_coldfire_timer*)(TIMER0);
390 
391     timer->ter = 0x3; /* write event bits to clear */
392     timer->tcn = 0x0;
393 }
394 
395 #endif
396 
397 /* Enable PIT interrupts by clearing the Status Register (SR)
398    interrupt priority mask (I) field. */
399 #define ENABLE_TIMER_INTERRUPT __EI
400 
401 /* Return the exception PC */
GET_EPC(void)402 uint32_t GET_EPC(void)
403 {
404     return __ghs_exception_pc;
405 }
406