[U-Boot] [PATCH v1 0/5] Enable PPA in SPL for ARMv8 Layerscape SoCs

This is the first step to move NXP Layerscape SoCs to run at EL2. With PPA (an implementation of trusted firmware) loaded during SPL stage, the rest of U-Boot (and subsequently loaded RAM version) runs at EL2. Eventually non-SPL boot will also moves to this direction.
York Sun (5): armv8: layerscape: Make U-Boot EL2 safe armv8: layerscape: Enabling loading PPA during SPL stage armv8: ls1043ardb: Enable loading PPA during SPL stage for SD boot armv8: ls1046a: Enable spl_board_init() function armv8: ls1046ardb: Enable loading PPA during SPL stage for SD boot
arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 13 +++++++ arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 11 +++++- arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 16 ++++++++- arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 7 ++++ arch/arm/cpu/armv8/fsl-layerscape/soc.c | 14 ++++++-- arch/arm/cpu/armv8/fsl-layerscape/spl.c | 41 ++++++++++++++++++++++- arch/arm/cpu/armv8/sec_firmware.c | 2 +- arch/arm/cpu/armv8/start.S | 3 ++ arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + board/freescale/common/ns_access.c | 5 ++- configs/ls1043ardb_sdcard_defconfig | 1 + configs/ls1046ardb_sdcard_defconfig | 1 + include/configs/ls1046a_common.h | 1 + 13 files changed, 109 insertions(+), 7 deletions(-)

When U-Boot boots from EL2, skip some lowlevel init code requiring EL3, including CCI-400/CCN-504, trust zone, GIC, etc. These initialization tasks are carried out before U-Boot runs. This applies to the RAM version image used for SPL boot if PPA is loaded first.
Signed-off-by: York Sun york.sun@nxp.com ---
arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 11 ++++++++++- arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 16 +++++++++++++++- arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 7 +++++++ arch/arm/cpu/armv8/fsl-layerscape/soc.c | 14 ++++++++++++-- arch/arm/cpu/armv8/sec_firmware.c | 2 +- arch/arm/cpu/armv8/start.S | 3 +++ board/freescale/common/ns_access.c | 5 ++++- 7 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index bb02960..cf20ee6 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -242,6 +242,14 @@ u64 get_page_table_size(void)
int arch_cpu_init(void) { + /* + * This function is called before U-Boot relocates itself to speed up + * on system running. It is not necessary to run if performance is not + * critical. Skip if MMU is already enabled by SPL or other means. + */ + if (get_sctlr() & CR_M) + return 0; + icache_enable(); __asm_invalidate_dcache_all(); __asm_invalidate_tlb_all(); @@ -528,7 +536,8 @@ int timer_init(void) unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
/* Update with accurate clock frequency */ - asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); + if (current_el() == 3) + asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); #endif
#ifdef CONFIG_FSL_LSCH3 diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S index f427356..619d9b7 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S @@ -73,6 +73,9 @@ ENDPROC(smp_kick_all_cpus) ENTRY(lowlevel_init) mov x29, lr /* Save LR */
+ switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: + #ifdef CONFIG_FSL_LSCH3
/* Set Wuo bit for RN-I 20 */ @@ -193,6 +196,7 @@ ENTRY(lowlevel_init) #endif #endif
+100: branch_if_master x0, x1, 2f
#if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY) @@ -201,6 +205,8 @@ ENTRY(lowlevel_init) #endif
2: + switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: #ifdef CONFIG_FSL_TZPC_BP147 /* Set Non Secure access for all devices protected via TZPC */ ldr x1, =TZPCDECPROT_0_SET_BASE /* Decode Protection-0 Set Reg */ @@ -266,8 +272,11 @@ ENTRY(lowlevel_init) isb dsb sy #endif +100: 1: #ifdef CONFIG_ARCH_LS1046A + switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: /* Initialize the L2 RAM latency */ mrs x1, S3_1_c11_c0_2 mov x0, #0x1C7 @@ -279,6 +288,7 @@ ENTRY(lowlevel_init) orr x1, x1, #0x80 msr S3_1_c11_c0_2, x1 isb +100: #endif
#if defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD) @@ -379,11 +389,14 @@ ENTRY(__asm_flush_l3_dcache) /* * Return status in x0 * success 0 - * tmeout 1 for setting SFONLY, 2 for FAM, 3 for both + * timeout 1 for setting SFONLY, 2 for FAM, 3 for both */ mov x29, lr mov x8, #0
+ switch_el x0, 1f, 100f, 100f /* skip if not in EL3 */ + +1: dsb sy mov x0, #0x1 /* HNFPSTAT_SFONLY */ bl hnf_set_pstate @@ -401,6 +414,7 @@ ENTRY(__asm_flush_l3_dcache) bl hnf_pstate_poll cbz x0, 1f add x8, x8, #0x2 +100: 1: mov x0, x8 mov lr, x29 diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c index 26c47a1..35c612d 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
int ppa_init(void) { + unsigned int el = current_el(); void *ppa_fit_addr; u32 *boot_loc_ptr_l, *boot_loc_ptr_h; int ret; @@ -45,6 +46,12 @@ int ppa_init(void) #endif #endif
+ /* Skip if running at lower exception level */ + if (el < 3) { + debug("Skipping PPA init, running at EL%d\n", el); + return 0; + } + #ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR; debug("%s: PPA image load from XIP\n", __func__); diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 9e3cdd7..b1d9204 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -288,6 +288,10 @@ static void erratum_a008850_early(void) struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR; struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+ /* Skip if running at lower exception level */ + if (current_el() < 3) + return; + /* disables propagation of barrier transactions to DDRC from CCI400 */ out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
@@ -304,6 +308,10 @@ void erratum_a008850_post(void) struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; u32 tmp;
+ /* Skip if running at lower exception level */ + if (current_el() < 3) + return; + /* enable propagation of barrier transactions to DDRC from CCI400 */ out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
@@ -455,8 +463,10 @@ void fsl_lsch2_early_init_f(void) * Enable snoop requests and DVM message requests for * Slave insterface S4 (A53 core cluster) */ - out_le32(&cci->slave[4].snoop_ctrl, - CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + if (current_el() == 3) { + out_le32(&cci->slave[4].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + }
/* Erratum */ erratum_a008850_early(); /* part 1 of 2 */ diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c index 4afa3ad..fffce71 100644 --- a/arch/arm/cpu/armv8/sec_firmware.c +++ b/arch/arm/cpu/armv8/sec_firmware.c @@ -224,7 +224,7 @@ __weak bool sec_firmware_is_valid(const void *sec_firmware_img) */ unsigned int sec_firmware_support_psci_version(void) { - if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) + if (current_el() == SEC_FIRMWARE_TARGET_EL) return _sec_firmware_support_psci_version();
return PSCI_INVALID_VER; diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 62d97f7..29343d3 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -91,9 +91,12 @@ save_boot_params_ret: * this bit should be set for A53/A57/A72. */ #ifdef CONFIG_ARMV8_SET_SMPEN + switch_el x1, 3f, 1f, 1f +3: mrs x0, S3_1_c15_c2_1 /* cpuactlr_el1 */ orr x0, x0, #0x40 msr S3_1_c15_c2_1, x0 +1: #endif
/* Apply ARM core specific erratas */ diff --git a/board/freescale/common/ns_access.c b/board/freescale/common/ns_access.c index 81c9211..1c2287d 100644 --- a/board/freescale/common/ns_access.c +++ b/board/freescale/common/ns_access.c @@ -39,7 +39,10 @@ static void enable_devices_ns_access(struct csu_ns_dev *ns_dev, uint32_t num)
void enable_layerscape_ns_access(void) { - enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev)); +#ifdef CONFIG_ARM64 + if (current_el() == 3) +#endif + enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev)); }
void set_pcie_ns_access(int pcie, u16 val)

On 05/15/2017 08:52 AM, York Sun wrote:
When U-Boot boots from EL2, skip some lowlevel init code requiring EL3, including CCI-400/CCN-504, trust zone, GIC, etc. These initialization tasks are carried out before U-Boot runs. This applies to the RAM version image used for SPL boot if PPA is loaded first.
Signed-off-by: York Sunyork.sun@nxp.com
arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 11 ++++++++++- arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 16 +++++++++++++++- arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 7 +++++++ arch/arm/cpu/armv8/fsl-layerscape/soc.c | 14 ++++++++++++-- arch/arm/cpu/armv8/sec_firmware.c | 2 +- arch/arm/cpu/armv8/start.S | 3 +++ board/freescale/common/ns_access.c | 5 ++++- 7 files changed, 52 insertions(+), 6 deletions(-)
Applied this set (with patch v2 4/5) to fsl-qoriq master, awaiting upstream.
York

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 ---
arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 13 +++++++ arch/arm/cpu/armv8/fsl-layerscape/spl.c | 41 ++++++++++++++++++++++- arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + 3 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 4c16c4c..25690b9 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -135,6 +135,19 @@ config FSL_LS_PPA 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 @@ void spl_board_init(void) 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 @@ void board_init_f(ulong dummy) 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 }

Signed-off-by: York Sun york.sun@nxp.com ---
configs/ls1043ardb_sdcard_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/ls1043ardb_sdcard_defconfig b/configs/ls1043ardb_sdcard_defconfig index 329dd3b..ea674c8 100644 --- a/configs/ls1043ardb_sdcard_defconfig +++ b/configs/ls1043ardb_sdcard_defconfig @@ -3,6 +3,7 @@ CONFIG_TARGET_LS1043ARDB=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_FSL_LS_PPA=y +CONFIG_SPL_FSL_LS_PPA=y CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y

CONFIG_SPL_BOARD_INIT is used for SPL boot. It is only defined for secure boot at this moment. Define it in board header file for SPL build.
Signed-off-by: York Sun york.sun@nxp.com ---
include/configs/ls1046a_common.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/configs/ls1046a_common.h b/include/configs/ls1046a_common.h index 957ffd3..ffa1c78 100644 --- a/include/configs/ls1046a_common.h +++ b/include/configs/ls1046a_common.h @@ -9,6 +9,7 @@
/* SPL build */ #ifdef CONFIG_SPL_BUILD +#define CONFIG_SPL_BOARD_INIT #define SPL_NO_QBMAN #define SPL_NO_FMAN #define SPL_NO_ENV

Signed-off-by: York Sun york.sun@nxp.com
---
configs/ls1046ardb_sdcard_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/ls1046ardb_sdcard_defconfig b/configs/ls1046ardb_sdcard_defconfig index d70a387..f84358f 100644 --- a/configs/ls1046ardb_sdcard_defconfig +++ b/configs/ls1046ardb_sdcard_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_TARGET_LS1046ARDB=y CONFIG_FSL_LS_PPA=y +CONFIG_SPL_FSL_LS_PPA=y CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1046a-rdb" CONFIG_FIT_VERBOSE=y CONFIG_OF_BOARD_SETUP=y
participants (2)
-
York Sun
-
york sun