armv8: layerscape: Make U-Boot EL2 safe
authorYork Sun <york.sun@nxp.com>
Mon, 15 May 2017 15:51:59 +0000 (08:51 -0700)
committerYork Sun <york.sun@nxp.com>
Fri, 2 Jun 2017 02:57:24 +0000 (19:57 -0700)
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
arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
arch/arm/cpu/armv8/fsl-layerscape/ppa.c
arch/arm/cpu/armv8/fsl-layerscape/soc.c
arch/arm/cpu/armv8/sec_firmware.c
arch/arm/cpu/armv8/start.S
board/freescale/common/ns_access.c

index c4bb31156b42e3a1649f400be387151c7b7b208d..cb3a52c711b35f008da0ac8f6a1e71e9a14cfe93 100644 (file)
@@ -244,6 +244,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();
@@ -530,7 +538,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
index f4273561040f9deede84f2c0bb5d99a907b09b3b..619d9b7a0eda718bcb3ab7a5fc44e634e8ac870b 100644 (file)
@@ -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
index 26c47a183c668c4f8754d7727230704b10646b37..35c612df05181ea7301a578cb7db30d7de202100 100644 (file)
@@ -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__);
index 76e3af0d561d34fc4cefa1a6b327cfddbedd6f52..0943e833d740a10efed6da9b42b016629e2b26f2 100644 (file)
@@ -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 */
index 4afa3ad8b1dcefc6deb6115b464998fd897c9b72..fffce712d38b99d3e739a5970b275d2138aee8e8 100644 (file)
@@ -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;
index 354468b9053d5e03d7ca8d513ce33623abd47c32..5c500be51d1f5fb616e04539e5fd2cb9e7287e3b 100644 (file)
@@ -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               /* cpuectlr_el1 */
        orr     x0, x0, #0x40
        msr     S3_1_c15_c2_1, x0
+1:
 #endif
 
        /* Apply ARM core specific erratas */
index 81c921122e8f65053e7e581426fc8083a62b44e1..1c2287d22a352d023bd28ef7cec12005bc62b10f 100644 (file)
@@ -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)