1/* 2 * Copyright (c) 2020, 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 <common/bl_common.h> 10#include "../fpga_private.h" 11 12#include <platform_def.h> 13 14 .globl plat_get_my_entrypoint 15 .globl plat_secondary_cold_boot_setup 16 .globl plat_is_my_cpu_primary 17 .globl platform_mem_init 18 .globl plat_my_core_pos 19 .globl plat_crash_console_init 20 .globl plat_crash_console_putc 21 .globl plat_crash_console_flush 22 .globl plat_fpga_calc_core_pos 23 24/* ----------------------------------------------------------------------- 25 * Indicate a cold boot for every CPU - warm boot is unsupported for the 26 * holding pen PSCI implementation. 27 * ----------------------------------------------------------------------- 28 */ 29func plat_get_my_entrypoint 30 mov x0, #0 31 ret 32endfunc plat_get_my_entrypoint 33 34/* ----------------------------------------------------------------------- 35 * void plat_secondary_cold_boot_setup (void); 36 * ----------------------------------------------------------------------- 37 */ 38func plat_secondary_cold_boot_setup 39 40 /* 41 * Wait for the primary processor to initialise the .BSS segment 42 * to avoid a race condition that would erase fpga_valid_mpids 43 * if it is populated before the C runtime is ready. 44 * 45 * We cannot use the current spin-lock implementation until the 46 * runtime is up and we should not rely on sevl/wfe instructions as 47 * it is optional whether they are implemented or not, so we use 48 * a global variable as lock and wait for the primary processor to 49 * finish the C runtime bring-up. 50 */ 51 52 ldr w0, =C_RUNTIME_READY_KEY 53 adrp x1, secondary_core_spinlock 54 add x1, x1, :lo12:secondary_core_spinlock 551: 56 wfe 57 ldr w2, [x1] 58 cmp w2, w0 59 b.ne 1b 60 /* Prevent reordering of the store into fpga_valid_mpids below */ 61 dmb ish 62 63 mov x10, x30 64 bl plat_my_core_pos 65 mov x30, x10 66 67 adrp x4, fpga_valid_mpids 68 add x4, x4, :lo12:fpga_valid_mpids 69 mov x5, #VALID_MPID 70 strb w5, [x4, x0] 71 72 /* 73 * Poll the CPU's hold entry until it indicates to jump 74 * to the entrypoint address. 75 */ 76 77 adrp x1, hold_base 78 add x1, x1, :lo12:hold_base 79poll_hold_entry: 80 ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT] 81 cmp x3, #PLAT_FPGA_HOLD_STATE_GO 82 b.ne 1f 83 84 adrp x2, fpga_sec_entrypoint 85 add x2, x2, :lo12:fpga_sec_entrypoint 86 ldr x3, [x2] 87 br x3 881: 89 wfe 90 b poll_hold_entry 91 92endfunc plat_secondary_cold_boot_setup 93 94/* ----------------------------------------------------------------------- 95 * unsigned int plat_is_my_cpu_primary (void); 96 * 97 * Find out whether the current cpu is the primary cpu 98 * ----------------------------------------------------------------------- 99 */ 100func plat_is_my_cpu_primary 101 mrs x0, mpidr_el1 102 mov_imm x1, MPIDR_AFFINITY_MASK 103 and x0, x0, x1 104 cmp x0, #FPGA_PRIMARY_CPU 105 cset w0, eq 106 ret 107endfunc plat_is_my_cpu_primary 108 109func platform_mem_init 110 ret 111endfunc platform_mem_init 112 113func plat_my_core_pos 114 ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)) 115 mrs x0, mpidr_el1 116 and x0, x0, x1 117 b plat_fpga_calc_core_pos 118 119endfunc plat_my_core_pos 120 121/* ----------------------------------------------------------------------- 122 * unsigned int plat_fpga_calc_core_pos (uint32_t mpid) 123 * Clobber registers: x0 to x5 124 * ----------------------------------------------------------------------- 125 */ 126func plat_fpga_calc_core_pos 127 /* 128 * Check for MT bit in MPIDR, which may be either value for images 129 * running on the FPGA. 130 * 131 * If not set, shift MPIDR to left to make it look as if in a 132 * multi-threaded implementation. 133 * 134 */ 135 tst x0, #MPIDR_MT_MASK 136 lsl x3, x0, #MPIDR_AFFINITY_BITS 137 csel x3, x3, x0, eq 138 139 /* Extract individual affinity fields from MPIDR */ 140 ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS 141 ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS 142 ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS 143 144 mov x4, #FPGA_MAX_CPUS_PER_CLUSTER 145 mov x5, #FPGA_MAX_PE_PER_CPU 146 147 /* Compute linear position */ 148 madd x1, x2, x4, x1 149 madd x0, x1, x5, x0 150 151 ret 152endfunc plat_fpga_calc_core_pos 153 154func plat_crash_console_init 155 mov_imm x0, PLAT_FPGA_CRASH_UART_BASE 156 b console_pl011_core_init 157endfunc plat_crash_console_init 158 159func plat_crash_console_putc 160 mov_imm x1, PLAT_FPGA_CRASH_UART_BASE 161 b console_pl011_core_putc 162endfunc plat_crash_console_putc 163 164func plat_crash_console_flush 165 mov_imm x0, PLAT_FPGA_CRASH_UART_BASE 166 b console_pl011_core_flush 167endfunc plat_crash_console_flush 168