Home | History | Annotate | Download | only in aarch64
      1 /*
      2  * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 
      7 #include <arch.h>
      8 #include <asm_macros.S>
      9 #include <gicv2.h>
     10 #include <gicv3.h>
     11 #include <platform_def.h>
     12 #include <v2m_def.h>
     13 #include "../drivers/pwrc/fvp_pwrc.h"
     14 #include "../fvp_def.h"
     15 
     16 	.globl	plat_secondary_cold_boot_setup
     17 	.globl	plat_get_my_entrypoint
     18 	.globl	plat_is_my_cpu_primary
     19 	.globl	plat_arm_calc_core_pos
     20 
     21 	.macro	fvp_choose_gicmmap  param1, param2, x_tmp, w_tmp, res
     22 	ldr	\x_tmp, =V2M_SYSREGS_BASE + V2M_SYS_ID
     23 	ldr	\w_tmp, [\x_tmp]
     24 	ubfx	\w_tmp, \w_tmp, #V2M_SYS_ID_BLD_SHIFT, #V2M_SYS_ID_BLD_LENGTH
     25 	cmp	\w_tmp, #BLD_GIC_VE_MMAP
     26 	csel	\res, \param1, \param2, eq
     27 	.endm
     28 
     29 	/* -----------------------------------------------------
     30 	 * void plat_secondary_cold_boot_setup (void);
     31 	 *
     32 	 * This function performs any platform specific actions
     33 	 * needed for a secondary cpu after a cold reset e.g
     34 	 * mark the cpu's presence, mechanism to place it in a
     35 	 * holding pen etc.
     36 	 * TODO: Should we read the PSYS register to make sure
     37 	 * that the request has gone through.
     38 	 * -----------------------------------------------------
     39 	 */
     40 func plat_secondary_cold_boot_setup
     41 #ifndef EL3_PAYLOAD_BASE
     42 	/* ---------------------------------------------
     43 	 * Power down this cpu.
     44 	 * TODO: Do we need to worry about powering the
     45 	 * cluster down as well here. That will need
     46 	 * locks which we won't have unless an elf-
     47 	 * loader zeroes out the zi section.
     48 	 * ---------------------------------------------
     49 	 */
     50 	mrs	x0, mpidr_el1
     51 	ldr	x1, =PWRC_BASE
     52 	str	w0, [x1, #PPOFFR_OFF]
     53 
     54 	/* ---------------------------------------------
     55 	 * Disable GIC bypass as well
     56 	 * ---------------------------------------------
     57 	 */
     58 	/* Check for GICv3 system register access */
     59 	mrs	x0, id_aa64pfr0_el1
     60 	ubfx	x0, x0, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
     61 	cmp	x0, #1
     62 	b.ne	gicv2_bypass_disable
     63 
     64 	/* Check for SRE enable */
     65 	mrs	x1, ICC_SRE_EL3
     66 	tst	x1, #ICC_SRE_SRE_BIT
     67 	b.eq	gicv2_bypass_disable
     68 
     69 	mrs	x2, ICC_SRE_EL3
     70 	orr	x2, x2, #(ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)
     71 	msr	ICC_SRE_EL3, x2
     72 	b	secondary_cold_boot_wait
     73 
     74 gicv2_bypass_disable:
     75 	ldr	x0, =VE_GICC_BASE
     76 	ldr	x1, =BASE_GICC_BASE
     77 	fvp_choose_gicmmap	x0, x1, x2, w2, x1
     78 	mov	w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
     79 	orr	w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
     80 	str	w0, [x1, #GICC_CTLR]
     81 
     82 secondary_cold_boot_wait:
     83 	/* ---------------------------------------------
     84 	 * There is no sane reason to come out of this
     85 	 * wfi so panic if we do. This cpu will be pow-
     86 	 * ered on and reset by the cpu_on pm api
     87 	 * ---------------------------------------------
     88 	 */
     89 	dsb	sy
     90 	wfi
     91 	no_ret	plat_panic_handler
     92 #else
     93 	mov_imm	x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
     94 
     95 	/* Wait until the entrypoint gets populated */
     96 poll_mailbox:
     97 	ldr	x1, [x0]
     98 	cbz	x1, 1f
     99 	br	x1
    100 1:
    101 	wfe
    102 	b	poll_mailbox
    103 #endif /* EL3_PAYLOAD_BASE */
    104 endfunc plat_secondary_cold_boot_setup
    105 
    106 	/* ---------------------------------------------------------------------
    107 	 * uintptr_t plat_get_my_entrypoint (void);
    108 	 *
    109 	 * Main job of this routine is to distinguish between a cold and warm
    110 	 * boot. On FVP, this information can be queried from the power
    111 	 * controller. The Power Control SYS Status Register (PSYSR) indicates
    112 	 * the wake-up reason for the CPU.
    113 	 *
    114 	 * For a cold boot, return 0.
    115 	 * For a warm boot, read the mailbox and return the address it contains.
    116 	 *
    117 	 * TODO: PSYSR is a common register and should be
    118 	 * 	accessed using locks. Since it is not possible
    119 	 * 	to use locks immediately after a cold reset
    120 	 * 	we are relying on the fact that after a cold
    121 	 * 	reset all cpus will read the same WK field
    122 	 * ---------------------------------------------------------------------
    123 	 */
    124 func plat_get_my_entrypoint
    125 	/* ---------------------------------------------------------------------
    126 	 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
    127 	 * WakeRequest signal" then it is a warm boot.
    128 	 * ---------------------------------------------------------------------
    129 	 */
    130 	mrs	x2, mpidr_el1
    131 	ldr	x1, =PWRC_BASE
    132 	str	w2, [x1, #PSYSR_OFF]
    133 	ldr	w2, [x1, #PSYSR_OFF]
    134 	ubfx	w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
    135 	cmp	w2, #WKUP_PPONR
    136 	beq	warm_reset
    137 	cmp	w2, #WKUP_GICREQ
    138 	beq	warm_reset
    139 
    140 	/* Cold reset */
    141 	mov	x0, #0
    142 	ret
    143 
    144 warm_reset:
    145 	/* ---------------------------------------------------------------------
    146 	 * A mailbox is maintained in the trusted SRAM. It is flushed out of the
    147 	 * caches after every update using normal memory so it is safe to read
    148 	 * it here with SO attributes.
    149 	 * ---------------------------------------------------------------------
    150 	 */
    151 	mov_imm	x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
    152 	ldr	x0, [x0]
    153 	cbz	x0, _panic_handler
    154 	ret
    155 
    156 	/* ---------------------------------------------------------------------
    157 	 * The power controller indicates this is a warm reset but the mailbox
    158 	 * is empty. This should never happen!
    159 	 * ---------------------------------------------------------------------
    160 	 */
    161 _panic_handler:
    162 	no_ret	plat_panic_handler
    163 endfunc plat_get_my_entrypoint
    164 
    165 	/* -----------------------------------------------------
    166 	 * unsigned int plat_is_my_cpu_primary (void);
    167 	 *
    168 	 * Find out whether the current cpu is the primary
    169 	 * cpu.
    170 	 * -----------------------------------------------------
    171 	 */
    172 func plat_is_my_cpu_primary
    173 	mrs	x0, mpidr_el1
    174 	ldr	x1, =MPIDR_AFFINITY_MASK
    175 	and	x0, x0, x1
    176 	cmp	x0, #FVP_PRIMARY_CPU
    177 	cset	w0, eq
    178 	ret
    179 endfunc plat_is_my_cpu_primary
    180 
    181 	/* -----------------------------------------------------
    182 	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
    183 	 *
    184 	 * Function to calculate the core position on FVP.
    185 	 *
    186 	 * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) +
    187 	 * (CPUId * FVP_MAX_PE_PER_CPU) +
    188 	 * ThreadId
    189 	 * -----------------------------------------------------
    190 	 */
    191 func plat_arm_calc_core_pos
    192 	mov	x3, x0
    193 
    194 	/*
    195 	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
    196 	 * look as if in a multi-threaded implementation.
    197 	 */
    198 	tst	x0, #MPIDR_MT_MASK
    199 	lsl	x3, x0, #MPIDR_AFFINITY_BITS
    200 	csel	x3, x3, x0, eq
    201 
    202 	/* Extract individual affinity fields from MPIDR */
    203 	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
    204 	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
    205 	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
    206 
    207 	/* Compute linear position */
    208 	mov	x4, #FVP_MAX_PE_PER_CPU
    209 	madd	x0, x1, x4, x0
    210 	mov	x5, #FVP_MAX_CPUS_PER_CLUSTER
    211 	madd	x0, x2, x5, x0
    212 	ret
    213 endfunc plat_arm_calc_core_pos
    214