armv8: layerscape: Enabling loading PPA during SPL stage

Loading PPA in SPL puts the rest of U-Boot (including RAM version
loaded later) in EL2 with MMU and cache enabled. Once PPA is loaded,
PSCI is available.

Signed-off-by: York Sun <york.sun@nxp.com>
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index fa386c6..d8b285d 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -135,6 +135,19 @@
 	  which is loaded during boot stage, and then remains resident in RAM
 	  and runs in the TrustZone after boot.
 	  Say y to enable it.
+
+config SPL_FSL_LS_PPA
+	bool "FSL Layerscape PPA firmware support for SPL build"
+	depends on !ARMV8_PSCI
+	select SPL_ARMV8_SEC_FIRMWARE_SUPPORT
+	select SEC_FIRMWARE_ARMV8_PSCI
+	select ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT if FSL_LSCH2
+	help
+	  The FSL Primary Protected Application (PPA) is a software component
+	  which is loaded during boot stage, and then remains resident in RAM
+	  and runs in the TrustZone after boot. This is to load PPA during SPL
+	  stage instead of the RAM version of U-Boot. Once PPA is initialized,
+	  the rest of U-Boot (including RAM version) runs at EL2.
 choice
 	prompt "FSL Layerscape PPA firmware loading-media select"
 	depends on FSL_LS_PPA
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
index eb730e8..2776240 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
@@ -9,6 +9,9 @@
 #include <asm/io.h>
 #include <fsl_ifc.h>
 #include <i2c.h>
+#include <fsl_csu.h>
+#include <asm/arch/fdt.h>
+#include <asm/arch/ppa.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -57,6 +60,12 @@
 	val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
 	out_le32(SMMU_NSCR0, val);
 #endif
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+#ifdef CONFIG_SPL_FSL_LS_PPA
+	ppa_init();
+#endif
 }
 
 void board_init_f(ulong dummy)
@@ -76,5 +85,35 @@
 	i2c_init_all();
 #endif
 	dram_init();
-}
+#ifdef CONFIG_SPL_FSL_LS_PPA
+#ifndef CONFIG_SYS_MEM_RESERVE_SECURE
+#error Need secure RAM for PPA
 #endif
+	/*
+	 * Secure memory location is determined in dram_init_banksize().
+	 * gd->ram_size is deducted by the size of secure ram.
+	 */
+	dram_init_banksize();
+
+	/*
+	 * After dram_init_bank_size(), we know U-Boot only uses the first
+	 * memory bank regardless how big the memory is.
+	 */
+	gd->ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+
+	/*
+	 * If PPA is loaded, U-Boot will resume running at EL2.
+	 * Cache and MMU will be enabled. Need a place for TLB.
+	 * U-Boot will be relocated to the end of available memory
+	 * in first bank. At this point, we cannot know how much
+	 * memory U-Boot uses. Put TLB table lower by SPL_TLB_SETBACK
+	 * to avoid overlapping. As soon as the RAM version U-Boot sets
+	 * up new MMU, this space is no longer needed.
+	 */
+	gd->ram_top -= SPL_TLB_SETBACK;
+	gd->arch.tlb_size = PGTABLE_SIZE;
+	gd->arch.tlb_addr = (gd->ram_top - gd->arch.tlb_size) & ~(0x10000 - 1);
+	gd->arch.tlb_allocated = gd->arch.tlb_addr;
+#endif	/* CONFIG_SPL_FSL_LS_PPA */
+}
+#endif /* CONFIG_SPL_BUILD */
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 93e6597..79e94f9 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -17,6 +17,7 @@
  * To be aligned with MMU block size
  */
 #define CONFIG_SYS_MEM_RESERVE_SECURE	(2048 * 1024)	/* 2MB */
+#define SPL_TLB_SETBACK	0x1000000	/* 16MB under effective memory top */
 
 #ifdef CONFIG_ARCH_LS2080A
 #define CONFIG_SYS_FSL_CLUSTER_CLOCKS		{ 1, 1, 4, 4 }