You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
4.3 KiB
167 lines
4.3 KiB
/*
|
|
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <arch.h>
|
|
#include <asm_macros.S>
|
|
#include <common/bl_common.h>
|
|
#include "../fpga_private.h"
|
|
|
|
#include <platform_def.h>
|
|
|
|
.globl plat_get_my_entrypoint
|
|
.globl plat_secondary_cold_boot_setup
|
|
.globl plat_is_my_cpu_primary
|
|
.globl platform_mem_init
|
|
.globl plat_my_core_pos
|
|
.globl plat_crash_console_init
|
|
.globl plat_crash_console_putc
|
|
.globl plat_crash_console_flush
|
|
.globl plat_fpga_calc_core_pos
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* Indicate a cold boot for every CPU - warm boot is unsupported for the
|
|
* holding pen PSCI implementation.
|
|
* -----------------------------------------------------------------------
|
|
*/
|
|
func plat_get_my_entrypoint
|
|
mov x0, #0
|
|
ret
|
|
endfunc plat_get_my_entrypoint
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* void plat_secondary_cold_boot_setup (void);
|
|
* -----------------------------------------------------------------------
|
|
*/
|
|
func plat_secondary_cold_boot_setup
|
|
|
|
/*
|
|
* Wait for the primary processor to initialise the .BSS segment
|
|
* to avoid a race condition that would erase fpga_valid_mpids
|
|
* if it is populated before the C runtime is ready.
|
|
*
|
|
* We cannot use the current spin-lock implementation until the
|
|
* runtime is up and we should not rely on sevl/wfe instructions as
|
|
* it is optional whether they are implemented or not, so we use
|
|
* a global variable as lock and wait for the primary processor to
|
|
* finish the C runtime bring-up.
|
|
*/
|
|
|
|
ldr w0, =C_RUNTIME_READY_KEY
|
|
adrp x1, secondary_core_spinlock
|
|
add x1, x1, :lo12:secondary_core_spinlock
|
|
1:
|
|
wfe
|
|
ldr w2, [x1]
|
|
cmp w2, w0
|
|
b.ne 1b
|
|
/* Prevent reordering of the store into fpga_valid_mpids below */
|
|
dmb ish
|
|
|
|
mov x10, x30
|
|
bl plat_my_core_pos
|
|
mov x30, x10
|
|
|
|
adrp x4, fpga_valid_mpids
|
|
add x4, x4, :lo12:fpga_valid_mpids
|
|
mov x5, #VALID_MPID
|
|
strb w5, [x4, x0]
|
|
|
|
/*
|
|
* Poll the CPU's hold entry until it indicates to jump
|
|
* to the entrypoint address.
|
|
*/
|
|
|
|
adrp x1, hold_base
|
|
add x1, x1, :lo12:hold_base
|
|
poll_hold_entry:
|
|
ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
|
|
cmp x3, #PLAT_FPGA_HOLD_STATE_GO
|
|
b.ne 1f
|
|
|
|
adrp x2, fpga_sec_entrypoint
|
|
add x2, x2, :lo12:fpga_sec_entrypoint
|
|
ldr x3, [x2]
|
|
br x3
|
|
1:
|
|
wfe
|
|
b poll_hold_entry
|
|
|
|
endfunc plat_secondary_cold_boot_setup
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* unsigned int plat_is_my_cpu_primary (void);
|
|
*
|
|
* Find out whether the current cpu is the primary cpu
|
|
* -----------------------------------------------------------------------
|
|
*/
|
|
func plat_is_my_cpu_primary
|
|
mrs x0, mpidr_el1
|
|
mov_imm x1, MPIDR_AFFINITY_MASK
|
|
and x0, x0, x1
|
|
cmp x0, #FPGA_PRIMARY_CPU
|
|
cset w0, eq
|
|
ret
|
|
endfunc plat_is_my_cpu_primary
|
|
|
|
func platform_mem_init
|
|
ret
|
|
endfunc platform_mem_init
|
|
|
|
func plat_my_core_pos
|
|
ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
|
|
mrs x0, mpidr_el1
|
|
and x0, x0, x1
|
|
b plat_fpga_calc_core_pos
|
|
|
|
endfunc plat_my_core_pos
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
|
|
* Clobber registers: x0 to x5
|
|
* -----------------------------------------------------------------------
|
|
*/
|
|
func plat_fpga_calc_core_pos
|
|
/*
|
|
* Check for MT bit in MPIDR, which may be either value for images
|
|
* running on the FPGA.
|
|
*
|
|
* If not set, shift MPIDR to left to make it look as if in a
|
|
* multi-threaded implementation.
|
|
*
|
|
*/
|
|
tst x0, #MPIDR_MT_MASK
|
|
lsl x3, x0, #MPIDR_AFFINITY_BITS
|
|
csel x3, x3, x0, eq
|
|
|
|
/* Extract individual affinity fields from MPIDR */
|
|
ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
|
ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
|
ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
|
|
|
mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
|
|
mov x5, #FPGA_MAX_PE_PER_CPU
|
|
|
|
/* Compute linear position */
|
|
madd x1, x2, x4, x1
|
|
madd x0, x1, x5, x0
|
|
|
|
ret
|
|
endfunc plat_fpga_calc_core_pos
|
|
|
|
func plat_crash_console_init
|
|
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
|
b console_pl011_core_init
|
|
endfunc plat_crash_console_init
|
|
|
|
func plat_crash_console_putc
|
|
mov_imm x1, PLAT_FPGA_CRASH_UART_BASE
|
|
b console_pl011_core_putc
|
|
endfunc plat_crash_console_putc
|
|
|
|
func plat_crash_console_flush
|
|
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
|
b console_pl011_core_flush
|
|
endfunc plat_crash_console_flush
|
|
|