]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / arch / arm / cpu / armv8 / fsl-layerscape / lowlevel.S
index 5af6b73bc9e8dab0bb32edff6b9653ac49b8e1c0..e9d373e4641fa4863cd33cd5f5225a8521956c61 100644 (file)
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * (C) Copyright 2014-2015 Freescale Semiconductor
  *
- * SPDX-License-Identifier:    GPL-2.0+
- *
  * Extracted from armv8/start.S
  */
 
 #include <linux/linkage.h>
 #include <asm/gic.h>
 #include <asm/macro.h>
+#include <asm/arch-fsl-layerscape/soc.h>
 #ifdef CONFIG_MP
 #include <asm/arch/mp.h>
 #endif
+#ifdef CONFIG_FSL_LSCH3
+#include <asm/arch-fsl-layerscape/immap_lsch3.h>
+#endif
+#include <asm/u-boot.h>
+
+/* Get GIC offset
+* For LS1043a rev1.0, GIC base address align with 4k.
+* For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT]
+* is set, GIC base address align with 4K, or else align
+* with 64k.
+* output:
+*      x0: the base address of GICD
+*      x1: the base address of GICC
+*/
+ENTRY(get_gic_offset)
+       ldr     x0, =GICD_BASE
+#ifdef CONFIG_GICV2
+       ldr     x1, =GICC_BASE
+#endif
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+       ldr     x2, =DCFG_CCSR_SVR
+       ldr     w2, [x2]
+       rev     w2, w2
+       lsr     w3, w2, #16
+       ldr     w4, =SVR_DEV(SVR_LS1043A)
+       cmp     w3, w4
+       b.ne    1f
+       ands    w2, w2, #0xff
+       cmp     w2, #REV1_0
+       b.eq    1f
+       ldr     x2, =SCFG_GIC400_ALIGN
+       ldr     w2, [x2]
+       rev     w2, w2
+       tbnz    w2, #GIC_ADDR_BIT, 1f
+       ldr     x0, =GICD_BASE_64K
+#ifdef CONFIG_GICV2
+       ldr     x1, =GICC_BASE_64K
+#endif
+1:
+#endif
+       ret
+ENDPROC(get_gic_offset)
+
+ENTRY(smp_kick_all_cpus)
+       /* Kick secondary cpus up by SGI 0 interrupt */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+       mov     x29, lr                 /* Save LR */
+       bl      get_gic_offset
+       bl      gic_kick_secondary_cpus
+       mov     lr, x29                 /* Restore LR */
+#endif
+       ret
+ENDPROC(smp_kick_all_cpus)
+
 
 ENTRY(lowlevel_init)
        mov     x29, lr                 /* Save LR */
 
-#ifdef CONFIG_FSL_LSCH3
+       switch_el x1, 1f, 100f, 100f    /* skip if not in EL3 */
+1:
+
+#if defined (CONFIG_SYS_FSL_HAS_CCN504)
 
        /* Set Wuo bit for RN-I 20 */
-#ifdef CONFIG_LS2080A
+#ifdef CONFIG_ARCH_LS2080A
        ldr     x0, =CCI_AUX_CONTROL_BASE(20)
        ldr     x1, =0x00000010
        bl      ccn504_set_aux
+
+       /*
+        * Set forced-order mode in RNI-6, RNI-20
+        * This is required for performance optimization on LS2088A
+        * LS2080A family does not support setting forced-order mode,
+        * so skip this operation for LS2080A family
+        */
+       bl      get_svr
+       lsr     w0, w0, #16
+       ldr     w1, =SVR_DEV(SVR_LS2080A)
+       cmp     w0, w1
+       b.eq    1f
+
+       ldr     x0, =CCI_AUX_CONTROL_BASE(6)
+       ldr     x1, =0x00000020
+       bl      ccn504_set_aux
+       ldr     x0, =CCI_AUX_CONTROL_BASE(20)
+       ldr     x1, =0x00000020
+       bl      ccn504_set_aux
+1:
 #endif
 
        /* Add fully-coherent masters to DVM domain */
@@ -92,7 +169,7 @@ ENTRY(lowlevel_init)
        ldr     x0, =CCI_S2_QOS_CONTROL_BASE(20)
        ldr     x1, =0x00FF000C
        bl      ccn504_set_qos
-#endif
+#endif /* CONFIG_SYS_FSL_HAS_CCN504 */
 
 #ifdef SMMU_BASE
        /* Set the SMMU page size in the sACR register */
@@ -105,19 +182,19 @@ ENTRY(lowlevel_init)
        /* Initialize GIC Secure Bank Status */
 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
        branch_if_slave x0, 1f
-       ldr     x0, =GICD_BASE
+       bl      get_gic_offset
        bl      gic_init_secure
 1:
 #ifdef CONFIG_GICV3
        ldr     x0, =GICR_BASE
        bl      gic_init_secure_percpu
 #elif defined(CONFIG_GICV2)
-       ldr     x0, =GICD_BASE
-       ldr     x1, =GICC_BASE
+       bl      get_gic_offset
        bl      gic_init_secure_percpu
 #endif
 #endif
 
+100:
        branch_if_master x0, x1, 2f
 
 #if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY)
@@ -126,6 +203,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 */
@@ -137,6 +216,16 @@ ENTRY(lowlevel_init)
 #endif
 
 #ifdef CONFIG_FSL_TZASC_400
+       /*
+        * LS2080 and its personalities does not support TZASC
+        * So skip TZASC related operations
+        */
+       bl      get_svr
+       lsr     w0, w0, #16
+       ldr     w1, =SVR_DEV(SVR_LS2080A)
+       cmp     w0, w1
+       b.eq    1f
+
        /* Set TZASC so that:
         * a. We use only Region0 whose global secure write/read is EN
         * b. We use only Region0 whose NSAID write/read is EN
@@ -144,46 +233,112 @@ ENTRY(lowlevel_init)
         * NOTE: As per the CCSR map doc, TZASC 3 and TZASC 4 are just
         *       placeholders.
         */
+#ifdef CONFIG_FSL_TZASC_1
        ldr     x1, =TZASC_GATE_KEEPER(0)
-       ldr     x0, [x1]                /* Filter 0 Gate Keeper Register */
-       orr     x0, x0, #1 << 0         /* Set open_request for Filter 0 */
-       str     x0, [x1]
-
-       ldr     x1, =TZASC_GATE_KEEPER(1)
-       ldr     x0, [x1]                /* Filter 0 Gate Keeper Register */
-       orr     x0, x0, #1 << 0         /* Set open_request for Filter 0 */
-       str     x0, [x1]
+       ldr     w0, [x1]                /* Filter 0 Gate Keeper Register */
+       orr     w0, w0, #1 << 0         /* Set open_request for Filter 0 */
+       str     w0, [x1]
 
        ldr     x1, =TZASC_REGION_ATTRIBUTES_0(0)
-       ldr     x0, [x1]                /* Region-0 Attributes Register */
-       orr     x0, x0, #1 << 31        /* Set Sec global write en, Bit[31] */
-       orr     x0, x0, #1 << 30        /* Set Sec global read en, Bit[30] */
-       str     x0, [x1]
-
-       ldr     x1, =TZASC_REGION_ATTRIBUTES_0(1)
-       ldr     x0, [x1]                /* Region-1 Attributes Register */
-       orr     x0, x0, #1 << 31        /* Set Sec global write en, Bit[31] */
-       orr     x0, x0, #1 << 30        /* Set Sec global read en, Bit[30] */
-       str     x0, [x1]
+       ldr     w0, [x1]                /* Region-0 Attributes Register */
+       orr     w0, w0, #1 << 31        /* Set Sec global write en, Bit[31] */
+       orr     w0, w0, #1 << 30        /* Set Sec global read en, Bit[30] */
+       str     w0, [x1]
 
        ldr     x1, =TZASC_REGION_ID_ACCESS_0(0)
        ldr     w0, [x1]                /* Region-0 Access Register */
        mov     w0, #0xFFFFFFFF         /* Set nsaid_wr_en and nsaid_rd_en */
        str     w0, [x1]
+#endif
+#ifdef CONFIG_FSL_TZASC_2
+       ldr     x1, =TZASC_GATE_KEEPER(1)
+       ldr     w0, [x1]                /* Filter 0 Gate Keeper Register */
+       orr     w0, w0, #1 << 0         /* Set open_request for Filter 0 */
+       str     w0, [x1]
+
+       ldr     x1, =TZASC_REGION_ATTRIBUTES_0(1)
+       ldr     w0, [x1]                /* Region-1 Attributes Register */
+       orr     w0, w0, #1 << 31        /* Set Sec global write en, Bit[31] */
+       orr     w0, w0, #1 << 30        /* Set Sec global read en, Bit[30] */
+       str     w0, [x1]
 
        ldr     x1, =TZASC_REGION_ID_ACCESS_0(1)
        ldr     w0, [x1]                /* Region-1 Attributes Register */
        mov     w0, #0xFFFFFFFF         /* Set nsaid_wr_en and nsaid_rd_en */
        str     w0, [x1]
-
+#endif
        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
+       /* Clear L2 Tag RAM latency and L2 Data RAM latency */
+       bic   x1, x1, x0
+       /* Set L2 data ram latency bits [2:0] */
+       orr   x1, x1, #0x2
+       /* set L2 tag ram latency bits [8:6] */
+       orr   x1,  x1, #0x80
+       msr   S3_1_c11_c0_2, x1
+       isb
+100:
+#endif
+
+#if defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD)
+       bl      fsl_ocram_init
+#endif
+
        mov     lr, x29                 /* Restore LR */
        ret
 ENDPROC(lowlevel_init)
 
+#if defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD)
+ENTRY(fsl_ocram_init)
+       mov     x28, lr                 /* Save LR */
+       bl      fsl_clear_ocram
+       bl      fsl_ocram_clear_ecc_err
+       mov     lr, x28                 /* Restore LR */
+       ret
+ENDPROC(fsl_ocram_init)
+
+ENTRY(fsl_clear_ocram)
+/* Clear OCRAM */
+       ldr     x0, =CONFIG_SYS_FSL_OCRAM_BASE
+       ldr     x1, =(CONFIG_SYS_FSL_OCRAM_BASE + CONFIG_SYS_FSL_OCRAM_SIZE)
+       mov     x2, #0
+clear_loop:
+       str     x2, [x0]
+       add     x0, x0, #8
+       cmp     x0, x1
+       b.lo    clear_loop
+       ret
+ENDPROC(fsl_clear_ocram)
+
+ENTRY(fsl_ocram_clear_ecc_err)
+       /* OCRAM1/2 ECC status bit */
+       mov     w1, #0x60
+       ldr     x0, =DCSR_DCFG_SBEESR2
+       str     w1, [x0]
+       ldr     x0, =DCSR_DCFG_MBEESR2
+       str     w1, [x0]
+       ret
+ENDPROC(fsl_ocram_init)
+#endif
+
 #ifdef CONFIG_FSL_LSCH3
+       .globl get_svr
+get_svr:
+       ldr     x1, =FSL_LSCH3_SVR
+       ldr     w0, [x1]
+       ret
+#endif
+
+#ifdef CONFIG_SYS_FSL_HAS_CCN504
 hnf_pstate_poll:
        /* x0 has the desired status, return 0 for success, 1 for timeout
         * clobber x1, x2, x3, x4, x6, x7
@@ -230,11 +385,11 @@ hnf_set_pstate:
 
        ret
 
-ENTRY(__asm_flush_l3_cache)
+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
@@ -260,8 +415,8 @@ ENTRY(__asm_flush_l3_cache)
        mov     x0, x8
        mov     lr, x29
        ret
-ENDPROC(__asm_flush_l3_cache)
-#endif
+ENDPROC(__asm_flush_l3_dcache)
+#endif /* CONFIG_SYS_FSL_HAS_CCN504 */
 
 #ifdef CONFIG_MP
        /* Keep literals not used by the secondary boot code outside it */
@@ -320,15 +475,11 @@ ENTRY(secondary_boot_func)
 #if defined(CONFIG_GICV3)
        gic_wait_for_interrupt_m x0
 #elif defined(CONFIG_GICV2)
-        ldr     x0, =GICC_BASE
+       bl      get_gic_offset
+       mov     x0, x1
         gic_wait_for_interrupt_m x0, w1
 #endif
 
-       bl secondary_switch_to_el2
-#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
-       bl secondary_switch_to_el1
-#endif
-
 slave_cpu:
        wfe
        ldr     x0, [x11]
@@ -341,19 +492,60 @@ slave_cpu:
        tbz     x1, #25, cpu_is_le
        rev     x0, x0                  /* BE to LE conversion */
 cpu_is_le:
-       br      x0                      /* branch to the given address */
+       ldr     x5, [x11, #24]
+       cbz     x5, 1f
+
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+       adr     x4, secondary_switch_to_el1
+       ldr     x5, =ES_TO_AARCH64
+#else
+       ldr     x4, [x11]
+       ldr     x5, =ES_TO_AARCH32
+#endif
+       bl      secondary_switch_to_el2
+
+1:
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+       adr     x4, secondary_switch_to_el1
+#else
+       ldr     x4, [x11]
+#endif
+       ldr     x5, =ES_TO_AARCH64
+       bl      secondary_switch_to_el2
+
 ENDPROC(secondary_boot_func)
 
 ENTRY(secondary_switch_to_el2)
-       switch_el x0, 1f, 0f, 0f
+       switch_el x6, 1f, 0f, 0f
 0:     ret
-1:     armv8_switch_to_el2_m x0
+1:     armv8_switch_to_el2_m x4, x5, x6
 ENDPROC(secondary_switch_to_el2)
 
 ENTRY(secondary_switch_to_el1)
-       switch_el x0, 0f, 1f, 0f
+       mrs     x0, mpidr_el1
+       ubfm    x1, x0, #8, #15
+       ubfm    x2, x0, #0, #1
+       orr     x10, x2, x1, lsl #2     /* x10 has LPID */
+
+       lsl     x1, x10, #6
+       ldr     x0, =__spin_table
+       /* physical address of this cpus spin table element */
+       add     x11, x1, x0
+
+       ldr     x4, [x11]
+
+       ldr     x5, [x11, #24]
+       cbz     x5, 2f
+
+       ldr     x5, =ES_TO_AARCH32
+       bl      switch_to_el1
+
+2:     ldr     x5, =ES_TO_AARCH64
+
+switch_to_el1:
+       switch_el x6, 0f, 1f, 0f
 0:     ret
-1:     armv8_switch_to_el1_m x0, x1
+1:     armv8_switch_to_el1_m x4, x5, x6
 ENDPROC(secondary_switch_to_el1)
 
        /* Ensure that the literals used by the secondary boot code are