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