xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv8/fsl-layerscape/cpu.c (revision 1a4f6af8bfd44c8ae6e87a81ff125eed47042cc5)
19f3183d2SMingkai Hu /*
2e809e747SPriyanka Jain  * Copyright 2017 NXP
39f3183d2SMingkai Hu  * Copyright 2014-2015 Freescale Semiconductor, Inc.
49f3183d2SMingkai Hu  *
59f3183d2SMingkai Hu  * SPDX-License-Identifier:	GPL-2.0+
69f3183d2SMingkai Hu  */
79f3183d2SMingkai Hu 
89f3183d2SMingkai Hu #include <common.h>
93eace37eSSimon Glass #include <fsl_ddr_sdram.h>
109f3183d2SMingkai Hu #include <asm/io.h>
111221ce45SMasahiro Yamada #include <linux/errno.h>
129f3183d2SMingkai Hu #include <asm/system.h>
139f3183d2SMingkai Hu #include <asm/armv8/mmu.h>
149f3183d2SMingkai Hu #include <asm/io.h>
159f3183d2SMingkai Hu #include <asm/arch/fsl_serdes.h>
169f3183d2SMingkai Hu #include <asm/arch/soc.h>
179f3183d2SMingkai Hu #include <asm/arch/cpu.h>
189f3183d2SMingkai Hu #include <asm/arch/speed.h>
199f3183d2SMingkai Hu #include <asm/arch/mp.h>
2078d57842SAlexander Graf #include <efi_loader.h>
219f3183d2SMingkai Hu #include <fm_eth.h>
229f3183d2SMingkai Hu #include <fsl-mc/fsl_mc.h>
239f3183d2SMingkai Hu #ifdef CONFIG_FSL_ESDHC
249f3183d2SMingkai Hu #include <fsl_esdhc.h>
259f3183d2SMingkai Hu #endif
26032d5bb4SHou Zhiqiang #include <asm/armv8/sec_firmware.h>
2702fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_DDR
2802fb2761SShengzhou Liu #include <fsl_ddr.h>
2902fb2761SShengzhou Liu #endif
306e2941d7SSimon Glass #include <asm/arch/clock.h>
319f3183d2SMingkai Hu 
329f3183d2SMingkai Hu DECLARE_GLOBAL_DATA_PTR;
339f3183d2SMingkai Hu 
345ad5823dSYork Sun struct mm_region *mem_map = early_map;
357985cdf7SAlexander Graf 
cpu_name(char * name)369f3183d2SMingkai Hu void cpu_name(char *name)
379f3183d2SMingkai Hu {
389f3183d2SMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
399f3183d2SMingkai Hu 	unsigned int i, svr, ver;
409f3183d2SMingkai Hu 
419f3183d2SMingkai Hu 	svr = gur_in32(&gur->svr);
429f3183d2SMingkai Hu 	ver = SVR_SOC_VER(svr);
439f3183d2SMingkai Hu 
449f3183d2SMingkai Hu 	for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
459f3183d2SMingkai Hu 		if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) {
469f3183d2SMingkai Hu 			strcpy(name, cpu_type_list[i].name);
479f3183d2SMingkai Hu 
489f3183d2SMingkai Hu 			if (IS_E_PROCESSOR(svr))
499f3183d2SMingkai Hu 				strcat(name, "E");
505d1a7a9dSWenbin Song 
515d1a7a9dSWenbin Song 			sprintf(name + strlen(name), " Rev%d.%d",
525d1a7a9dSWenbin Song 				SVR_MAJ(svr), SVR_MIN(svr));
539f3183d2SMingkai Hu 			break;
549f3183d2SMingkai Hu 		}
559f3183d2SMingkai Hu 
569f3183d2SMingkai Hu 	if (i == ARRAY_SIZE(cpu_type_list))
579f3183d2SMingkai Hu 		strcpy(name, "unknown");
589f3183d2SMingkai Hu }
599f3183d2SMingkai Hu 
609f3183d2SMingkai Hu #ifndef CONFIG_SYS_DCACHE_OFF
619f3183d2SMingkai Hu /*
629f3183d2SMingkai Hu  * To start MMU before DDR is available, we create MMU table in SRAM.
639f3183d2SMingkai Hu  * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three
649f3183d2SMingkai Hu  * levels of translation tables here to cover 40-bit address space.
659f3183d2SMingkai Hu  * We use 4KB granule size, with 40 bits physical address, T0SZ=24
665ad5823dSYork Sun  * Address above EARLY_PGTABLE_SIZE (0x5000) is free for other purpose.
675ad5823dSYork Sun  * Note, the debug print in cache_v8.c is not usable for debugging
685ad5823dSYork Sun  * these early MMU tables because UART is not yet available.
699f3183d2SMingkai Hu  */
early_mmu_setup(void)709f3183d2SMingkai Hu static inline void early_mmu_setup(void)
719f3183d2SMingkai Hu {
725ad5823dSYork Sun 	unsigned int el = current_el();
739f3183d2SMingkai Hu 
745ad5823dSYork Sun 	/* global data is already setup, no allocation yet */
755ad5823dSYork Sun 	gd->arch.tlb_addr = CONFIG_SYS_FSL_OCRAM_BASE;
765ad5823dSYork Sun 	gd->arch.tlb_fillptr = gd->arch.tlb_addr;
775ad5823dSYork Sun 	gd->arch.tlb_size = EARLY_PGTABLE_SIZE;
789f3183d2SMingkai Hu 
795ad5823dSYork Sun 	/* Create early page tables */
805ad5823dSYork Sun 	setup_pgtables();
819f3183d2SMingkai Hu 
825ad5823dSYork Sun 	/* point TTBR to the new table */
835ad5823dSYork Sun 	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
845ad5823dSYork Sun 			  get_tcr(el, NULL, NULL) &
855ad5823dSYork Sun 			  ~(TCR_ORGN_MASK | TCR_IRGN_MASK),
869f3183d2SMingkai Hu 			  MEMORY_ATTRIBUTES);
875ad5823dSYork Sun 
889f3183d2SMingkai Hu 	set_sctlr(get_sctlr() | CR_M);
899f3183d2SMingkai Hu }
909f3183d2SMingkai Hu 
fix_pcie_mmu_map(void)913d8553f0SHou Zhiqiang static void fix_pcie_mmu_map(void)
923d8553f0SHou Zhiqiang {
934a3ab193SYork Sun #ifdef CONFIG_ARCH_LS2080A
943d8553f0SHou Zhiqiang 	unsigned int i;
953d8553f0SHou Zhiqiang 	u32 svr, ver;
963d8553f0SHou Zhiqiang 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
973d8553f0SHou Zhiqiang 
983d8553f0SHou Zhiqiang 	svr = gur_in32(&gur->svr);
993d8553f0SHou Zhiqiang 	ver = SVR_SOC_VER(svr);
1003d8553f0SHou Zhiqiang 
1013d8553f0SHou Zhiqiang 	/* Fix PCIE base and size for LS2088A */
1023d8553f0SHou Zhiqiang 	if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) ||
103e809e747SPriyanka Jain 	    (ver == SVR_LS2048A) || (ver == SVR_LS2044A) ||
104e809e747SPriyanka Jain 	    (ver == SVR_LS2081A) || (ver == SVR_LS2041A)) {
1053d8553f0SHou Zhiqiang 		for (i = 0; i < ARRAY_SIZE(final_map); i++) {
1063d8553f0SHou Zhiqiang 			switch (final_map[i].phys) {
1073d8553f0SHou Zhiqiang 			case CONFIG_SYS_PCIE1_PHYS_ADDR:
1083d8553f0SHou Zhiqiang 				final_map[i].phys = 0x2000000000ULL;
1093d8553f0SHou Zhiqiang 				final_map[i].virt = 0x2000000000ULL;
1103d8553f0SHou Zhiqiang 				final_map[i].size = 0x800000000ULL;
1113d8553f0SHou Zhiqiang 				break;
1123d8553f0SHou Zhiqiang 			case CONFIG_SYS_PCIE2_PHYS_ADDR:
1133d8553f0SHou Zhiqiang 				final_map[i].phys = 0x2800000000ULL;
1143d8553f0SHou Zhiqiang 				final_map[i].virt = 0x2800000000ULL;
1153d8553f0SHou Zhiqiang 				final_map[i].size = 0x800000000ULL;
1163d8553f0SHou Zhiqiang 				break;
1173d8553f0SHou Zhiqiang 			case CONFIG_SYS_PCIE3_PHYS_ADDR:
1183d8553f0SHou Zhiqiang 				final_map[i].phys = 0x3000000000ULL;
1193d8553f0SHou Zhiqiang 				final_map[i].virt = 0x3000000000ULL;
1203d8553f0SHou Zhiqiang 				final_map[i].size = 0x800000000ULL;
1213d8553f0SHou Zhiqiang 				break;
1223d8553f0SHou Zhiqiang 			case CONFIG_SYS_PCIE4_PHYS_ADDR:
1233d8553f0SHou Zhiqiang 				final_map[i].phys = 0x3800000000ULL;
1243d8553f0SHou Zhiqiang 				final_map[i].virt = 0x3800000000ULL;
1253d8553f0SHou Zhiqiang 				final_map[i].size = 0x800000000ULL;
1263d8553f0SHou Zhiqiang 				break;
1273d8553f0SHou Zhiqiang 			default:
1283d8553f0SHou Zhiqiang 				break;
1293d8553f0SHou Zhiqiang 			}
1303d8553f0SHou Zhiqiang 		}
1313d8553f0SHou Zhiqiang 	}
1323d8553f0SHou Zhiqiang #endif
1333d8553f0SHou Zhiqiang }
1343d8553f0SHou Zhiqiang 
1359f3183d2SMingkai Hu /*
1369f3183d2SMingkai Hu  * The final tables look similar to early tables, but different in detail.
1379f3183d2SMingkai Hu  * These tables are in DRAM. Sub tables are added to enable cache for
1389f3183d2SMingkai Hu  * QBMan and OCRAM.
1399f3183d2SMingkai Hu  *
140e61a7534SYork Sun  * Put the MMU table in secure memory if gd->arch.secure_ram is valid.
141e61a7534SYork Sun  * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0.
1429f3183d2SMingkai Hu  */
final_mmu_setup(void)1439f3183d2SMingkai Hu static inline void final_mmu_setup(void)
1449f3183d2SMingkai Hu {
1455ad5823dSYork Sun 	u64 tlb_addr_save = gd->arch.tlb_addr;
146c107c0c0SYork Sun 	unsigned int el = current_el();
1475ad5823dSYork Sun 	int index;
1485ad5823dSYork Sun 
1493d8553f0SHou Zhiqiang 	/* fix the final_map before filling in the block entries */
1503d8553f0SHou Zhiqiang 	fix_pcie_mmu_map();
1513d8553f0SHou Zhiqiang 
1525ad5823dSYork Sun 	mem_map = final_map;
153c107c0c0SYork Sun 
15424f55496SYork Sun 	/* Update mapping for DDR to actual size */
15524f55496SYork Sun 	for (index = 0; index < ARRAY_SIZE(final_map) - 2; index++) {
15624f55496SYork Sun 		/*
15724f55496SYork Sun 		 * Find the entry for DDR mapping and update the address and
15824f55496SYork Sun 		 * size. Zero-sized mapping will be skipped when creating MMU
15924f55496SYork Sun 		 * table.
16024f55496SYork Sun 		 */
16124f55496SYork Sun 		switch (final_map[index].virt) {
16224f55496SYork Sun 		case CONFIG_SYS_FSL_DRAM_BASE1:
16324f55496SYork Sun 			final_map[index].virt = gd->bd->bi_dram[0].start;
16424f55496SYork Sun 			final_map[index].phys = gd->bd->bi_dram[0].start;
16524f55496SYork Sun 			final_map[index].size = gd->bd->bi_dram[0].size;
16624f55496SYork Sun 			break;
16724f55496SYork Sun #ifdef CONFIG_SYS_FSL_DRAM_BASE2
16824f55496SYork Sun 		case CONFIG_SYS_FSL_DRAM_BASE2:
16924f55496SYork Sun #if (CONFIG_NR_DRAM_BANKS >= 2)
17024f55496SYork Sun 			final_map[index].virt = gd->bd->bi_dram[1].start;
17124f55496SYork Sun 			final_map[index].phys = gd->bd->bi_dram[1].start;
17224f55496SYork Sun 			final_map[index].size = gd->bd->bi_dram[1].size;
17324f55496SYork Sun #else
17424f55496SYork Sun 			final_map[index].size = 0;
17524f55496SYork Sun #endif
17624f55496SYork Sun 		break;
17724f55496SYork Sun #endif
17824f55496SYork Sun #ifdef CONFIG_SYS_FSL_DRAM_BASE3
17924f55496SYork Sun 		case CONFIG_SYS_FSL_DRAM_BASE3:
18024f55496SYork Sun #if (CONFIG_NR_DRAM_BANKS >= 3)
18124f55496SYork Sun 			final_map[index].virt = gd->bd->bi_dram[2].start;
18224f55496SYork Sun 			final_map[index].phys = gd->bd->bi_dram[2].start;
18324f55496SYork Sun 			final_map[index].size = gd->bd->bi_dram[2].size;
18424f55496SYork Sun #else
18524f55496SYork Sun 			final_map[index].size = 0;
18624f55496SYork Sun #endif
18724f55496SYork Sun 		break;
18824f55496SYork Sun #endif
18924f55496SYork Sun 		default:
19024f55496SYork Sun 			break;
19124f55496SYork Sun 		}
19224f55496SYork Sun 	}
19324f55496SYork Sun 
194c107c0c0SYork Sun #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
1955ad5823dSYork Sun 	if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
196c107c0c0SYork Sun 		if (el == 3) {
197c107c0c0SYork Sun 			/*
1985ad5823dSYork Sun 			 * Only use gd->arch.secure_ram if the address is
1995ad5823dSYork Sun 			 * recalculated. Align to 4KB for MMU table.
200c107c0c0SYork Sun 			 */
2015ad5823dSYork Sun 			/* put page tables in secure ram */
2025ad5823dSYork Sun 			index = ARRAY_SIZE(final_map) - 2;
2035ad5823dSYork Sun 			gd->arch.tlb_addr = gd->arch.secure_ram & ~0xfff;
2045ad5823dSYork Sun 			final_map[index].virt = gd->arch.secure_ram & ~0x3;
2055ad5823dSYork Sun 			final_map[index].phys = final_map[index].virt;
2065ad5823dSYork Sun 			final_map[index].size = CONFIG_SYS_MEM_RESERVE_SECURE;
2075ad5823dSYork Sun 			final_map[index].attrs = PTE_BLOCK_OUTER_SHARE;
208e61a7534SYork Sun 			gd->arch.secure_ram |= MEM_RESERVE_SECURE_SECURED;
2095ad5823dSYork Sun 			tlb_addr_save = gd->arch.tlb_addr;
210c107c0c0SYork Sun 		} else {
2115ad5823dSYork Sun 			/* Use allocated (board_f.c) memory for TLB */
2125ad5823dSYork Sun 			tlb_addr_save = gd->arch.tlb_allocated;
2135ad5823dSYork Sun 			gd->arch.tlb_addr = tlb_addr_save;
214c107c0c0SYork Sun 		}
215c107c0c0SYork Sun 	}
216c107c0c0SYork Sun #endif
2179f3183d2SMingkai Hu 
2185ad5823dSYork Sun 	/* Reset the fill ptr */
2195ad5823dSYork Sun 	gd->arch.tlb_fillptr = tlb_addr_save;
2205ad5823dSYork Sun 
2215ad5823dSYork Sun 	/* Create normal system page tables */
2225ad5823dSYork Sun 	setup_pgtables();
2235ad5823dSYork Sun 
2245ad5823dSYork Sun 	/* Create emergency page tables */
2255ad5823dSYork Sun 	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
2265ad5823dSYork Sun 	gd->arch.tlb_emerg = gd->arch.tlb_addr;
2275ad5823dSYork Sun 	setup_pgtables();
2285ad5823dSYork Sun 	gd->arch.tlb_addr = tlb_addr_save;
2295ad5823dSYork Sun 
230a045a0c3SYork Sun 	/* Disable cache and MMU */
231a045a0c3SYork Sun 	dcache_disable();	/* TLBs are invalidated */
232a045a0c3SYork Sun 	invalidate_icache_all();
2339f3183d2SMingkai Hu 
2349f3183d2SMingkai Hu 	/* point TTBR to the new table */
2355ad5823dSYork Sun 	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
2369f3183d2SMingkai Hu 			  MEMORY_ATTRIBUTES);
237a045a0c3SYork Sun 
238ed7a3943SYork Sun 	set_sctlr(get_sctlr() | CR_M);
2399f3183d2SMingkai Hu }
2409f3183d2SMingkai Hu 
get_page_table_size(void)241c05016abSAlexander Graf u64 get_page_table_size(void)
242c05016abSAlexander Graf {
243c05016abSAlexander Graf 	return 0x10000;
244c05016abSAlexander Graf }
245c05016abSAlexander Graf 
arch_cpu_init(void)2469f3183d2SMingkai Hu int arch_cpu_init(void)
2479f3183d2SMingkai Hu {
248399e2bb6SYork Sun 	/*
249399e2bb6SYork Sun 	 * This function is called before U-Boot relocates itself to speed up
250399e2bb6SYork Sun 	 * on system running. It is not necessary to run if performance is not
251399e2bb6SYork Sun 	 * critical. Skip if MMU is already enabled by SPL or other means.
252399e2bb6SYork Sun 	 */
253399e2bb6SYork Sun 	if (get_sctlr() & CR_M)
254399e2bb6SYork Sun 		return 0;
255399e2bb6SYork Sun 
2569f3183d2SMingkai Hu 	icache_enable();
2579f3183d2SMingkai Hu 	__asm_invalidate_dcache_all();
2589f3183d2SMingkai Hu 	__asm_invalidate_tlb_all();
2599f3183d2SMingkai Hu 	early_mmu_setup();
2609f3183d2SMingkai Hu 	set_sctlr(get_sctlr() | CR_C);
2619f3183d2SMingkai Hu 	return 0;
2629f3183d2SMingkai Hu }
2639f3183d2SMingkai Hu 
mmu_setup(void)26485cdf38eSHou Zhiqiang void mmu_setup(void)
26585cdf38eSHou Zhiqiang {
26685cdf38eSHou Zhiqiang 	final_mmu_setup();
26785cdf38eSHou Zhiqiang }
26885cdf38eSHou Zhiqiang 
2699f3183d2SMingkai Hu /*
27085cdf38eSHou Zhiqiang  * This function is called from common/board_r.c.
27185cdf38eSHou Zhiqiang  * It recreates MMU table in main memory.
2729f3183d2SMingkai Hu  */
enable_caches(void)2739f3183d2SMingkai Hu void enable_caches(void)
2749f3183d2SMingkai Hu {
27585cdf38eSHou Zhiqiang 	mmu_setup();
2769f3183d2SMingkai Hu 	__asm_invalidate_tlb_all();
27785cdf38eSHou Zhiqiang 	icache_enable();
27885cdf38eSHou Zhiqiang 	dcache_enable();
2799f3183d2SMingkai Hu }
2809f3183d2SMingkai Hu #endif
2819f3183d2SMingkai Hu 
initiator_type(u32 cluster,int init_id)282e87c673cSPriyanka Jain u32 initiator_type(u32 cluster, int init_id)
2839f3183d2SMingkai Hu {
2849f3183d2SMingkai Hu 	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
2859f3183d2SMingkai Hu 	u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK;
2869f3183d2SMingkai Hu 	u32 type = 0;
2879f3183d2SMingkai Hu 
2889f3183d2SMingkai Hu 	type = gur_in32(&gur->tp_ityp[idx]);
2899f3183d2SMingkai Hu 	if (type & TP_ITYP_AV)
2909f3183d2SMingkai Hu 		return type;
2919f3183d2SMingkai Hu 
2929f3183d2SMingkai Hu 	return 0;
2939f3183d2SMingkai Hu }
2949f3183d2SMingkai Hu 
cpu_pos_mask(void)295ef9a5fd8SYork Sun u32 cpu_pos_mask(void)
296ef9a5fd8SYork Sun {
297ef9a5fd8SYork Sun 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
298ef9a5fd8SYork Sun 	int i = 0;
299ef9a5fd8SYork Sun 	u32 cluster, type, mask = 0;
300ef9a5fd8SYork Sun 
301ef9a5fd8SYork Sun 	do {
302ef9a5fd8SYork Sun 		int j;
303ef9a5fd8SYork Sun 
304ef9a5fd8SYork Sun 		cluster = gur_in32(&gur->tp_cluster[i].lower);
305ef9a5fd8SYork Sun 		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
306ef9a5fd8SYork Sun 			type = initiator_type(cluster, j);
307ef9a5fd8SYork Sun 			if (type && (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM))
308ef9a5fd8SYork Sun 				mask |= 1 << (i * TP_INIT_PER_CLUSTER + j);
309ef9a5fd8SYork Sun 		}
310ef9a5fd8SYork Sun 		i++;
311ef9a5fd8SYork Sun 	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
312ef9a5fd8SYork Sun 
313ef9a5fd8SYork Sun 	return mask;
314ef9a5fd8SYork Sun }
315ef9a5fd8SYork Sun 
cpu_mask(void)3169f3183d2SMingkai Hu u32 cpu_mask(void)
3179f3183d2SMingkai Hu {
3189f3183d2SMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
3199f3183d2SMingkai Hu 	int i = 0, count = 0;
3209f3183d2SMingkai Hu 	u32 cluster, type, mask = 0;
3219f3183d2SMingkai Hu 
3229f3183d2SMingkai Hu 	do {
3239f3183d2SMingkai Hu 		int j;
3249f3183d2SMingkai Hu 
3259f3183d2SMingkai Hu 		cluster = gur_in32(&gur->tp_cluster[i].lower);
3269f3183d2SMingkai Hu 		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
3279f3183d2SMingkai Hu 			type = initiator_type(cluster, j);
3289f3183d2SMingkai Hu 			if (type) {
3299f3183d2SMingkai Hu 				if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
3309f3183d2SMingkai Hu 					mask |= 1 << count;
3319f3183d2SMingkai Hu 				count++;
3329f3183d2SMingkai Hu 			}
3339f3183d2SMingkai Hu 		}
3349f3183d2SMingkai Hu 		i++;
3359f3183d2SMingkai Hu 	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
3369f3183d2SMingkai Hu 
3379f3183d2SMingkai Hu 	return mask;
3389f3183d2SMingkai Hu }
3399f3183d2SMingkai Hu 
3409f3183d2SMingkai Hu /*
3419f3183d2SMingkai Hu  * Return the number of cores on this SOC.
3429f3183d2SMingkai Hu  */
cpu_numcores(void)3439f3183d2SMingkai Hu int cpu_numcores(void)
3449f3183d2SMingkai Hu {
3459f3183d2SMingkai Hu 	return hweight32(cpu_mask());
3469f3183d2SMingkai Hu }
3479f3183d2SMingkai Hu 
fsl_qoriq_core_to_cluster(unsigned int core)3489f3183d2SMingkai Hu int fsl_qoriq_core_to_cluster(unsigned int core)
3499f3183d2SMingkai Hu {
3509f3183d2SMingkai Hu 	struct ccsr_gur __iomem *gur =
3519f3183d2SMingkai Hu 		(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
3529f3183d2SMingkai Hu 	int i = 0, count = 0;
3539f3183d2SMingkai Hu 	u32 cluster;
3549f3183d2SMingkai Hu 
3559f3183d2SMingkai Hu 	do {
3569f3183d2SMingkai Hu 		int j;
3579f3183d2SMingkai Hu 
3589f3183d2SMingkai Hu 		cluster = gur_in32(&gur->tp_cluster[i].lower);
3599f3183d2SMingkai Hu 		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
3609f3183d2SMingkai Hu 			if (initiator_type(cluster, j)) {
3619f3183d2SMingkai Hu 				if (count == core)
3629f3183d2SMingkai Hu 					return i;
3639f3183d2SMingkai Hu 				count++;
3649f3183d2SMingkai Hu 			}
3659f3183d2SMingkai Hu 		}
3669f3183d2SMingkai Hu 		i++;
3679f3183d2SMingkai Hu 	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
3689f3183d2SMingkai Hu 
3699f3183d2SMingkai Hu 	return -1;      /* cannot identify the cluster */
3709f3183d2SMingkai Hu }
3719f3183d2SMingkai Hu 
fsl_qoriq_core_to_type(unsigned int core)3729f3183d2SMingkai Hu u32 fsl_qoriq_core_to_type(unsigned int core)
3739f3183d2SMingkai Hu {
3749f3183d2SMingkai Hu 	struct ccsr_gur __iomem *gur =
3759f3183d2SMingkai Hu 		(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
3769f3183d2SMingkai Hu 	int i = 0, count = 0;
3779f3183d2SMingkai Hu 	u32 cluster, type;
3789f3183d2SMingkai Hu 
3799f3183d2SMingkai Hu 	do {
3809f3183d2SMingkai Hu 		int j;
3819f3183d2SMingkai Hu 
3829f3183d2SMingkai Hu 		cluster = gur_in32(&gur->tp_cluster[i].lower);
3839f3183d2SMingkai Hu 		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
3849f3183d2SMingkai Hu 			type = initiator_type(cluster, j);
3859f3183d2SMingkai Hu 			if (type) {
3869f3183d2SMingkai Hu 				if (count == core)
3879f3183d2SMingkai Hu 					return type;
3889f3183d2SMingkai Hu 				count++;
3899f3183d2SMingkai Hu 			}
3909f3183d2SMingkai Hu 		}
3919f3183d2SMingkai Hu 		i++;
3929f3183d2SMingkai Hu 	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
3939f3183d2SMingkai Hu 
3949f3183d2SMingkai Hu 	return -1;      /* cannot identify the cluster */
3959f3183d2SMingkai Hu }
3969f3183d2SMingkai Hu 
397f6a70b3aSPriyanka Jain #ifndef CONFIG_FSL_LSCH3
get_svr(void)3986fb522dcSSriram Dash uint get_svr(void)
3996fb522dcSSriram Dash {
4006fb522dcSSriram Dash 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
4016fb522dcSSriram Dash 
4026fb522dcSSriram Dash 	return gur_in32(&gur->svr);
4036fb522dcSSriram Dash }
404f6a70b3aSPriyanka Jain #endif
4056fb522dcSSriram Dash 
4069f3183d2SMingkai Hu #ifdef CONFIG_DISPLAY_CPUINFO
print_cpuinfo(void)4079f3183d2SMingkai Hu int print_cpuinfo(void)
4089f3183d2SMingkai Hu {
4099f3183d2SMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
4109f3183d2SMingkai Hu 	struct sys_info sysinfo;
4119f3183d2SMingkai Hu 	char buf[32];
4129f3183d2SMingkai Hu 	unsigned int i, core;
4133c1d218aSYork Sun 	u32 type, rcw, svr = gur_in32(&gur->svr);
4149f3183d2SMingkai Hu 
4159f3183d2SMingkai Hu 	puts("SoC: ");
4169f3183d2SMingkai Hu 
4179f3183d2SMingkai Hu 	cpu_name(buf);
4183c1d218aSYork Sun 	printf(" %s (0x%x)\n", buf, svr);
4199f3183d2SMingkai Hu 	memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
4209f3183d2SMingkai Hu 	get_sys_info(&sysinfo);
4219f3183d2SMingkai Hu 	puts("Clock Configuration:");
4229f3183d2SMingkai Hu 	for_each_cpu(i, core, cpu_numcores(), cpu_mask()) {
4239f3183d2SMingkai Hu 		if (!(i % 3))
4249f3183d2SMingkai Hu 			puts("\n       ");
4259f3183d2SMingkai Hu 		type = TP_ITYP_VER(fsl_qoriq_core_to_type(core));
4269f3183d2SMingkai Hu 		printf("CPU%d(%s):%-4s MHz  ", core,
4279f3183d2SMingkai Hu 		       type == TY_ITYP_VER_A7 ? "A7 " :
4289f3183d2SMingkai Hu 		       (type == TY_ITYP_VER_A53 ? "A53" :
42979119a4dSAlison Wang 		       (type == TY_ITYP_VER_A57 ? "A57" :
43079119a4dSAlison Wang 		       (type == TY_ITYP_VER_A72 ? "A72" : "   "))),
4319f3183d2SMingkai Hu 		       strmhz(buf, sysinfo.freq_processor[core]));
4329f3183d2SMingkai Hu 	}
433904110c7SHou Zhiqiang 	/* Display platform clock as Bus frequency. */
4349f3183d2SMingkai Hu 	printf("\n       Bus:      %-4s MHz  ",
435904110c7SHou Zhiqiang 	       strmhz(buf, sysinfo.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV));
4369f3183d2SMingkai Hu 	printf("DDR:      %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus));
437e8297341SShaohui Xie #ifdef CONFIG_SYS_DPAA_FMAN
438e8297341SShaohui Xie 	printf("  FMAN:     %-4s MHz", strmhz(buf, sysinfo.freq_fman[0]));
439e8297341SShaohui Xie #endif
44044937214SPrabhakar Kushwaha #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
4413c1d218aSYork Sun 	if (soc_has_dp_ddr()) {
4423c1d218aSYork Sun 		printf("     DP-DDR:   %-4s MT/s",
4433c1d218aSYork Sun 		       strmhz(buf, sysinfo.freq_ddrbus2));
4443c1d218aSYork Sun 	}
4459f3183d2SMingkai Hu #endif
4469f3183d2SMingkai Hu 	puts("\n");
4479f3183d2SMingkai Hu 
4489f3183d2SMingkai Hu 	/*
4499f3183d2SMingkai Hu 	 * Display the RCW, so that no one gets confused as to what RCW
4509f3183d2SMingkai Hu 	 * we're actually using for this boot.
4519f3183d2SMingkai Hu 	 */
4529f3183d2SMingkai Hu 	puts("Reset Configuration Word (RCW):");
4539f3183d2SMingkai Hu 	for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) {
4549f3183d2SMingkai Hu 		rcw = gur_in32(&gur->rcwsr[i]);
4559f3183d2SMingkai Hu 		if ((i % 4) == 0)
4569f3183d2SMingkai Hu 			printf("\n       %08x:", i * 4);
4579f3183d2SMingkai Hu 		printf(" %08x", rcw);
4589f3183d2SMingkai Hu 	}
4599f3183d2SMingkai Hu 	puts("\n");
4609f3183d2SMingkai Hu 
4619f3183d2SMingkai Hu 	return 0;
4629f3183d2SMingkai Hu }
4639f3183d2SMingkai Hu #endif
4649f3183d2SMingkai Hu 
4659f3183d2SMingkai Hu #ifdef CONFIG_FSL_ESDHC
cpu_mmc_init(bd_t * bis)4669f3183d2SMingkai Hu int cpu_mmc_init(bd_t *bis)
4679f3183d2SMingkai Hu {
4689f3183d2SMingkai Hu 	return fsl_esdhc_mmc_init(bis);
4699f3183d2SMingkai Hu }
4709f3183d2SMingkai Hu #endif
4719f3183d2SMingkai Hu 
cpu_eth_init(bd_t * bis)4729f3183d2SMingkai Hu int cpu_eth_init(bd_t *bis)
4739f3183d2SMingkai Hu {
4749f3183d2SMingkai Hu 	int error = 0;
4759f3183d2SMingkai Hu 
4761f55a938SSantan Kumar #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
4779f3183d2SMingkai Hu 	error = fsl_mc_ldpaa_init(bis);
4789f3183d2SMingkai Hu #endif
479e8297341SShaohui Xie #ifdef CONFIG_FMAN_ENET
480e8297341SShaohui Xie 	fm_standard_init(bis);
481e8297341SShaohui Xie #endif
4829f3183d2SMingkai Hu 	return error;
4839f3183d2SMingkai Hu }
4849f3183d2SMingkai Hu 
check_psci(void)485026f30ecSYuantian Tang static inline int check_psci(void)
486026f30ecSYuantian Tang {
487026f30ecSYuantian Tang 	unsigned int psci_ver;
488026f30ecSYuantian Tang 
489026f30ecSYuantian Tang 	psci_ver = sec_firmware_support_psci_version();
490026f30ecSYuantian Tang 	if (psci_ver == PSCI_INVALID_VER)
491026f30ecSYuantian Tang 		return 1;
492026f30ecSYuantian Tang 
493026f30ecSYuantian Tang 	return 0;
494026f30ecSYuantian Tang }
495026f30ecSYuantian Tang 
arch_early_init_r(void)4969f3183d2SMingkai Hu int arch_early_init_r(void)
4979f3183d2SMingkai Hu {
498b4017364SPrabhakar Kushwaha #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
499eea1cb77SPriyanka Jain 	u32 svr_dev_id;
500eea1cb77SPriyanka Jain 	/*
501eea1cb77SPriyanka Jain 	 * erratum A009635 is valid only for LS2080A SoC and
502eea1cb77SPriyanka Jain 	 * its personalitiesi
503eea1cb77SPriyanka Jain 	 */
504*739cab17SWenbin song 	svr_dev_id = get_svr();
505*739cab17SWenbin song 	if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
506b4017364SPrabhakar Kushwaha 		erratum_a009635();
507b4017364SPrabhakar Kushwaha #endif
50802fb2761SShengzhou Liu #if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
50902fb2761SShengzhou Liu 	erratum_a009942_check_cpo();
51002fb2761SShengzhou Liu #endif
511026f30ecSYuantian Tang 	if (check_psci()) {
512026f30ecSYuantian Tang 		debug("PSCI: PSCI does not exist.\n");
513026f30ecSYuantian Tang 
514026f30ecSYuantian Tang 		/* if PSCI does not exist, boot secondary cores here */
515026f30ecSYuantian Tang 		if (fsl_layerscape_wake_seconday_cores())
5169f3183d2SMingkai Hu 			printf("Did not wake secondary cores\n");
517032d5bb4SHou Zhiqiang 	}
5189f3183d2SMingkai Hu 
5199f3183d2SMingkai Hu #ifdef CONFIG_SYS_HAS_SERDES
5209f3183d2SMingkai Hu 	fsl_serdes_init();
5219f3183d2SMingkai Hu #endif
522e8297341SShaohui Xie #ifdef CONFIG_FMAN_ENET
523e8297341SShaohui Xie 	fman_enet_init();
524e8297341SShaohui Xie #endif
5259f3183d2SMingkai Hu 	return 0;
5269f3183d2SMingkai Hu }
5279f3183d2SMingkai Hu 
timer_init(void)5289f3183d2SMingkai Hu int timer_init(void)
5299f3183d2SMingkai Hu {
5309f3183d2SMingkai Hu 	u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
5319f3183d2SMingkai Hu #ifdef CONFIG_FSL_LSCH3
5329f3183d2SMingkai Hu 	u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
5339f3183d2SMingkai Hu #endif
5344a3ab193SYork Sun #ifdef CONFIG_ARCH_LS2080A
535a758177fSYunhui Cui 	u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
536f6b96ff6SPriyanka Jain 	u32 svr_dev_id;
537a758177fSYunhui Cui #endif
5389f3183d2SMingkai Hu #ifdef COUNTER_FREQUENCY_REAL
5399f3183d2SMingkai Hu 	unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
5409f3183d2SMingkai Hu 
5419f3183d2SMingkai Hu 	/* Update with accurate clock frequency */
542399e2bb6SYork Sun 	if (current_el() == 3)
5439f3183d2SMingkai Hu 		asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
5449f3183d2SMingkai Hu #endif
5459f3183d2SMingkai Hu 
5469f3183d2SMingkai Hu #ifdef CONFIG_FSL_LSCH3
5479f3183d2SMingkai Hu 	/* Enable timebase for all clusters.
5489f3183d2SMingkai Hu 	 * It is safe to do so even some clusters are not enabled.
5499f3183d2SMingkai Hu 	 */
5509f3183d2SMingkai Hu 	out_le32(cltbenr, 0xf);
5519f3183d2SMingkai Hu #endif
5529f3183d2SMingkai Hu 
5534a3ab193SYork Sun #ifdef CONFIG_ARCH_LS2080A
554a758177fSYunhui Cui 	/*
555a758177fSYunhui Cui 	 * In certain Layerscape SoCs, the clock for each core's
556a758177fSYunhui Cui 	 * has an enable bit in the PMU Physical Core Time Base Enable
557a758177fSYunhui Cui 	 * Register (PCTBENR), which allows the watchdog to operate.
558a758177fSYunhui Cui 	 */
559a758177fSYunhui Cui 	setbits_le32(pctbenr, 0xff);
560f6b96ff6SPriyanka Jain 	/*
561f6b96ff6SPriyanka Jain 	 * For LS2080A SoC and its personalities, timer controller
562f6b96ff6SPriyanka Jain 	 * offset is different
563f6b96ff6SPriyanka Jain 	 */
564*739cab17SWenbin song 	svr_dev_id = get_svr();
565*739cab17SWenbin song 	if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
566f6b96ff6SPriyanka Jain 		cntcr = (u32 *)SYS_FSL_LS2080A_LS2085A_TIMER_ADDR;
567f6b96ff6SPriyanka Jain 
568a758177fSYunhui Cui #endif
569a758177fSYunhui Cui 
5709f3183d2SMingkai Hu 	/* Enable clock for timer
5719f3183d2SMingkai Hu 	 * This is a global setting.
5729f3183d2SMingkai Hu 	 */
5739f3183d2SMingkai Hu 	out_le32(cntcr, 0x1);
5749f3183d2SMingkai Hu 
5759f3183d2SMingkai Hu 	return 0;
5769f3183d2SMingkai Hu }
5779f3183d2SMingkai Hu 
57878d57842SAlexander Graf __efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR;
57978d57842SAlexander Graf 
reset_cpu(ulong addr)58078d57842SAlexander Graf void __efi_runtime reset_cpu(ulong addr)
5819f3183d2SMingkai Hu {
5829f3183d2SMingkai Hu 	u32 val;
5839f3183d2SMingkai Hu 
5849f3183d2SMingkai Hu 	/* Raise RESET_REQ_B */
5859f3183d2SMingkai Hu 	val = scfg_in32(rstcr);
5869f3183d2SMingkai Hu 	val |= 0x02;
5879f3183d2SMingkai Hu 	scfg_out32(rstcr, val);
5889f3183d2SMingkai Hu }
589c0492141SYork Sun 
59078d57842SAlexander Graf #ifdef CONFIG_EFI_LOADER
59178d57842SAlexander Graf 
efi_reset_system(enum efi_reset_type reset_type,efi_status_t reset_status,unsigned long data_size,void * reset_data)59278d57842SAlexander Graf void __efi_runtime EFIAPI efi_reset_system(
59378d57842SAlexander Graf 		       enum efi_reset_type reset_type,
59478d57842SAlexander Graf 		       efi_status_t reset_status,
59578d57842SAlexander Graf 		       unsigned long data_size, void *reset_data)
59678d57842SAlexander Graf {
59778d57842SAlexander Graf 	switch (reset_type) {
59878d57842SAlexander Graf 	case EFI_RESET_COLD:
59978d57842SAlexander Graf 	case EFI_RESET_WARM:
60078d57842SAlexander Graf 		reset_cpu(0);
60178d57842SAlexander Graf 		break;
60278d57842SAlexander Graf 	case EFI_RESET_SHUTDOWN:
60378d57842SAlexander Graf 		/* Nothing we can do */
60478d57842SAlexander Graf 		break;
60578d57842SAlexander Graf 	}
60678d57842SAlexander Graf 
60778d57842SAlexander Graf 	while (1) { }
60878d57842SAlexander Graf }
60978d57842SAlexander Graf 
efi_reset_system_init(void)61078d57842SAlexander Graf void efi_reset_system_init(void)
61178d57842SAlexander Graf {
61278d57842SAlexander Graf        efi_add_runtime_mmio(&rstcr, sizeof(*rstcr));
61378d57842SAlexander Graf }
61478d57842SAlexander Graf 
61578d57842SAlexander Graf #endif
61678d57842SAlexander Graf 
board_reserve_ram_top(phys_size_t ram_size)617c0492141SYork Sun phys_size_t board_reserve_ram_top(phys_size_t ram_size)
618c0492141SYork Sun {
619c0492141SYork Sun 	phys_size_t ram_top = ram_size;
620c0492141SYork Sun 
6211f55a938SSantan Kumar #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
62236cc0de0SYork Sun 	/* The start address of MC reserved memory needs to be aligned. */
623c0492141SYork Sun 	ram_top -= mc_get_dram_block_size();
624c0492141SYork Sun 	ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1);
625c0492141SYork Sun #endif
626c0492141SYork Sun 
62736cc0de0SYork Sun 	return ram_size - ram_top;
628c0492141SYork Sun }
62936cc0de0SYork Sun 
get_effective_memsize(void)63036cc0de0SYork Sun phys_size_t get_effective_memsize(void)
63136cc0de0SYork Sun {
63236cc0de0SYork Sun 	phys_size_t ea_size, rem = 0;
63336cc0de0SYork Sun 
63436cc0de0SYork Sun 	/*
63536cc0de0SYork Sun 	 * For ARMv8 SoCs, DDR memory is split into two or three regions. The
63636cc0de0SYork Sun 	 * first region is 2GB space at 0x8000_0000. If the memory extends to
63736cc0de0SYork Sun 	 * the second region (or the third region if applicable), the secure
63836cc0de0SYork Sun 	 * memory and Management Complex (MC) memory should be put into the
63936cc0de0SYork Sun 	 * highest region, i.e. the end of DDR memory. CONFIG_MAX_MEM_MAPPED
64036cc0de0SYork Sun 	 * is set to the size of first region so U-Boot doesn't relocate itself
64136cc0de0SYork Sun 	 * into higher address. Should DDR be configured to skip the first
64236cc0de0SYork Sun 	 * region, this function needs to be adjusted.
64336cc0de0SYork Sun 	 */
64436cc0de0SYork Sun 	if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) {
64536cc0de0SYork Sun 		ea_size = CONFIG_MAX_MEM_MAPPED;
64636cc0de0SYork Sun 		rem = gd->ram_size - ea_size;
64736cc0de0SYork Sun 	} else {
64836cc0de0SYork Sun 		ea_size = gd->ram_size;
64936cc0de0SYork Sun 	}
65036cc0de0SYork Sun 
65136cc0de0SYork Sun #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
65236cc0de0SYork Sun 	/* Check if we have enough space for secure memory */
65336cc0de0SYork Sun 	if (rem > CONFIG_SYS_MEM_RESERVE_SECURE) {
65436cc0de0SYork Sun 		rem -= CONFIG_SYS_MEM_RESERVE_SECURE;
65536cc0de0SYork Sun 	} else {
65636cc0de0SYork Sun 		if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE) {
65736cc0de0SYork Sun 			ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
65836cc0de0SYork Sun 			rem = 0;	/* Presume MC requires more memory */
65936cc0de0SYork Sun 		} else {
66036cc0de0SYork Sun 			printf("Error: No enough space for secure memory.\n");
66136cc0de0SYork Sun 		}
66236cc0de0SYork Sun 	}
66336cc0de0SYork Sun #endif
66436cc0de0SYork Sun 	/* Check if we have enough memory for MC */
66536cc0de0SYork Sun 	if (rem < board_reserve_ram_top(rem)) {
66636cc0de0SYork Sun 		/* Not enough memory in high region to reserve */
66736cc0de0SYork Sun 		if (ea_size > board_reserve_ram_top(rem))
66836cc0de0SYork Sun 			ea_size -= board_reserve_ram_top(rem);
66936cc0de0SYork Sun 		else
67036cc0de0SYork Sun 			printf("Error: No enough space for reserved memory.\n");
67136cc0de0SYork Sun 	}
67236cc0de0SYork Sun 
67336cc0de0SYork Sun 	return ea_size;
67436cc0de0SYork Sun }
67536cc0de0SYork Sun 
dram_init_banksize(void)67676b00acaSSimon Glass int dram_init_banksize(void)
67736cc0de0SYork Sun {
67836cc0de0SYork Sun #ifdef CONFIG_SYS_DP_DDR_BASE_PHY
67936cc0de0SYork Sun 	phys_size_t dp_ddr_size;
68036cc0de0SYork Sun #endif
68136cc0de0SYork Sun 
68236cc0de0SYork Sun 	/*
68336cc0de0SYork Sun 	 * gd->ram_size has the total size of DDR memory, less reserved secure
68436cc0de0SYork Sun 	 * memory. The DDR extends from low region to high region(s) presuming
68536cc0de0SYork Sun 	 * no hole is created with DDR configuration. gd->arch.secure_ram tracks
68636cc0de0SYork Sun 	 * the location of secure memory. gd->arch.resv_ram tracks the location
68736cc0de0SYork Sun 	 * of reserved memory for Management Complex (MC).
68836cc0de0SYork Sun 	 */
68936cc0de0SYork Sun 	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
69036cc0de0SYork Sun 	if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) {
69136cc0de0SYork Sun 		gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE;
69236cc0de0SYork Sun 		gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
69336cc0de0SYork Sun 		gd->bd->bi_dram[1].size = gd->ram_size -
69436cc0de0SYork Sun 					  CONFIG_SYS_DDR_BLOCK1_SIZE;
69536cc0de0SYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
69636cc0de0SYork Sun 		if (gd->bi_dram[1].size > CONFIG_SYS_DDR_BLOCK2_SIZE) {
69736cc0de0SYork Sun 			gd->bd->bi_dram[2].start = CONFIG_SYS_DDR_BLOCK3_BASE;
69836cc0de0SYork Sun 			gd->bd->bi_dram[2].size = gd->bd->bi_dram[1].size -
69936cc0de0SYork Sun 						  CONFIG_SYS_DDR_BLOCK2_SIZE;
70036cc0de0SYork Sun 			gd->bd->bi_dram[1].size = CONFIG_SYS_DDR_BLOCK2_SIZE;
70136cc0de0SYork Sun 		}
70236cc0de0SYork Sun #endif
70336cc0de0SYork Sun 	} else {
70436cc0de0SYork Sun 		gd->bd->bi_dram[0].size = gd->ram_size;
70536cc0de0SYork Sun 	}
70636cc0de0SYork Sun #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
70736cc0de0SYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
70836cc0de0SYork Sun 	if (gd->bd->bi_dram[2].size >= CONFIG_SYS_MEM_RESERVE_SECURE) {
70936cc0de0SYork Sun 		gd->bd->bi_dram[2].size -= CONFIG_SYS_MEM_RESERVE_SECURE;
71036cc0de0SYork Sun 		gd->arch.secure_ram = gd->bd->bi_dram[2].start +
71136cc0de0SYork Sun 				      gd->bd->bi_dram[2].size;
71236cc0de0SYork Sun 		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
71336cc0de0SYork Sun 		gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
71436cc0de0SYork Sun 	} else
71536cc0de0SYork Sun #endif
71636cc0de0SYork Sun 	{
71736cc0de0SYork Sun 		if (gd->bd->bi_dram[1].size >= CONFIG_SYS_MEM_RESERVE_SECURE) {
71836cc0de0SYork Sun 			gd->bd->bi_dram[1].size -=
71936cc0de0SYork Sun 					CONFIG_SYS_MEM_RESERVE_SECURE;
72036cc0de0SYork Sun 			gd->arch.secure_ram = gd->bd->bi_dram[1].start +
72136cc0de0SYork Sun 					      gd->bd->bi_dram[1].size;
72236cc0de0SYork Sun 			gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
72336cc0de0SYork Sun 			gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
72436cc0de0SYork Sun 		} else if (gd->bd->bi_dram[0].size >
72536cc0de0SYork Sun 					CONFIG_SYS_MEM_RESERVE_SECURE) {
72636cc0de0SYork Sun 			gd->bd->bi_dram[0].size -=
72736cc0de0SYork Sun 					CONFIG_SYS_MEM_RESERVE_SECURE;
72836cc0de0SYork Sun 			gd->arch.secure_ram = gd->bd->bi_dram[0].start +
72936cc0de0SYork Sun 					      gd->bd->bi_dram[0].size;
73036cc0de0SYork Sun 			gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
73136cc0de0SYork Sun 			gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
73236cc0de0SYork Sun 		}
73336cc0de0SYork Sun 	}
73436cc0de0SYork Sun #endif	/* CONFIG_SYS_MEM_RESERVE_SECURE */
73536cc0de0SYork Sun 
7361f55a938SSantan Kumar #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
73736cc0de0SYork Sun 	/* Assign memory for MC */
73836cc0de0SYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
73936cc0de0SYork Sun 	if (gd->bd->bi_dram[2].size >=
74036cc0de0SYork Sun 	    board_reserve_ram_top(gd->bd->bi_dram[2].size)) {
74136cc0de0SYork Sun 		gd->arch.resv_ram = gd->bd->bi_dram[2].start +
74236cc0de0SYork Sun 			    gd->bd->bi_dram[2].size -
74336cc0de0SYork Sun 			    board_reserve_ram_top(gd->bd->bi_dram[2].size);
74436cc0de0SYork Sun 	} else
74536cc0de0SYork Sun #endif
74636cc0de0SYork Sun 	{
74736cc0de0SYork Sun 		if (gd->bd->bi_dram[1].size >=
74836cc0de0SYork Sun 		    board_reserve_ram_top(gd->bd->bi_dram[1].size)) {
74936cc0de0SYork Sun 			gd->arch.resv_ram = gd->bd->bi_dram[1].start +
75036cc0de0SYork Sun 				gd->bd->bi_dram[1].size -
75136cc0de0SYork Sun 				board_reserve_ram_top(gd->bd->bi_dram[1].size);
75236cc0de0SYork Sun 		} else if (gd->bd->bi_dram[0].size >
75336cc0de0SYork Sun 			   board_reserve_ram_top(gd->bd->bi_dram[0].size)) {
75436cc0de0SYork Sun 			gd->arch.resv_ram = gd->bd->bi_dram[0].start +
75536cc0de0SYork Sun 				gd->bd->bi_dram[0].size -
75636cc0de0SYork Sun 				board_reserve_ram_top(gd->bd->bi_dram[0].size);
75736cc0de0SYork Sun 		}
75836cc0de0SYork Sun 	}
75936cc0de0SYork Sun #endif	/* CONFIG_FSL_MC_ENET */
76036cc0de0SYork Sun 
76136cc0de0SYork Sun #ifdef CONFIG_SYS_DP_DDR_BASE_PHY
76236cc0de0SYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
76336cc0de0SYork Sun #error "This SoC shouldn't have DP DDR"
76436cc0de0SYork Sun #endif
76536cc0de0SYork Sun 	if (soc_has_dp_ddr()) {
76636cc0de0SYork Sun 		/* initialize DP-DDR here */
76736cc0de0SYork Sun 		puts("DP-DDR:  ");
76836cc0de0SYork Sun 		/*
76936cc0de0SYork Sun 		 * DDR controller use 0 as the base address for binding.
77036cc0de0SYork Sun 		 * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access.
77136cc0de0SYork Sun 		 */
77236cc0de0SYork Sun 		dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY,
77336cc0de0SYork Sun 					  CONFIG_DP_DDR_CTRL,
77436cc0de0SYork Sun 					  CONFIG_DP_DDR_NUM_CTRLS,
77536cc0de0SYork Sun 					  CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR,
77636cc0de0SYork Sun 					  NULL, NULL, NULL);
77736cc0de0SYork Sun 		if (dp_ddr_size) {
77836cc0de0SYork Sun 			gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE;
77936cc0de0SYork Sun 			gd->bd->bi_dram[2].size = dp_ddr_size;
78036cc0de0SYork Sun 		} else {
78136cc0de0SYork Sun 			puts("Not detected");
78236cc0de0SYork Sun 		}
78336cc0de0SYork Sun 	}
78436cc0de0SYork Sun #endif
78576b00acaSSimon Glass 
78676b00acaSSimon Glass 	return 0;
78736cc0de0SYork Sun }
78836cc0de0SYork Sun 
78936cc0de0SYork Sun #if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD)
efi_add_known_memory(void)79036cc0de0SYork Sun void efi_add_known_memory(void)
79136cc0de0SYork Sun {
79236cc0de0SYork Sun 	int i;
79336cc0de0SYork Sun 	phys_addr_t ram_start, start;
79436cc0de0SYork Sun 	phys_size_t ram_size;
79536cc0de0SYork Sun 	u64 pages;
79636cc0de0SYork Sun 
79736cc0de0SYork Sun 	/* Add RAM */
79836cc0de0SYork Sun 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
79936cc0de0SYork Sun #ifdef CONFIG_SYS_DP_DDR_BASE_PHY
80036cc0de0SYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
80136cc0de0SYork Sun #error "This SoC shouldn't have DP DDR"
80236cc0de0SYork Sun #endif
80336cc0de0SYork Sun 		if (i == 2)
80436cc0de0SYork Sun 			continue;	/* skip DP-DDR */
80536cc0de0SYork Sun #endif
80636cc0de0SYork Sun 		ram_start = gd->bd->bi_dram[i].start;
80736cc0de0SYork Sun 		ram_size = gd->bd->bi_dram[i].size;
80836cc0de0SYork Sun #ifdef CONFIG_RESV_RAM
80936cc0de0SYork Sun 		if (gd->arch.resv_ram >= ram_start &&
81036cc0de0SYork Sun 		    gd->arch.resv_ram < ram_start + ram_size)
81136cc0de0SYork Sun 			ram_size = gd->arch.resv_ram - ram_start;
81236cc0de0SYork Sun #endif
81336cc0de0SYork Sun 		start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
81436cc0de0SYork Sun 		pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
81536cc0de0SYork Sun 
81636cc0de0SYork Sun 		efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
81736cc0de0SYork Sun 				   false);
81836cc0de0SYork Sun 	}
81936cc0de0SYork Sun }
82036cc0de0SYork Sun #endif
8214961eafcSYork Sun 
8224961eafcSYork Sun /*
8234961eafcSYork Sun  * Before DDR size is known, early MMU table have DDR mapped as device memory
8244961eafcSYork Sun  * to avoid speculative access. To relocate U-Boot to DDR, "normal memory"
8254961eafcSYork Sun  * needs to be set for these mappings.
8264961eafcSYork Sun  * If a special case configures DDR with holes in the mapping, the holes need
8274961eafcSYork Sun  * to be marked as invalid. This is not implemented in this function.
8284961eafcSYork Sun  */
update_early_mmu_table(void)8294961eafcSYork Sun void update_early_mmu_table(void)
8304961eafcSYork Sun {
8314961eafcSYork Sun 	if (!gd->arch.tlb_addr)
8324961eafcSYork Sun 		return;
8334961eafcSYork Sun 
8344961eafcSYork Sun 	if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) {
8354961eafcSYork Sun 		mmu_change_region_attr(
8364961eafcSYork Sun 					CONFIG_SYS_SDRAM_BASE,
8374961eafcSYork Sun 					gd->ram_size,
8384961eafcSYork Sun 					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
8394961eafcSYork Sun 					PTE_BLOCK_OUTER_SHARE		|
8404961eafcSYork Sun 					PTE_BLOCK_NS			|
8414961eafcSYork Sun 					PTE_TYPE_VALID);
8424961eafcSYork Sun 	} else {
8434961eafcSYork Sun 		mmu_change_region_attr(
8444961eafcSYork Sun 					CONFIG_SYS_SDRAM_BASE,
8454961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK1_SIZE,
8464961eafcSYork Sun 					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
8474961eafcSYork Sun 					PTE_BLOCK_OUTER_SHARE		|
8484961eafcSYork Sun 					PTE_BLOCK_NS			|
8494961eafcSYork Sun 					PTE_TYPE_VALID);
8504961eafcSYork Sun #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
8514961eafcSYork Sun #ifndef CONFIG_SYS_DDR_BLOCK2_SIZE
8524961eafcSYork Sun #error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE"
8534961eafcSYork Sun #endif
8544961eafcSYork Sun 		if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE >
8554961eafcSYork Sun 		    CONFIG_SYS_DDR_BLOCK2_SIZE) {
8564961eafcSYork Sun 			mmu_change_region_attr(
8574961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK2_BASE,
8584961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK2_SIZE,
8594961eafcSYork Sun 					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
8604961eafcSYork Sun 					PTE_BLOCK_OUTER_SHARE		|
8614961eafcSYork Sun 					PTE_BLOCK_NS			|
8624961eafcSYork Sun 					PTE_TYPE_VALID);
8634961eafcSYork Sun 			mmu_change_region_attr(
8644961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK3_BASE,
8654961eafcSYork Sun 					gd->ram_size -
8664961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK1_SIZE -
8674961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK2_SIZE,
8684961eafcSYork Sun 					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
8694961eafcSYork Sun 					PTE_BLOCK_OUTER_SHARE		|
8704961eafcSYork Sun 					PTE_BLOCK_NS			|
8714961eafcSYork Sun 					PTE_TYPE_VALID);
8724961eafcSYork Sun 		} else
8734961eafcSYork Sun #endif
8744961eafcSYork Sun 		{
8754961eafcSYork Sun 			mmu_change_region_attr(
8764961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK2_BASE,
8774961eafcSYork Sun 					gd->ram_size -
8784961eafcSYork Sun 					CONFIG_SYS_DDR_BLOCK1_SIZE,
8794961eafcSYork Sun 					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
8804961eafcSYork Sun 					PTE_BLOCK_OUTER_SHARE		|
8814961eafcSYork Sun 					PTE_BLOCK_NS			|
8824961eafcSYork Sun 					PTE_TYPE_VALID);
8834961eafcSYork Sun 		}
8844961eafcSYork Sun 	}
8854961eafcSYork Sun }
8864961eafcSYork Sun 
dram_init(void)8874961eafcSYork Sun __weak int dram_init(void)
8884961eafcSYork Sun {
8893eace37eSSimon Glass 	fsl_initdram();
8904961eafcSYork Sun #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
8914961eafcSYork Sun 	/* This will break-before-make MMU for DDR */
8924961eafcSYork Sun 	update_early_mmu_table();
8934961eafcSYork Sun #endif
8944961eafcSYork Sun 
8954961eafcSYork Sun 	return 0;
8964961eafcSYork Sun }
897