]>
Commit | Line | Data |
---|---|---|
2f78eae5 | 1 | /* |
9f3183d2 | 2 | * Copyright 2014-2015 Freescale Semiconductor, Inc. |
2f78eae5 YS |
3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <asm/io.h> | |
1221ce45 | 9 | #include <linux/errno.h> |
2f78eae5 YS |
10 | #include <asm/system.h> |
11 | #include <asm/armv8/mmu.h> | |
12 | #include <asm/io.h> | |
9f3183d2 MH |
13 | #include <asm/arch/fsl_serdes.h> |
14 | #include <asm/arch/soc.h> | |
15 | #include <asm/arch/cpu.h> | |
16 | #include <asm/arch/speed.h> | |
17 | #ifdef CONFIG_MP | |
18 | #include <asm/arch/mp.h> | |
19 | #endif | |
78d57842 | 20 | #include <efi_loader.h> |
9f3183d2 | 21 | #include <fm_eth.h> |
7b3bd9a7 | 22 | #include <fsl-mc/fsl_mc.h> |
8b06460e YL |
23 | #ifdef CONFIG_FSL_ESDHC |
24 | #include <fsl_esdhc.h> | |
25 | #endif | |
032d5bb4 HZ |
26 | #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT |
27 | #include <asm/armv8/sec_firmware.h> | |
28 | #endif | |
02fb2761 SL |
29 | #ifdef CONFIG_SYS_FSL_DDR |
30 | #include <fsl_ddr.h> | |
31 | #endif | |
2f78eae5 YS |
32 | |
33 | DECLARE_GLOBAL_DATA_PTR; | |
34 | ||
5ad5823d | 35 | struct mm_region *mem_map = early_map; |
7985cdf7 | 36 | |
22629665 PK |
37 | void cpu_name(char *name) |
38 | { | |
39 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
40 | unsigned int i, svr, ver; | |
41 | ||
9f3183d2 | 42 | svr = gur_in32(&gur->svr); |
22629665 PK |
43 | ver = SVR_SOC_VER(svr); |
44 | ||
45 | for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) | |
46 | if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) { | |
47 | strcpy(name, cpu_type_list[i].name); | |
48 | ||
49 | if (IS_E_PROCESSOR(svr)) | |
50 | strcat(name, "E"); | |
5d1a7a9d WS |
51 | |
52 | sprintf(name + strlen(name), " Rev%d.%d", | |
53 | SVR_MAJ(svr), SVR_MIN(svr)); | |
22629665 PK |
54 | break; |
55 | } | |
56 | ||
57 | if (i == ARRAY_SIZE(cpu_type_list)) | |
58 | strcpy(name, "unknown"); | |
59 | } | |
60 | ||
2f78eae5 | 61 | #ifndef CONFIG_SYS_DCACHE_OFF |
99799220 AW |
62 | /* |
63 | * To start MMU before DDR is available, we create MMU table in SRAM. | |
64 | * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three | |
65 | * levels of translation tables here to cover 40-bit address space. | |
66 | * We use 4KB granule size, with 40 bits physical address, T0SZ=24 | |
5ad5823d YS |
67 | * Address above EARLY_PGTABLE_SIZE (0x5000) is free for other purpose. |
68 | * Note, the debug print in cache_v8.c is not usable for debugging | |
69 | * these early MMU tables because UART is not yet available. | |
99799220 AW |
70 | */ |
71 | static inline void early_mmu_setup(void) | |
72 | { | |
5ad5823d | 73 | unsigned int el = current_el(); |
99799220 | 74 | |
5ad5823d YS |
75 | /* global data is already setup, no allocation yet */ |
76 | gd->arch.tlb_addr = CONFIG_SYS_FSL_OCRAM_BASE; | |
77 | gd->arch.tlb_fillptr = gd->arch.tlb_addr; | |
78 | gd->arch.tlb_size = EARLY_PGTABLE_SIZE; | |
99799220 | 79 | |
5ad5823d YS |
80 | /* Create early page tables */ |
81 | setup_pgtables(); | |
9f3183d2 | 82 | |
5ad5823d YS |
83 | /* point TTBR to the new table */ |
84 | set_ttbr_tcr_mair(el, gd->arch.tlb_addr, | |
85 | get_tcr(el, NULL, NULL) & | |
86 | ~(TCR_ORGN_MASK | TCR_IRGN_MASK), | |
9f3183d2 | 87 | MEMORY_ATTRIBUTES); |
c107c0c0 | 88 | |
5ad5823d | 89 | set_sctlr(get_sctlr() | CR_M); |
c107c0c0 | 90 | } |
c107c0c0 | 91 | |
3d8553f0 HZ |
92 | static void fix_pcie_mmu_map(void) |
93 | { | |
94 | #ifdef CONFIG_LS2080A | |
95 | unsigned int i; | |
96 | u32 svr, ver; | |
97 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
98 | ||
99 | svr = gur_in32(&gur->svr); | |
100 | ver = SVR_SOC_VER(svr); | |
101 | ||
102 | /* Fix PCIE base and size for LS2088A */ | |
103 | if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) || | |
104 | (ver == SVR_LS2048A) || (ver == SVR_LS2044A)) { | |
105 | for (i = 0; i < ARRAY_SIZE(final_map); i++) { | |
106 | switch (final_map[i].phys) { | |
107 | case CONFIG_SYS_PCIE1_PHYS_ADDR: | |
108 | final_map[i].phys = 0x2000000000ULL; | |
109 | final_map[i].virt = 0x2000000000ULL; | |
110 | final_map[i].size = 0x800000000ULL; | |
111 | break; | |
112 | case CONFIG_SYS_PCIE2_PHYS_ADDR: | |
113 | final_map[i].phys = 0x2800000000ULL; | |
114 | final_map[i].virt = 0x2800000000ULL; | |
115 | final_map[i].size = 0x800000000ULL; | |
116 | break; | |
117 | case CONFIG_SYS_PCIE3_PHYS_ADDR: | |
118 | final_map[i].phys = 0x3000000000ULL; | |
119 | final_map[i].virt = 0x3000000000ULL; | |
120 | final_map[i].size = 0x800000000ULL; | |
121 | break; | |
122 | case CONFIG_SYS_PCIE4_PHYS_ADDR: | |
123 | final_map[i].phys = 0x3800000000ULL; | |
124 | final_map[i].virt = 0x3800000000ULL; | |
125 | final_map[i].size = 0x800000000ULL; | |
126 | break; | |
127 | default: | |
128 | break; | |
129 | } | |
130 | } | |
131 | } | |
132 | #endif | |
133 | } | |
134 | ||
2f78eae5 | 135 | /* |
99799220 AW |
136 | * The final tables look similar to early tables, but different in detail. |
137 | * These tables are in DRAM. Sub tables are added to enable cache for | |
138 | * QBMan and OCRAM. | |
139 | * | |
e61a7534 YS |
140 | * Put the MMU table in secure memory if gd->arch.secure_ram is valid. |
141 | * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0. | |
2f78eae5 YS |
142 | */ |
143 | static inline void final_mmu_setup(void) | |
144 | { | |
5ad5823d | 145 | u64 tlb_addr_save = gd->arch.tlb_addr; |
c107c0c0 | 146 | unsigned int el = current_el(); |
5ad5823d | 147 | int index; |
2f78eae5 | 148 | |
3d8553f0 HZ |
149 | /* fix the final_map before filling in the block entries */ |
150 | fix_pcie_mmu_map(); | |
151 | ||
5ad5823d | 152 | mem_map = final_map; |
2f78eae5 | 153 | |
24f55496 YS |
154 | /* Update mapping for DDR to actual size */ |
155 | for (index = 0; index < ARRAY_SIZE(final_map) - 2; index++) { | |
156 | /* | |
157 | * Find the entry for DDR mapping and update the address and | |
158 | * size. Zero-sized mapping will be skipped when creating MMU | |
159 | * table. | |
160 | */ | |
161 | switch (final_map[index].virt) { | |
162 | case CONFIG_SYS_FSL_DRAM_BASE1: | |
163 | final_map[index].virt = gd->bd->bi_dram[0].start; | |
164 | final_map[index].phys = gd->bd->bi_dram[0].start; | |
165 | final_map[index].size = gd->bd->bi_dram[0].size; | |
166 | break; | |
167 | #ifdef CONFIG_SYS_FSL_DRAM_BASE2 | |
168 | case CONFIG_SYS_FSL_DRAM_BASE2: | |
169 | #if (CONFIG_NR_DRAM_BANKS >= 2) | |
170 | final_map[index].virt = gd->bd->bi_dram[1].start; | |
171 | final_map[index].phys = gd->bd->bi_dram[1].start; | |
172 | final_map[index].size = gd->bd->bi_dram[1].size; | |
173 | #else | |
174 | final_map[index].size = 0; | |
175 | #endif | |
176 | break; | |
177 | #endif | |
178 | #ifdef CONFIG_SYS_FSL_DRAM_BASE3 | |
179 | case CONFIG_SYS_FSL_DRAM_BASE3: | |
180 | #if (CONFIG_NR_DRAM_BANKS >= 3) | |
181 | final_map[index].virt = gd->bd->bi_dram[2].start; | |
182 | final_map[index].phys = gd->bd->bi_dram[2].start; | |
183 | final_map[index].size = gd->bd->bi_dram[2].size; | |
184 | #else | |
185 | final_map[index].size = 0; | |
186 | #endif | |
187 | break; | |
188 | #endif | |
189 | default: | |
190 | break; | |
191 | } | |
192 | } | |
193 | ||
c107c0c0 | 194 | #ifdef CONFIG_SYS_MEM_RESERVE_SECURE |
5ad5823d YS |
195 | if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) { |
196 | if (el == 3) { | |
197 | /* | |
198 | * Only use gd->arch.secure_ram if the address is | |
199 | * recalculated. Align to 4KB for MMU table. | |
200 | */ | |
201 | /* put page tables in secure ram */ | |
202 | index = ARRAY_SIZE(final_map) - 2; | |
203 | gd->arch.tlb_addr = gd->arch.secure_ram & ~0xfff; | |
204 | final_map[index].virt = gd->arch.secure_ram & ~0x3; | |
205 | final_map[index].phys = final_map[index].virt; | |
206 | final_map[index].size = CONFIG_SYS_MEM_RESERVE_SECURE; | |
207 | final_map[index].attrs = PTE_BLOCK_OUTER_SHARE; | |
e61a7534 | 208 | gd->arch.secure_ram |= MEM_RESERVE_SECURE_SECURED; |
5ad5823d | 209 | tlb_addr_save = gd->arch.tlb_addr; |
c107c0c0 | 210 | } else { |
5ad5823d YS |
211 | /* Use allocated (board_f.c) memory for TLB */ |
212 | tlb_addr_save = gd->arch.tlb_allocated; | |
213 | gd->arch.tlb_addr = tlb_addr_save; | |
c107c0c0 YS |
214 | } |
215 | } | |
216 | #endif | |
2f78eae5 | 217 | |
5ad5823d YS |
218 | /* Reset the fill ptr */ |
219 | gd->arch.tlb_fillptr = tlb_addr_save; | |
220 | ||
221 | /* Create normal system page tables */ | |
222 | setup_pgtables(); | |
223 | ||
224 | /* Create emergency page tables */ | |
225 | gd->arch.tlb_addr = gd->arch.tlb_fillptr; | |
226 | gd->arch.tlb_emerg = gd->arch.tlb_addr; | |
227 | setup_pgtables(); | |
228 | gd->arch.tlb_addr = tlb_addr_save; | |
229 | ||
a045a0c3 YS |
230 | /* Disable cache and MMU */ |
231 | dcache_disable(); /* TLBs are invalidated */ | |
232 | invalidate_icache_all(); | |
2f78eae5 YS |
233 | |
234 | /* point TTBR to the new table */ | |
5ad5823d | 235 | set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL), |
db14f11d | 236 | MEMORY_ATTRIBUTES); |
a045a0c3 | 237 | |
ed7a3943 | 238 | set_sctlr(get_sctlr() | CR_M); |
2f78eae5 YS |
239 | } |
240 | ||
c05016ab AG |
241 | u64 get_page_table_size(void) |
242 | { | |
243 | return 0x10000; | |
244 | } | |
245 | ||
2f78eae5 YS |
246 | int arch_cpu_init(void) |
247 | { | |
248 | icache_enable(); | |
249 | __asm_invalidate_dcache_all(); | |
250 | __asm_invalidate_tlb_all(); | |
251 | early_mmu_setup(); | |
252 | set_sctlr(get_sctlr() | CR_C); | |
253 | return 0; | |
254 | } | |
255 | ||
85cdf38e HZ |
256 | void mmu_setup(void) |
257 | { | |
258 | final_mmu_setup(); | |
259 | } | |
260 | ||
2f78eae5 | 261 | /* |
85cdf38e HZ |
262 | * This function is called from common/board_r.c. |
263 | * It recreates MMU table in main memory. | |
2f78eae5 YS |
264 | */ |
265 | void enable_caches(void) | |
266 | { | |
85cdf38e | 267 | mmu_setup(); |
2f78eae5 | 268 | __asm_invalidate_tlb_all(); |
85cdf38e HZ |
269 | icache_enable(); |
270 | dcache_enable(); | |
2f78eae5 YS |
271 | } |
272 | #endif | |
273 | ||
e87c673c | 274 | u32 initiator_type(u32 cluster, int init_id) |
2f78eae5 YS |
275 | { |
276 | struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
277 | u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK; | |
9f3183d2 | 278 | u32 type = 0; |
2f78eae5 | 279 | |
9f3183d2 | 280 | type = gur_in32(&gur->tp_ityp[idx]); |
2f78eae5 YS |
281 | if (type & TP_ITYP_AV) |
282 | return type; | |
283 | ||
284 | return 0; | |
285 | } | |
286 | ||
ef9a5fd8 YS |
287 | u32 cpu_pos_mask(void) |
288 | { | |
289 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
290 | int i = 0; | |
291 | u32 cluster, type, mask = 0; | |
292 | ||
293 | do { | |
294 | int j; | |
295 | ||
296 | cluster = gur_in32(&gur->tp_cluster[i].lower); | |
297 | for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { | |
298 | type = initiator_type(cluster, j); | |
299 | if (type && (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)) | |
300 | mask |= 1 << (i * TP_INIT_PER_CLUSTER + j); | |
301 | } | |
302 | i++; | |
303 | } while ((cluster & TP_CLUSTER_EOC) == 0x0); | |
304 | ||
305 | return mask; | |
306 | } | |
307 | ||
2f78eae5 YS |
308 | u32 cpu_mask(void) |
309 | { | |
310 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
311 | int i = 0, count = 0; | |
312 | u32 cluster, type, mask = 0; | |
313 | ||
314 | do { | |
315 | int j; | |
9f3183d2 MH |
316 | |
317 | cluster = gur_in32(&gur->tp_cluster[i].lower); | |
2f78eae5 YS |
318 | for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { |
319 | type = initiator_type(cluster, j); | |
320 | if (type) { | |
321 | if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM) | |
322 | mask |= 1 << count; | |
323 | count++; | |
324 | } | |
325 | } | |
326 | i++; | |
9f3183d2 | 327 | } while ((cluster & TP_CLUSTER_EOC) == 0x0); |
2f78eae5 YS |
328 | |
329 | return mask; | |
330 | } | |
331 | ||
332 | /* | |
333 | * Return the number of cores on this SOC. | |
334 | */ | |
335 | int cpu_numcores(void) | |
336 | { | |
337 | return hweight32(cpu_mask()); | |
338 | } | |
339 | ||
340 | int fsl_qoriq_core_to_cluster(unsigned int core) | |
341 | { | |
342 | struct ccsr_gur __iomem *gur = | |
343 | (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
344 | int i = 0, count = 0; | |
345 | u32 cluster; | |
346 | ||
347 | do { | |
348 | int j; | |
9f3183d2 MH |
349 | |
350 | cluster = gur_in32(&gur->tp_cluster[i].lower); | |
2f78eae5 YS |
351 | for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { |
352 | if (initiator_type(cluster, j)) { | |
353 | if (count == core) | |
354 | return i; | |
355 | count++; | |
356 | } | |
357 | } | |
358 | i++; | |
9f3183d2 | 359 | } while ((cluster & TP_CLUSTER_EOC) == 0x0); |
2f78eae5 YS |
360 | |
361 | return -1; /* cannot identify the cluster */ | |
362 | } | |
363 | ||
364 | u32 fsl_qoriq_core_to_type(unsigned int core) | |
365 | { | |
366 | struct ccsr_gur __iomem *gur = | |
367 | (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
368 | int i = 0, count = 0; | |
369 | u32 cluster, type; | |
370 | ||
371 | do { | |
372 | int j; | |
9f3183d2 MH |
373 | |
374 | cluster = gur_in32(&gur->tp_cluster[i].lower); | |
2f78eae5 YS |
375 | for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { |
376 | type = initiator_type(cluster, j); | |
377 | if (type) { | |
378 | if (count == core) | |
379 | return type; | |
380 | count++; | |
381 | } | |
382 | } | |
383 | i++; | |
9f3183d2 | 384 | } while ((cluster & TP_CLUSTER_EOC) == 0x0); |
2f78eae5 YS |
385 | |
386 | return -1; /* cannot identify the cluster */ | |
387 | } | |
388 | ||
f6a70b3a | 389 | #ifndef CONFIG_FSL_LSCH3 |
6fb522dc SD |
390 | uint get_svr(void) |
391 | { | |
392 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
393 | ||
394 | return gur_in32(&gur->svr); | |
395 | } | |
f6a70b3a | 396 | #endif |
6fb522dc | 397 | |
2f78eae5 YS |
398 | #ifdef CONFIG_DISPLAY_CPUINFO |
399 | int print_cpuinfo(void) | |
400 | { | |
d27bf906 | 401 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); |
2f78eae5 YS |
402 | struct sys_info sysinfo; |
403 | char buf[32]; | |
404 | unsigned int i, core; | |
3c1d218a | 405 | u32 type, rcw, svr = gur_in32(&gur->svr); |
2f78eae5 | 406 | |
22629665 PK |
407 | puts("SoC: "); |
408 | ||
409 | cpu_name(buf); | |
3c1d218a | 410 | printf(" %s (0x%x)\n", buf, svr); |
22629665 | 411 | memset((u8 *)buf, 0x00, ARRAY_SIZE(buf)); |
2f78eae5 YS |
412 | get_sys_info(&sysinfo); |
413 | puts("Clock Configuration:"); | |
414 | for_each_cpu(i, core, cpu_numcores(), cpu_mask()) { | |
415 | if (!(i % 3)) | |
416 | puts("\n "); | |
417 | type = TP_ITYP_VER(fsl_qoriq_core_to_type(core)); | |
418 | printf("CPU%d(%s):%-4s MHz ", core, | |
419 | type == TY_ITYP_VER_A7 ? "A7 " : | |
420 | (type == TY_ITYP_VER_A53 ? "A53" : | |
79119a4d AW |
421 | (type == TY_ITYP_VER_A57 ? "A57" : |
422 | (type == TY_ITYP_VER_A72 ? "A72" : " "))), | |
2f78eae5 YS |
423 | strmhz(buf, sysinfo.freq_processor[core])); |
424 | } | |
904110c7 | 425 | /* Display platform clock as Bus frequency. */ |
2f78eae5 | 426 | printf("\n Bus: %-4s MHz ", |
904110c7 | 427 | strmhz(buf, sysinfo.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV)); |
d4c711f0 | 428 | printf("DDR: %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus)); |
e8297341 SX |
429 | #ifdef CONFIG_SYS_DPAA_FMAN |
430 | printf(" FMAN: %-4s MHz", strmhz(buf, sysinfo.freq_fman[0])); | |
431 | #endif | |
44937214 | 432 | #ifdef CONFIG_SYS_FSL_HAS_DP_DDR |
3c1d218a YS |
433 | if (soc_has_dp_ddr()) { |
434 | printf(" DP-DDR: %-4s MT/s", | |
435 | strmhz(buf, sysinfo.freq_ddrbus2)); | |
436 | } | |
9f3183d2 | 437 | #endif |
2f78eae5 YS |
438 | puts("\n"); |
439 | ||
9f3183d2 MH |
440 | /* |
441 | * Display the RCW, so that no one gets confused as to what RCW | |
d27bf906 BS |
442 | * we're actually using for this boot. |
443 | */ | |
444 | puts("Reset Configuration Word (RCW):"); | |
445 | for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { | |
9f3183d2 | 446 | rcw = gur_in32(&gur->rcwsr[i]); |
d27bf906 | 447 | if ((i % 4) == 0) |
9f3183d2 | 448 | printf("\n %08x:", i * 4); |
d27bf906 BS |
449 | printf(" %08x", rcw); |
450 | } | |
451 | puts("\n"); | |
452 | ||
2f78eae5 YS |
453 | return 0; |
454 | } | |
455 | #endif | |
b940ca64 | 456 | |
8b06460e YL |
457 | #ifdef CONFIG_FSL_ESDHC |
458 | int cpu_mmc_init(bd_t *bis) | |
459 | { | |
460 | return fsl_esdhc_mmc_init(bis); | |
461 | } | |
462 | #endif | |
463 | ||
b940ca64 GR |
464 | int cpu_eth_init(bd_t *bis) |
465 | { | |
466 | int error = 0; | |
467 | ||
468 | #ifdef CONFIG_FSL_MC_ENET | |
a2a55e51 | 469 | error = fsl_mc_ldpaa_init(bis); |
e8297341 SX |
470 | #endif |
471 | #ifdef CONFIG_FMAN_ENET | |
472 | fm_standard_init(bis); | |
b940ca64 GR |
473 | #endif |
474 | return error; | |
475 | } | |
40f8dec5 | 476 | |
40f8dec5 YS |
477 | int arch_early_init_r(void) |
478 | { | |
9f3183d2 MH |
479 | #ifdef CONFIG_MP |
480 | int rv = 1; | |
032d5bb4 | 481 | u32 psci_ver = 0xffffffff; |
b4017364 PK |
482 | #endif |
483 | ||
484 | #ifdef CONFIG_SYS_FSL_ERRATUM_A009635 | |
eea1cb77 PJ |
485 | u32 svr_dev_id; |
486 | /* | |
487 | * erratum A009635 is valid only for LS2080A SoC and | |
488 | * its personalitiesi | |
489 | */ | |
490 | svr_dev_id = get_svr() >> 16; | |
491 | if (svr_dev_id == SVR_DEV_LS2080A) | |
492 | erratum_a009635(); | |
b4017364 | 493 | #endif |
02fb2761 SL |
494 | #if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR) |
495 | erratum_a009942_check_cpo(); | |
496 | #endif | |
b4017364 | 497 | #ifdef CONFIG_MP |
2d16a1a6 | 498 | #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \ |
daa92644 | 499 | defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI) |
032d5bb4 HZ |
500 | /* Check the psci version to determine if the psci is supported */ |
501 | psci_ver = sec_firmware_support_psci_version(); | |
502 | #endif | |
503 | if (psci_ver == 0xffffffff) { | |
504 | rv = fsl_layerscape_wake_seconday_cores(); | |
505 | if (rv) | |
506 | printf("Did not wake secondary cores\n"); | |
507 | } | |
9f3183d2 | 508 | #endif |
40f8dec5 | 509 | |
31d34c6c ML |
510 | #ifdef CONFIG_SYS_HAS_SERDES |
511 | fsl_serdes_init(); | |
e8297341 SX |
512 | #endif |
513 | #ifdef CONFIG_FMAN_ENET | |
514 | fman_enet_init(); | |
31d34c6c | 515 | #endif |
40f8dec5 YS |
516 | return 0; |
517 | } | |
207774b2 YS |
518 | |
519 | int timer_init(void) | |
520 | { | |
521 | u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR; | |
9f3183d2 | 522 | #ifdef CONFIG_FSL_LSCH3 |
207774b2 | 523 | u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR; |
9f3183d2 | 524 | #endif |
a758177f YC |
525 | #ifdef CONFIG_LS2080A |
526 | u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET; | |
f6b96ff6 | 527 | u32 svr_dev_id; |
a758177f | 528 | #endif |
207774b2 YS |
529 | #ifdef COUNTER_FREQUENCY_REAL |
530 | unsigned long cntfrq = COUNTER_FREQUENCY_REAL; | |
531 | ||
532 | /* Update with accurate clock frequency */ | |
533 | asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); | |
534 | #endif | |
535 | ||
9f3183d2 | 536 | #ifdef CONFIG_FSL_LSCH3 |
207774b2 YS |
537 | /* Enable timebase for all clusters. |
538 | * It is safe to do so even some clusters are not enabled. | |
539 | */ | |
540 | out_le32(cltbenr, 0xf); | |
9f3183d2 | 541 | #endif |
207774b2 | 542 | |
a758177f YC |
543 | #ifdef CONFIG_LS2080A |
544 | /* | |
545 | * In certain Layerscape SoCs, the clock for each core's | |
546 | * has an enable bit in the PMU Physical Core Time Base Enable | |
547 | * Register (PCTBENR), which allows the watchdog to operate. | |
548 | */ | |
549 | setbits_le32(pctbenr, 0xff); | |
f6b96ff6 PJ |
550 | /* |
551 | * For LS2080A SoC and its personalities, timer controller | |
552 | * offset is different | |
553 | */ | |
554 | svr_dev_id = get_svr() >> 16; | |
555 | if (svr_dev_id == SVR_DEV_LS2080A) | |
556 | cntcr = (u32 *)SYS_FSL_LS2080A_LS2085A_TIMER_ADDR; | |
557 | ||
a758177f YC |
558 | #endif |
559 | ||
207774b2 YS |
560 | /* Enable clock for timer |
561 | * This is a global setting. | |
562 | */ | |
563 | out_le32(cntcr, 0x1); | |
564 | ||
565 | return 0; | |
566 | } | |
05d2e21b | 567 | |
78d57842 AG |
568 | __efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR; |
569 | ||
570 | void __efi_runtime reset_cpu(ulong addr) | |
05d2e21b | 571 | { |
05d2e21b | 572 | u32 val; |
573 | ||
574 | /* Raise RESET_REQ_B */ | |
9f3183d2 | 575 | val = scfg_in32(rstcr); |
05d2e21b | 576 | val |= 0x02; |
9f3183d2 | 577 | scfg_out32(rstcr, val); |
05d2e21b | 578 | } |
c0492141 | 579 | |
78d57842 AG |
580 | #ifdef CONFIG_EFI_LOADER |
581 | ||
582 | void __efi_runtime EFIAPI efi_reset_system( | |
583 | enum efi_reset_type reset_type, | |
584 | efi_status_t reset_status, | |
585 | unsigned long data_size, void *reset_data) | |
586 | { | |
587 | switch (reset_type) { | |
588 | case EFI_RESET_COLD: | |
589 | case EFI_RESET_WARM: | |
590 | reset_cpu(0); | |
591 | break; | |
592 | case EFI_RESET_SHUTDOWN: | |
593 | /* Nothing we can do */ | |
594 | break; | |
595 | } | |
596 | ||
597 | while (1) { } | |
598 | } | |
599 | ||
600 | void efi_reset_system_init(void) | |
601 | { | |
602 | efi_add_runtime_mmio(&rstcr, sizeof(*rstcr)); | |
603 | } | |
604 | ||
605 | #endif | |
606 | ||
c0492141 YS |
607 | phys_size_t board_reserve_ram_top(phys_size_t ram_size) |
608 | { | |
609 | phys_size_t ram_top = ram_size; | |
610 | ||
c0492141 | 611 | #ifdef CONFIG_FSL_MC_ENET |
36cc0de0 | 612 | /* The start address of MC reserved memory needs to be aligned. */ |
c0492141 YS |
613 | ram_top -= mc_get_dram_block_size(); |
614 | ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1); | |
615 | #endif | |
616 | ||
36cc0de0 YS |
617 | return ram_size - ram_top; |
618 | } | |
619 | ||
620 | phys_size_t get_effective_memsize(void) | |
621 | { | |
622 | phys_size_t ea_size, rem = 0; | |
623 | ||
624 | /* | |
625 | * For ARMv8 SoCs, DDR memory is split into two or three regions. The | |
626 | * first region is 2GB space at 0x8000_0000. If the memory extends to | |
627 | * the second region (or the third region if applicable), the secure | |
628 | * memory and Management Complex (MC) memory should be put into the | |
629 | * highest region, i.e. the end of DDR memory. CONFIG_MAX_MEM_MAPPED | |
630 | * is set to the size of first region so U-Boot doesn't relocate itself | |
631 | * into higher address. Should DDR be configured to skip the first | |
632 | * region, this function needs to be adjusted. | |
633 | */ | |
634 | if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) { | |
635 | ea_size = CONFIG_MAX_MEM_MAPPED; | |
636 | rem = gd->ram_size - ea_size; | |
637 | } else { | |
638 | ea_size = gd->ram_size; | |
639 | } | |
640 | ||
641 | #ifdef CONFIG_SYS_MEM_RESERVE_SECURE | |
642 | /* Check if we have enough space for secure memory */ | |
643 | if (rem > CONFIG_SYS_MEM_RESERVE_SECURE) { | |
644 | rem -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
645 | } else { | |
646 | if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE) { | |
647 | ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
648 | rem = 0; /* Presume MC requires more memory */ | |
649 | } else { | |
650 | printf("Error: No enough space for secure memory.\n"); | |
651 | } | |
652 | } | |
653 | #endif | |
654 | /* Check if we have enough memory for MC */ | |
655 | if (rem < board_reserve_ram_top(rem)) { | |
656 | /* Not enough memory in high region to reserve */ | |
657 | if (ea_size > board_reserve_ram_top(rem)) | |
658 | ea_size -= board_reserve_ram_top(rem); | |
659 | else | |
660 | printf("Error: No enough space for reserved memory.\n"); | |
661 | } | |
662 | ||
663 | return ea_size; | |
664 | } | |
665 | ||
666 | void dram_init_banksize(void) | |
667 | { | |
668 | #ifdef CONFIG_SYS_DP_DDR_BASE_PHY | |
669 | phys_size_t dp_ddr_size; | |
670 | #endif | |
671 | ||
672 | /* | |
673 | * gd->ram_size has the total size of DDR memory, less reserved secure | |
674 | * memory. The DDR extends from low region to high region(s) presuming | |
675 | * no hole is created with DDR configuration. gd->arch.secure_ram tracks | |
676 | * the location of secure memory. gd->arch.resv_ram tracks the location | |
677 | * of reserved memory for Management Complex (MC). | |
678 | */ | |
679 | gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; | |
680 | if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) { | |
681 | gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE; | |
682 | gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; | |
683 | gd->bd->bi_dram[1].size = gd->ram_size - | |
684 | CONFIG_SYS_DDR_BLOCK1_SIZE; | |
685 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
686 | if (gd->bi_dram[1].size > CONFIG_SYS_DDR_BLOCK2_SIZE) { | |
687 | gd->bd->bi_dram[2].start = CONFIG_SYS_DDR_BLOCK3_BASE; | |
688 | gd->bd->bi_dram[2].size = gd->bd->bi_dram[1].size - | |
689 | CONFIG_SYS_DDR_BLOCK2_SIZE; | |
690 | gd->bd->bi_dram[1].size = CONFIG_SYS_DDR_BLOCK2_SIZE; | |
691 | } | |
692 | #endif | |
693 | } else { | |
694 | gd->bd->bi_dram[0].size = gd->ram_size; | |
695 | } | |
696 | #ifdef CONFIG_SYS_MEM_RESERVE_SECURE | |
697 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
698 | if (gd->bd->bi_dram[2].size >= CONFIG_SYS_MEM_RESERVE_SECURE) { | |
699 | gd->bd->bi_dram[2].size -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
700 | gd->arch.secure_ram = gd->bd->bi_dram[2].start + | |
701 | gd->bd->bi_dram[2].size; | |
702 | gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; | |
703 | gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
704 | } else | |
705 | #endif | |
706 | { | |
707 | if (gd->bd->bi_dram[1].size >= CONFIG_SYS_MEM_RESERVE_SECURE) { | |
708 | gd->bd->bi_dram[1].size -= | |
709 | CONFIG_SYS_MEM_RESERVE_SECURE; | |
710 | gd->arch.secure_ram = gd->bd->bi_dram[1].start + | |
711 | gd->bd->bi_dram[1].size; | |
712 | gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; | |
713 | gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
714 | } else if (gd->bd->bi_dram[0].size > | |
715 | CONFIG_SYS_MEM_RESERVE_SECURE) { | |
716 | gd->bd->bi_dram[0].size -= | |
717 | CONFIG_SYS_MEM_RESERVE_SECURE; | |
718 | gd->arch.secure_ram = gd->bd->bi_dram[0].start + | |
719 | gd->bd->bi_dram[0].size; | |
720 | gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; | |
721 | gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; | |
722 | } | |
723 | } | |
724 | #endif /* CONFIG_SYS_MEM_RESERVE_SECURE */ | |
725 | ||
726 | #ifdef CONFIG_FSL_MC_ENET | |
727 | /* Assign memory for MC */ | |
728 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
729 | if (gd->bd->bi_dram[2].size >= | |
730 | board_reserve_ram_top(gd->bd->bi_dram[2].size)) { | |
731 | gd->arch.resv_ram = gd->bd->bi_dram[2].start + | |
732 | gd->bd->bi_dram[2].size - | |
733 | board_reserve_ram_top(gd->bd->bi_dram[2].size); | |
734 | } else | |
735 | #endif | |
736 | { | |
737 | if (gd->bd->bi_dram[1].size >= | |
738 | board_reserve_ram_top(gd->bd->bi_dram[1].size)) { | |
739 | gd->arch.resv_ram = gd->bd->bi_dram[1].start + | |
740 | gd->bd->bi_dram[1].size - | |
741 | board_reserve_ram_top(gd->bd->bi_dram[1].size); | |
742 | } else if (gd->bd->bi_dram[0].size > | |
743 | board_reserve_ram_top(gd->bd->bi_dram[0].size)) { | |
744 | gd->arch.resv_ram = gd->bd->bi_dram[0].start + | |
745 | gd->bd->bi_dram[0].size - | |
746 | board_reserve_ram_top(gd->bd->bi_dram[0].size); | |
747 | } | |
748 | } | |
749 | #endif /* CONFIG_FSL_MC_ENET */ | |
750 | ||
751 | #ifdef CONFIG_SYS_DP_DDR_BASE_PHY | |
752 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
753 | #error "This SoC shouldn't have DP DDR" | |
754 | #endif | |
755 | if (soc_has_dp_ddr()) { | |
756 | /* initialize DP-DDR here */ | |
757 | puts("DP-DDR: "); | |
758 | /* | |
759 | * DDR controller use 0 as the base address for binding. | |
760 | * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access. | |
761 | */ | |
762 | dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY, | |
763 | CONFIG_DP_DDR_CTRL, | |
764 | CONFIG_DP_DDR_NUM_CTRLS, | |
765 | CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR, | |
766 | NULL, NULL, NULL); | |
767 | if (dp_ddr_size) { | |
768 | gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE; | |
769 | gd->bd->bi_dram[2].size = dp_ddr_size; | |
770 | } else { | |
771 | puts("Not detected"); | |
772 | } | |
773 | } | |
774 | #endif | |
775 | } | |
776 | ||
777 | #if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD) | |
778 | void efi_add_known_memory(void) | |
779 | { | |
780 | int i; | |
781 | phys_addr_t ram_start, start; | |
782 | phys_size_t ram_size; | |
783 | u64 pages; | |
784 | ||
785 | /* Add RAM */ | |
786 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
787 | #ifdef CONFIG_SYS_DP_DDR_BASE_PHY | |
788 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
789 | #error "This SoC shouldn't have DP DDR" | |
790 | #endif | |
791 | if (i == 2) | |
792 | continue; /* skip DP-DDR */ | |
793 | #endif | |
794 | ram_start = gd->bd->bi_dram[i].start; | |
795 | ram_size = gd->bd->bi_dram[i].size; | |
796 | #ifdef CONFIG_RESV_RAM | |
797 | if (gd->arch.resv_ram >= ram_start && | |
798 | gd->arch.resv_ram < ram_start + ram_size) | |
799 | ram_size = gd->arch.resv_ram - ram_start; | |
800 | #endif | |
801 | start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; | |
802 | pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; | |
803 | ||
804 | efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY, | |
805 | false); | |
806 | } | |
c0492141 | 807 | } |
36cc0de0 | 808 | #endif |
4961eafc YS |
809 | |
810 | /* | |
811 | * Before DDR size is known, early MMU table have DDR mapped as device memory | |
812 | * to avoid speculative access. To relocate U-Boot to DDR, "normal memory" | |
813 | * needs to be set for these mappings. | |
814 | * If a special case configures DDR with holes in the mapping, the holes need | |
815 | * to be marked as invalid. This is not implemented in this function. | |
816 | */ | |
817 | void update_early_mmu_table(void) | |
818 | { | |
819 | if (!gd->arch.tlb_addr) | |
820 | return; | |
821 | ||
822 | if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) { | |
823 | mmu_change_region_attr( | |
824 | CONFIG_SYS_SDRAM_BASE, | |
825 | gd->ram_size, | |
826 | PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
827 | PTE_BLOCK_OUTER_SHARE | | |
828 | PTE_BLOCK_NS | | |
829 | PTE_TYPE_VALID); | |
830 | } else { | |
831 | mmu_change_region_attr( | |
832 | CONFIG_SYS_SDRAM_BASE, | |
833 | CONFIG_SYS_DDR_BLOCK1_SIZE, | |
834 | PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
835 | PTE_BLOCK_OUTER_SHARE | | |
836 | PTE_BLOCK_NS | | |
837 | PTE_TYPE_VALID); | |
838 | #ifdef CONFIG_SYS_DDR_BLOCK3_BASE | |
839 | #ifndef CONFIG_SYS_DDR_BLOCK2_SIZE | |
840 | #error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE" | |
841 | #endif | |
842 | if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE > | |
843 | CONFIG_SYS_DDR_BLOCK2_SIZE) { | |
844 | mmu_change_region_attr( | |
845 | CONFIG_SYS_DDR_BLOCK2_BASE, | |
846 | CONFIG_SYS_DDR_BLOCK2_SIZE, | |
847 | PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
848 | PTE_BLOCK_OUTER_SHARE | | |
849 | PTE_BLOCK_NS | | |
850 | PTE_TYPE_VALID); | |
851 | mmu_change_region_attr( | |
852 | CONFIG_SYS_DDR_BLOCK3_BASE, | |
853 | gd->ram_size - | |
854 | CONFIG_SYS_DDR_BLOCK1_SIZE - | |
855 | CONFIG_SYS_DDR_BLOCK2_SIZE, | |
856 | PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
857 | PTE_BLOCK_OUTER_SHARE | | |
858 | PTE_BLOCK_NS | | |
859 | PTE_TYPE_VALID); | |
860 | } else | |
861 | #endif | |
862 | { | |
863 | mmu_change_region_attr( | |
864 | CONFIG_SYS_DDR_BLOCK2_BASE, | |
865 | gd->ram_size - | |
866 | CONFIG_SYS_DDR_BLOCK1_SIZE, | |
867 | PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
868 | PTE_BLOCK_OUTER_SHARE | | |
869 | PTE_BLOCK_NS | | |
870 | PTE_TYPE_VALID); | |
871 | } | |
872 | } | |
873 | } | |
874 | ||
875 | __weak int dram_init(void) | |
876 | { | |
088454cd | 877 | initdram(); |
4961eafc YS |
878 | #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) |
879 | /* This will break-before-make MMU for DDR */ | |
880 | update_early_mmu_table(); | |
881 | #endif | |
882 | ||
883 | return 0; | |
884 | } |