1 /* 2 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 10 #include <common/fdt_fixup.h> 11 #include <common/fdt_wrappers.h> 12 #include <drivers/arm/gicv3.h> 13 #include <drivers/delay_timer.h> 14 #include <drivers/generic_delay_timer.h> 15 #include <lib/extensions/spe.h> 16 #include <libfdt.h> 17 18 #include "fpga_private.h" 19 #include <plat/common/platform.h> 20 #include <platform_def.h> 21 22 static entry_point_info_t bl33_image_ep_info; 23 volatile uint32_t secondary_core_spinlock; 24 25 uintptr_t plat_get_ns_image_entrypoint(void) 26 { 27 #ifdef PRELOADED_BL33_BASE 28 return PRELOADED_BL33_BASE; 29 #else 30 return 0ULL; 31 #endif 32 } 33 34 uint32_t fpga_get_spsr_for_bl33_entry(void) 35 { 36 return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 37 } 38 39 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 40 u_register_t arg2, u_register_t arg3) 41 { 42 /* Add this core to the VALID mpids list */ 43 fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID; 44 45 /* 46 * Notify the secondary CPUs that the C runtime is ready 47 * so they can announce themselves. 48 */ 49 secondary_core_spinlock = C_RUNTIME_READY_KEY; 50 dsbish(); 51 sev(); 52 53 fpga_console_init(); 54 55 bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); 56 bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry(); 57 SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 58 59 /* Set x0-x3 for the primary CPU as expected by the kernel */ 60 bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE; 61 bl33_image_ep_info.args.arg1 = 0U; 62 bl33_image_ep_info.args.arg2 = 0U; 63 bl33_image_ep_info.args.arg3 = 0U; 64 } 65 66 void bl31_plat_arch_setup(void) 67 { 68 } 69 70 void bl31_platform_setup(void) 71 { 72 /* Write frequency to CNTCRL and initialize timer */ 73 generic_delay_timer_init(); 74 75 /* 76 * Before doing anything else, wait for some time to ensure that 77 * the secondary CPUs have populated the fpga_valid_mpids array. 78 * As the number of secondary cores is unknown and can even be 0, 79 * it is not possible to rely on any signal from them, so use a 80 * delay instead. 81 */ 82 mdelay(5); 83 84 /* 85 * On the event of a cold reset issued by, for instance, a reset pin 86 * assertion, we cannot guarantee memory to be initialized to zero. 87 * In such scenario, if the secondary cores reached 88 * plat_secondary_cold_boot_setup before the primary one initialized 89 * .BSS, we could end up having a race condition if the spinlock 90 * was not cleared before. 91 * 92 * Similarly, if there were a reset before the spinlock had been 93 * cleared, the secondary cores would find the lock opened before 94 * .BSS is cleared, causing another race condition. 95 * 96 * So clean the spinlock as soon as we think it is safe to reduce the 97 * chances of any race condition on a reset. 98 */ 99 secondary_core_spinlock = 0UL; 100 101 /* Initialize the GIC driver, cpu and distributor interfaces */ 102 plat_fpga_gic_init(); 103 } 104 105 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) 106 { 107 entry_point_info_t *next_image_info; 108 next_image_info = &bl33_image_ep_info; 109 110 /* Only expecting BL33: the kernel will run in EL2NS */ 111 assert(type == NON_SECURE); 112 113 /* None of the images can have 0x0 as the entrypoint */ 114 if (next_image_info->pc) { 115 return next_image_info; 116 } else { 117 return NULL; 118 } 119 } 120 121 unsigned int plat_get_syscnt_freq2(void) 122 { 123 const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 124 int node; 125 126 node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer"); 127 if (node < 0) { 128 return FPGA_DEFAULT_TIMER_FREQUENCY; 129 } 130 131 return fdt_read_uint32_default(fdt, node, "clock-frequency", 132 FPGA_DEFAULT_TIMER_FREQUENCY); 133 } 134 135 static void fpga_prepare_dtb(void) 136 { 137 void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 138 const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE; 139 int err; 140 141 err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE); 142 if (err < 0) { 143 ERROR("cannot open devicetree at %p: %d\n", fdt, err); 144 panic(); 145 } 146 147 /* Reserve memory used by Trusted Firmware. */ 148 if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE, 149 BL31_LIMIT - BL31_BASE)) { 150 WARN("Failed to add reserved memory node to DT\n"); 151 } 152 153 /* Check for the command line signature. */ 154 if (!strncmp(cmdline, "CMD:", 4)) { 155 int chosen; 156 157 INFO("using command line at 0x%x\n", FPGA_PRELOADED_CMD_LINE); 158 159 chosen = fdt_add_subnode(fdt, 0, "chosen"); 160 if (chosen == -FDT_ERR_EXISTS) { 161 chosen = fdt_path_offset(fdt, "/chosen"); 162 } 163 if (chosen < 0) { 164 ERROR("cannot find /chosen node: %d\n", chosen); 165 } else { 166 const char *eol; 167 char nul = 0; 168 int slen; 169 170 /* 171 * There is most likely an EOL at the end of the 172 * command line, make sure we terminate the line there. 173 * We can't replace the EOL with a NUL byte in the 174 * source, as this is in read-only memory. So we first 175 * create the property without any termination, then 176 * append a single NUL byte. 177 */ 178 eol = strchr(cmdline, '\n'); 179 if (!eol) { 180 eol = strchr(cmdline, 0); 181 } 182 /* Skip the signature and omit the EOL/NUL byte. */ 183 slen = eol - (cmdline + 4); 184 185 /* 186 * Let's limit the size of the property, just in case 187 * we find the signature by accident. The Linux kernel 188 * limits to 4096 characters at most (in fact 2048 for 189 * arm64), so that sounds like a reasonable number. 190 */ 191 if (slen > 4095) { 192 slen = 4095; 193 } 194 err = fdt_setprop(fdt, chosen, "bootargs", 195 cmdline + 4, slen); 196 if (!err) { 197 err = fdt_appendprop(fdt, chosen, "bootargs", 198 &nul, 1); 199 } 200 if (err) { 201 ERROR("Could not set command line: %d\n", err); 202 } 203 } 204 } 205 206 if (err < 0) { 207 ERROR("Error %d extending Device Tree\n", err); 208 panic(); 209 } 210 211 err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU, 212 FPGA_MAX_CPUS_PER_CLUSTER, 213 FPGA_MAX_CLUSTER_COUNT); 214 215 if (err == -EEXIST) { 216 WARN("Not overwriting already existing /cpus node in DTB\n"); 217 } else { 218 if (err < 0) { 219 ERROR("Error %d creating the /cpus DT node\n", err); 220 panic(); 221 } else { 222 unsigned int nr_cores = fpga_get_nr_gic_cores(); 223 224 INFO("Adjusting GICR DT region to cover %u cores\n", 225 nr_cores); 226 err = fdt_adjust_gic_redist(fdt, nr_cores, 227 fpga_get_redist_base(), 228 fpga_get_redist_size()); 229 if (err < 0) { 230 ERROR("Error %d fixing up GIC DT node\n", err); 231 } 232 } 233 } 234 235 /* Check whether we support the SPE PMU. Remove the DT node if not. */ 236 if (!spe_supported()) { 237 int node = fdt_node_offset_by_compatible(fdt, 0, 238 "arm,statistical-profiling-extension-v1"); 239 240 if (node >= 0) { 241 fdt_del_node(fdt, node); 242 } 243 } 244 245 err = fdt_pack(fdt); 246 if (err < 0) { 247 ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err); 248 } 249 250 clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); 251 } 252 253 void bl31_plat_runtime_setup(void) 254 { 255 fpga_prepare_dtb(); 256 } 257 258 void bl31_plat_enable_mmu(uint32_t flags) 259 { 260 /* TODO: determine if MMU needs to be enabled */ 261 } 262