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 #include <ppc_ghs.h>
11 
12 /***
13  * Tested on IBM PowerPC 750FX Evaluation Board (Buckeye)
14  *           IBM PowerPC 440GX Reference Board
15  *              (don't use board's ROM monitor to reset the board as it
16  *               causes unhandled external interrupts; make sure
17  *               $USE_ROM_MONITOR is set to 0 in board setup script.)
18  *           Embedded Planet RPX Classic LF MPC857T
19  *           Embedded Planet EP8260
20  *           Embedded Planet EP405 with 405gpr
21  *           Freescale MPC55xxDEMO with MPC5534
22  *           Freescale LITE5200
23  *              (tested without using ROM monitor to reset the board; make
24  *               sure $ROM_MONITOR is set to 0 in board setup script.)
25  *
26  * Should work on most PowerPC implemenations.
27  * All implementations need to set TICKS_PER_SEC.
28  */
29 
30 /* TICKS_PER_SEC: on some targets you may be able to read or
31  * compute this value. If so, define a function called
32  * __ghs_manprf_timer_ticks_per_sec that returns the timer
33  * frequency. Otherwise, you'll want to set this value here.
34  */
35 #pragma weak __ghs_manprf_timer_ticks_per_sec
36 unsigned int __ghs_manprf_timer_ticks_per_sec(void);
TICKS_PER_SEC(void)37 unsigned int TICKS_PER_SEC(void) {
38     if(__ghs_manprf_timer_ticks_per_sec) {
39         return __ghs_manprf_timer_ticks_per_sec();
40     } else {
41 	return 20000000;
42     }
43 }
44 
45 /**************** PPC85xx, PPC55xx, PPC440 ****************/
46 #if defined(__SPE__)    || defined(__ppc440)   || defined(__ppc440ep) ||     \
47     defined(__ppc440gx) || defined(__ppc440gr)
48 
49 #ifdef __SPE__
50 #define ENABLE_TIMEBASE                                                     \
51   /* Enable HID0[TBEN] */ __MTSPR(1008, __MFSPR(1008) | 0x4000);
52 #else
53 #define ENABLE_TIMEBASE /* Already enabled. */ ;
54 #endif
55 
56 #define ENABLE_TIMER_INTERRUPT                                              \
57   /* Make IVPR and IVOR10 point to a 16-byte aligned jump to the handler */ \
58   /* Also make IVOR15 point to the same instruction because e500 requires a \
59    * valid opcode at the Debug interrupt vector for successful debugging */ \
60   {                                                                         \
61     unsigned vector = (unsigned)&__ghs_manprf_timer_handler;                \
62     __MTSPR(0x03f/*IVPR*/,   vector & 0xffff0000);                          \
63     __MTSPR(0x19f/*IVOR15*/, vector & 0x0000fff0);                          \
64     __MTSPR(0x19a/*IVOR10*/, vector & 0x0000fff0);                          \
65   }                                                                         \
66   /* Enable TCR[PIE] */                                                     \
67   __MTSPR(0x154/*TCR*/, 0x04000000);                                        \
68   ENABLE_TIMEBASE                                                           \
69   /* Enable interrupts. in particular, set MSR_EE=1 to enable               \
70    *  the decrementer interrupts (note: enables all external                \
71    *  interrupts) */                                                        \
72   __EI
73 
74 /* Initialize the decrementer register. */
75 #define TIMER_INIT(count) __MTSPR(22/*DEC*/, count);                        \
76   /* Clear TSR[TIS] */                                                      \
77   __MTSPR(0x150/*TSR*/, 0x08000000)
78 
79 
80 /**************** PPC40x ****************/
81 #elif defined(__ppc405) || defined(__ppc403) || defined(__ppc401)
82 
83 #define __PIT_VECTOR_ADDRESS 0x00001000
84 
85 #define ENABLE_TIMER_INTERRUPT                                              \
86   /* Setup EVPR to vector correctly */                                      \
87   __MTSPR(0x3d6/*EVPR*/, __PIT_VECTOR_ADDRESS & 0xffff0000);                \
88   /* Enable TCR[PIE] */                                                     \
89   __MTSPR(0x3da/*TCR*/, 0x04000000);                                        \
90   /* Enable interrupts. in particular, set MSR_EE=1 to enable               \
91    *  the decrementer interrupts (note: enables all external                \
92    *  interrupts) */                                                        \
93   __EI
94 
95 /* setup the interrupt vector: timer interrupt (assumes EVPR = 0) */
96 #pragma intvect __ghs_manprf_timer_handler __PIT_VECTOR_ADDRESS
97 
98 /* Initialize the PIT register. */
99 #define TIMER_INIT(count) __MTSPR(0x3db/*PIT*/, count);                     \
100   /* Clear TSR[PIS] */                                                      \
101   __MTSPR(0x3d8/*TSR*/, 0x08000000)
102 
103 #else
104 
105 
106 /**************** PPC8xx ****************/
107 #if defined(__ppc821)    || defined(__ppc823)  || defined(__ppc823e)   ||    \
108     defined(__ppc850)    || defined(__ppc852t) || defined(__ppc855t)   ||    \
109     defined(__ppc857dsl) || defined(__ppc857t) || defined(__ppc859dsl) ||    \
110     defined(__ppc859t)   || defined(__ppc860)  || defined(__ppc862)    ||    \
111     defined(__ppc866p)   || defined(__ppc866t) || defined(__ppc870)    ||    \
112     defined(__ppc875)    || defined(__ppc880)  || defined(__ppc885)
113 
114 /* Initialize the decrementer register. */
115 #define TIMER_INIT(count)                                                    \
116   /*  Need to unprotect the decrementer by writting 0x55ccaa33 to TBK */     \
117   *(volatile int*)((__MFSPR(638/*IMMR*/)&0xffff0000)+0x30c) = 0x55ccaa33;    \
118   /* Initialize the decrementer register. */                                 \
119   __MTSPR(22/*DEC*/, count)
120 
121 
122 /**************** PPC52xx ****************/
123 #elif defined(__ppc5200)
124 
125 #define TIMER_INIT(count)                                                    \
126   /* Assume MBAR == 0x80000000 (as on reset). Turn on TBEN (Time Base   */   \
127   /* Enable) in the XLB Arbiter Configuration Register, at MBAR+0x1F40. */   \
128   *(int *)(0x80001F40) |= 0x2000;                                            \
129   /* Initialize the decrementer register. */                                 \
130   __MTSPR(22/*DEC*/, count)
131 
132 #else
133 
134 
135 /**************** All Other PowerPC's ****************/
136 
137 /* Initialize the decrementer register. */
138 #define TIMER_INIT(count) __MTSPR(22/*DEC*/, count)
139 
140 #endif
141 
142 /* setup the interrupt vector: timer interrupt */
143 #pragma intvect __ghs_manprf_timer_handler 0x00000900
144 
145 /* Enable interrupts. in particular, set MSR_EE=1 to enable
146  *  the decrementer interrupts (note: enables all external
147  *  interrupts) */
148 #define ENABLE_TIMER_INTERRUPT __EI
149 
150 #endif
151 
152 /* Return address points to next instruction to execute.
153  *  Use that value as the sample. */
154 #define GET_EPC() (address)__builtin_return_address(0)
155 
156 #define CLEAR_TIMER_INTERRUPT()
157     /* PowerPC interrupt cleared on return */
158