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