]>
Commit | Line | Data |
---|---|---|
1e9a164e DH |
1 | /* Initializes CPU and basic hardware such as memory |
2 | * controllers, IRQ controller and system timer 0. | |
3 | * | |
4 | * (C) Copyright 2007 | |
5 | * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com | |
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 | ||
27 | #include <common.h> | |
28 | #include <asm/asi.h> | |
29 | #include <asm/leon.h> | |
30 | #include <ambapp.h> | |
31 | ||
32 | #include <config.h> | |
33 | ||
34 | DECLARE_GLOBAL_DATA_PTR; | |
35 | ||
36 | /* reset CPU (jump to 0, without reset) */ | |
37 | void start(void); | |
38 | ||
39 | /* find & initialize the memory controller */ | |
40 | int init_memory_ctrl(void); | |
41 | ||
42 | ambapp_dev_irqmp *irqmp = NULL; | |
43 | ambapp_dev_mctrl memctrl; | |
44 | ambapp_dev_gptimer *gptimer = NULL; | |
45 | unsigned int gptimer_irq = 0; | |
46 | int leon3_snooping_avail = 0; | |
47 | ||
48 | struct { | |
49 | gd_t gd_area; | |
50 | bd_t bd; | |
51 | } global_data; | |
52 | ||
53 | /* | |
54 | * Breath some life into the CPU... | |
55 | * | |
56 | * Set up the memory map, | |
57 | * initialize a bunch of registers. | |
58 | * | |
59 | * Run from FLASH/PROM: | |
60 | * - until memory controller is set up, only registers avaiable | |
61 | * - no global variables available for writing | |
62 | * - constants avaiable | |
63 | */ | |
64 | ||
65 | void cpu_init_f(void) | |
66 | { | |
67 | /* these varaiable must not be initialized */ | |
68 | ambapp_dev_irqmp *irqmp; | |
69 | ambapp_apbdev apbdev; | |
70 | register unsigned int apbmst; | |
71 | ||
72 | /* find AMBA APB Master */ | |
73 | apbmst = (unsigned int) | |
74 | ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0); | |
75 | if (!apbmst) { | |
76 | /* | |
77 | * no AHB/APB bridge, something is wrong | |
78 | * ==> jump to start (or hang) | |
79 | */ | |
80 | while (1) ; | |
81 | } | |
82 | /* Init memory controller */ | |
83 | if (init_memory_ctrl()) { | |
84 | while (1) ; | |
85 | } | |
86 | ||
87 | /**************************************************** | |
88 | * From here we can use the main memory and the stack. | |
89 | */ | |
90 | ||
91 | /* Find AMBA APB IRQMP Controller */ | |
92 | if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) != 1) { | |
93 | /* no IRQ controller, something is wrong | |
94 | * ==> jump to start (or hang) | |
95 | */ | |
96 | while (1) ; | |
97 | } | |
98 | irqmp = (ambapp_dev_irqmp *) apbdev.address; | |
99 | ||
100 | /* initialize the IRQMP */ | |
101 | irqmp->ilevel = 0xf; /* all IRQ off */ | |
102 | irqmp->iforce = 0; | |
103 | irqmp->ipend = 0; | |
104 | irqmp->iclear = 0xfffe; /* clear all old pending interrupts */ | |
105 | irqmp->cpu_mask[0] = 0; /* mask all IRQs on CPU 0 */ | |
106 | irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */ | |
107 | ||
108 | /* cache */ | |
109 | } | |
110 | ||
111 | void cpu_init_f2(void) | |
112 | { | |
113 | ||
114 | } | |
115 | ||
116 | /* | |
117 | * initialize higher level parts of CPU like time base and timers | |
118 | */ | |
119 | int cpu_init_r(void) | |
120 | { | |
121 | ambapp_apbdev apbdev; | |
122 | ||
123 | /* | |
124 | * Find AMBA APB IRQMP Controller, | |
125 | * When we come so far we know there is a IRQMP available | |
126 | */ | |
127 | ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev); | |
128 | irqmp = (ambapp_dev_irqmp *) apbdev.address; | |
129 | ||
130 | /* timer */ | |
131 | if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_GPTIMER, &apbdev) != 1) { | |
132 | printf("cpu_init_r: gptimer not found!\n"); | |
133 | return 1; | |
134 | } | |
135 | gptimer = (ambapp_dev_gptimer *) apbdev.address; | |
136 | gptimer_irq = apbdev.irq; | |
137 | ||
138 | /* initialize prescaler common to all timers to 1MHz */ | |
139 | gptimer->scalar = gptimer->scalar_reload = | |
140 | (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; | |
141 | ||
142 | return (0); | |
143 | } | |
144 | ||
145 | /* find & setup memory controller */ | |
146 | int init_memory_ctrl() | |
147 | { | |
148 | register ambapp_dev_mctrl *mctrl; | |
149 | register ambapp_dev_sdctrl *sdctrl; | |
150 | register ambapp_dev_ddrspa *ddrspa; | |
151 | register ambapp_dev_ddr2spa *ddr2spa; | |
152 | register ahbctrl_pp_dev *ahb; | |
153 | register unsigned int base; | |
154 | register int not_found_mctrl = -1; | |
155 | ||
156 | /* find ESA Memory controller */ | |
157 | base = ambapp_apb_next_nomem(VENDOR_ESA, ESA_MCTRL, 0); | |
158 | if (base) { | |
159 | mctrl = (ambapp_dev_mctrl *) base; | |
160 | ||
161 | /* config MCTRL memory controller */ | |
6d0f6bcf JCPV |
162 | mctrl->mcfg1 = CONFIG_SYS_GRLIB_MEMCFG1 | (mctrl->mcfg1 & 0x300); |
163 | mctrl->mcfg2 = CONFIG_SYS_GRLIB_MEMCFG2; | |
164 | mctrl->mcfg3 = CONFIG_SYS_GRLIB_MEMCFG3; | |
1e9a164e DH |
165 | not_found_mctrl = 0; |
166 | } | |
167 | ||
168 | /* find Gaisler Fault Tolerant Memory controller */ | |
169 | base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_FTMCTRL, 0); | |
170 | if (base) { | |
171 | mctrl = (ambapp_dev_mctrl *) base; | |
172 | ||
173 | /* config MCTRL memory controller */ | |
6d0f6bcf JCPV |
174 | mctrl->mcfg1 = CONFIG_SYS_GRLIB_FT_MEMCFG1 | (mctrl->mcfg1 & 0x300); |
175 | mctrl->mcfg2 = CONFIG_SYS_GRLIB_FT_MEMCFG2; | |
176 | mctrl->mcfg3 = CONFIG_SYS_GRLIB_FT_MEMCFG3; | |
1e9a164e DH |
177 | not_found_mctrl = 0; |
178 | } | |
179 | ||
180 | /* find SDRAM controller */ | |
181 | base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_SDCTRL, 0); | |
182 | if (base) { | |
183 | sdctrl = (ambapp_dev_sdctrl *) base; | |
184 | ||
185 | /* config memory controller */ | |
6d0f6bcf | 186 | sdctrl->sdcfg = CONFIG_SYS_GRLIB_SDRAM; |
1e9a164e DH |
187 | not_found_mctrl = 0; |
188 | } | |
189 | ||
190 | ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDR2SPA, 1, 0); | |
191 | if (ahb) { | |
192 | ddr2spa = (ambapp_dev_ddr2spa *) ambapp_ahb_get_info(ahb, 1); | |
193 | ||
194 | /* Config DDR2 memory controller */ | |
6d0f6bcf JCPV |
195 | ddr2spa->cfg1 = CONFIG_SYS_GRLIB_DDR2_CFG1; |
196 | ddr2spa->cfg3 = CONFIG_SYS_GRLIB_DDR2_CFG3; | |
1e9a164e DH |
197 | not_found_mctrl = 0; |
198 | } | |
199 | ||
200 | ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDRSPA, 1, 0); | |
201 | if (ahb) { | |
202 | ddrspa = (ambapp_dev_ddrspa *) ambapp_ahb_get_info(ahb, 1); | |
203 | ||
204 | /* Config DDR memory controller */ | |
6d0f6bcf | 205 | ddrspa->ctrl = CONFIG_SYS_GRLIB_DDR_CFG; |
1e9a164e DH |
206 | not_found_mctrl = 0; |
207 | } | |
208 | ||
209 | /* failed to find any memory controller */ | |
210 | return not_found_mctrl; | |
211 | } | |
212 | ||
213 | /* Uses Timer 0 to get accurate | |
214 | * pauses. Max 2 raised to 32 ticks | |
215 | * | |
216 | */ | |
217 | void cpu_wait_ticks(unsigned long ticks) | |
218 | { | |
219 | unsigned long start = get_timer(0); | |
220 | while (get_timer(start) < ticks) ; | |
221 | } | |
222 | ||
223 | /* initiate and setup timer0 interrupt to 1MHz | |
224 | * Return irq number for timer int or a negative number for | |
225 | * dealing with self | |
226 | */ | |
227 | int timer_interrupt_init_cpu(void) | |
228 | { | |
229 | /* 1ms ticks */ | |
230 | gptimer->e[0].val = 0; | |
231 | gptimer->e[0].rld = 999; /* (((1000000 / 100) - 1)) */ | |
232 | gptimer->e[0].ctrl = | |
233 | (LEON3_GPTIMER_EN | | |
234 | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); | |
235 | ||
236 | return gptimer_irq; | |
237 | } | |
238 | ||
239 | /* | |
240 | * This function is intended for SHORT delays only. | |
241 | */ | |
242 | unsigned long cpu_usec2ticks(unsigned long usec) | |
243 | { | |
244 | /* timer set to 1kHz ==> 1 clk tick = 1 msec */ | |
245 | if (usec < 1000) | |
246 | return 1; | |
247 | return (usec / 1000); | |
248 | } | |
249 | ||
250 | unsigned long cpu_ticks2usec(unsigned long ticks) | |
251 | { | |
252 | /* 1tick = 1usec */ | |
253 | return ticks * 1000; | |
254 | } |