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