1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <arch_features.h> 11*91f16700Schasinglulu #include <common/fdt_fixup.h> 12*91f16700Schasinglulu #include <common/fdt_wrappers.h> 13*91f16700Schasinglulu #include <drivers/arm/gicv3.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <drivers/generic_delay_timer.h> 16*91f16700Schasinglulu #include <lib/extensions/spe.h> 17*91f16700Schasinglulu #include <lib/mmio.h> 18*91f16700Schasinglulu #include <libfdt.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu #include "fpga_private.h" 21*91f16700Schasinglulu #include <plat/common/platform.h> 22*91f16700Schasinglulu #include <platform_def.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu static entry_point_info_t bl33_image_ep_info; 25*91f16700Schasinglulu static unsigned int system_freq; 26*91f16700Schasinglulu volatile uint32_t secondary_core_spinlock; 27*91f16700Schasinglulu 28*91f16700Schasinglulu uintptr_t plat_get_ns_image_entrypoint(void) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu #ifdef PRELOADED_BL33_BASE 31*91f16700Schasinglulu return PRELOADED_BL33_BASE; 32*91f16700Schasinglulu #else 33*91f16700Schasinglulu return 0ULL; 34*91f16700Schasinglulu #endif 35*91f16700Schasinglulu } 36*91f16700Schasinglulu 37*91f16700Schasinglulu uint32_t fpga_get_spsr_for_bl33_entry(void) 38*91f16700Schasinglulu { 39*91f16700Schasinglulu return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 40*91f16700Schasinglulu } 41*91f16700Schasinglulu 42*91f16700Schasinglulu void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 43*91f16700Schasinglulu u_register_t arg2, u_register_t arg3) 44*91f16700Schasinglulu { 45*91f16700Schasinglulu /* Add this core to the VALID mpids list */ 46*91f16700Schasinglulu fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID; 47*91f16700Schasinglulu 48*91f16700Schasinglulu /* 49*91f16700Schasinglulu * Notify the secondary CPUs that the C runtime is ready 50*91f16700Schasinglulu * so they can announce themselves. 51*91f16700Schasinglulu */ 52*91f16700Schasinglulu secondary_core_spinlock = C_RUNTIME_READY_KEY; 53*91f16700Schasinglulu dsbish(); 54*91f16700Schasinglulu sev(); 55*91f16700Schasinglulu 56*91f16700Schasinglulu fpga_console_init(); 57*91f16700Schasinglulu 58*91f16700Schasinglulu bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); 59*91f16700Schasinglulu bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry(); 60*91f16700Schasinglulu SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 61*91f16700Schasinglulu 62*91f16700Schasinglulu /* Set x0-x3 for the primary CPU as expected by the kernel */ 63*91f16700Schasinglulu bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE; 64*91f16700Schasinglulu bl33_image_ep_info.args.arg1 = 0U; 65*91f16700Schasinglulu bl33_image_ep_info.args.arg2 = 0U; 66*91f16700Schasinglulu bl33_image_ep_info.args.arg3 = 0U; 67*91f16700Schasinglulu } 68*91f16700Schasinglulu 69*91f16700Schasinglulu void bl31_plat_arch_setup(void) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu } 72*91f16700Schasinglulu 73*91f16700Schasinglulu void bl31_platform_setup(void) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu /* Write frequency to CNTCRL and initialize timer */ 76*91f16700Schasinglulu generic_delay_timer_init(); 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* 79*91f16700Schasinglulu * Before doing anything else, wait for some time to ensure that 80*91f16700Schasinglulu * the secondary CPUs have populated the fpga_valid_mpids array. 81*91f16700Schasinglulu * As the number of secondary cores is unknown and can even be 0, 82*91f16700Schasinglulu * it is not possible to rely on any signal from them, so use a 83*91f16700Schasinglulu * delay instead. 84*91f16700Schasinglulu */ 85*91f16700Schasinglulu mdelay(5); 86*91f16700Schasinglulu 87*91f16700Schasinglulu /* 88*91f16700Schasinglulu * On the event of a cold reset issued by, for instance, a reset pin 89*91f16700Schasinglulu * assertion, we cannot guarantee memory to be initialized to zero. 90*91f16700Schasinglulu * In such scenario, if the secondary cores reached 91*91f16700Schasinglulu * plat_secondary_cold_boot_setup before the primary one initialized 92*91f16700Schasinglulu * .BSS, we could end up having a race condition if the spinlock 93*91f16700Schasinglulu * was not cleared before. 94*91f16700Schasinglulu * 95*91f16700Schasinglulu * Similarly, if there were a reset before the spinlock had been 96*91f16700Schasinglulu * cleared, the secondary cores would find the lock opened before 97*91f16700Schasinglulu * .BSS is cleared, causing another race condition. 98*91f16700Schasinglulu * 99*91f16700Schasinglulu * So clean the spinlock as soon as we think it is safe to reduce the 100*91f16700Schasinglulu * chances of any race condition on a reset. 101*91f16700Schasinglulu */ 102*91f16700Schasinglulu secondary_core_spinlock = 0UL; 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* Initialize the GIC driver, cpu and distributor interfaces */ 105*91f16700Schasinglulu plat_fpga_gic_init(); 106*91f16700Schasinglulu } 107*91f16700Schasinglulu 108*91f16700Schasinglulu entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) 109*91f16700Schasinglulu { 110*91f16700Schasinglulu entry_point_info_t *next_image_info; 111*91f16700Schasinglulu next_image_info = &bl33_image_ep_info; 112*91f16700Schasinglulu 113*91f16700Schasinglulu /* Only expecting BL33: the kernel will run in EL2NS */ 114*91f16700Schasinglulu assert(type == NON_SECURE); 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* None of the images can have 0x0 as the entrypoint */ 117*91f16700Schasinglulu if (next_image_info->pc) { 118*91f16700Schasinglulu return next_image_info; 119*91f16700Schasinglulu } else { 120*91f16700Schasinglulu return NULL; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu } 123*91f16700Schasinglulu 124*91f16700Schasinglulu /* 125*91f16700Schasinglulu * Even though we sell the FPGA UART as an SBSA variant, it is actually 126*91f16700Schasinglulu * a full fledged PL011. So the baudrate divider registers exist. 127*91f16700Schasinglulu */ 128*91f16700Schasinglulu #ifndef UARTIBRD 129*91f16700Schasinglulu #define UARTIBRD 0x024 130*91f16700Schasinglulu #define UARTFBRD 0x028 131*91f16700Schasinglulu #endif 132*91f16700Schasinglulu 133*91f16700Schasinglulu /* Round an integer to the closest multiple of a value. */ 134*91f16700Schasinglulu static unsigned int round_multiple(unsigned int x, unsigned int multiple) 135*91f16700Schasinglulu { 136*91f16700Schasinglulu if (multiple < 2) { 137*91f16700Schasinglulu return x; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu return ((x + (multiple / 2 - 1)) / multiple) * multiple; 141*91f16700Schasinglulu } 142*91f16700Schasinglulu 143*91f16700Schasinglulu #define PL011_FRAC_SHIFT 6 144*91f16700Schasinglulu #define FPGA_DEFAULT_BAUDRATE 38400 145*91f16700Schasinglulu #define PL011_OVERSAMPLING 16 146*91f16700Schasinglulu static unsigned int pl011_freq_from_divider(unsigned int divider) 147*91f16700Schasinglulu { 148*91f16700Schasinglulu unsigned int freq; 149*91f16700Schasinglulu 150*91f16700Schasinglulu freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING; 151*91f16700Schasinglulu 152*91f16700Schasinglulu return freq >> PL011_FRAC_SHIFT; 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu /* 156*91f16700Schasinglulu * The FPGAs run most peripherals from one main clock, among them the CPUs, 157*91f16700Schasinglulu * the arch timer, and the UART baud base clock. 158*91f16700Schasinglulu * The SCP knows this frequency and programs the UART clock divider for a 159*91f16700Schasinglulu * 38400 bps baudrate. Recalculate the base input clock from there. 160*91f16700Schasinglulu */ 161*91f16700Schasinglulu static unsigned int fpga_get_system_frequency(void) 162*91f16700Schasinglulu { 163*91f16700Schasinglulu const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 164*91f16700Schasinglulu int node, err; 165*91f16700Schasinglulu 166*91f16700Schasinglulu /* 167*91f16700Schasinglulu * If the arch timer DT node has an explicit clock-frequency property 168*91f16700Schasinglulu * set, use that, to allow people overriding auto-detection. 169*91f16700Schasinglulu */ 170*91f16700Schasinglulu node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer"); 171*91f16700Schasinglulu if (node >= 0) { 172*91f16700Schasinglulu uint32_t freq; 173*91f16700Schasinglulu 174*91f16700Schasinglulu err = fdt_read_uint32(fdt, node, "clock-frequency", &freq); 175*91f16700Schasinglulu if (err >= 0) { 176*91f16700Schasinglulu return freq; 177*91f16700Schasinglulu } 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); 181*91f16700Schasinglulu if (node >= 0) { 182*91f16700Schasinglulu uintptr_t pl011_base; 183*91f16700Schasinglulu unsigned int divider; 184*91f16700Schasinglulu 185*91f16700Schasinglulu err = fdt_get_reg_props_by_index(fdt, node, 0, 186*91f16700Schasinglulu &pl011_base, NULL); 187*91f16700Schasinglulu if (err >= 0) { 188*91f16700Schasinglulu divider = mmio_read_32(pl011_base + UARTIBRD); 189*91f16700Schasinglulu divider <<= PL011_FRAC_SHIFT; 190*91f16700Schasinglulu divider += mmio_read_32(pl011_base + UARTFBRD); 191*91f16700Schasinglulu 192*91f16700Schasinglulu /* 193*91f16700Schasinglulu * The result won't be exact, due to rounding errors, 194*91f16700Schasinglulu * but the input frequency was a multiple of 250 KHz. 195*91f16700Schasinglulu */ 196*91f16700Schasinglulu return round_multiple(pl011_freq_from_divider(divider), 197*91f16700Schasinglulu 250000); 198*91f16700Schasinglulu } else { 199*91f16700Schasinglulu WARN("Cannot read PL011 MMIO base\n"); 200*91f16700Schasinglulu } 201*91f16700Schasinglulu } else { 202*91f16700Schasinglulu WARN("No PL011 DT node\n"); 203*91f16700Schasinglulu } 204*91f16700Schasinglulu 205*91f16700Schasinglulu /* No PL011 DT node or calculation failed. */ 206*91f16700Schasinglulu return FPGA_DEFAULT_TIMER_FREQUENCY; 207*91f16700Schasinglulu } 208*91f16700Schasinglulu 209*91f16700Schasinglulu unsigned int plat_get_syscnt_freq2(void) 210*91f16700Schasinglulu { 211*91f16700Schasinglulu if (system_freq == 0U) { 212*91f16700Schasinglulu system_freq = fpga_get_system_frequency(); 213*91f16700Schasinglulu } 214*91f16700Schasinglulu 215*91f16700Schasinglulu return system_freq; 216*91f16700Schasinglulu } 217*91f16700Schasinglulu 218*91f16700Schasinglulu static void fpga_dtb_update_clock(void *fdt, unsigned int freq) 219*91f16700Schasinglulu { 220*91f16700Schasinglulu uint32_t freq_dtb = fdt32_to_cpu(freq); 221*91f16700Schasinglulu uint32_t phandle; 222*91f16700Schasinglulu int node, err; 223*91f16700Schasinglulu 224*91f16700Schasinglulu node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); 225*91f16700Schasinglulu if (node < 0) { 226*91f16700Schasinglulu WARN("%s(): No PL011 DT node found\n", __func__); 227*91f16700Schasinglulu 228*91f16700Schasinglulu return; 229*91f16700Schasinglulu } 230*91f16700Schasinglulu 231*91f16700Schasinglulu err = fdt_read_uint32(fdt, node, "clocks", &phandle); 232*91f16700Schasinglulu if (err != 0) { 233*91f16700Schasinglulu WARN("Cannot find clocks property\n"); 234*91f16700Schasinglulu 235*91f16700Schasinglulu return; 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu node = fdt_node_offset_by_phandle(fdt, phandle); 239*91f16700Schasinglulu if (node < 0) { 240*91f16700Schasinglulu WARN("Cannot get phandle\n"); 241*91f16700Schasinglulu 242*91f16700Schasinglulu return; 243*91f16700Schasinglulu } 244*91f16700Schasinglulu 245*91f16700Schasinglulu err = fdt_setprop_inplace(fdt, node, 246*91f16700Schasinglulu "clock-frequency", 247*91f16700Schasinglulu &freq_dtb, 248*91f16700Schasinglulu sizeof(freq_dtb)); 249*91f16700Schasinglulu if (err < 0) { 250*91f16700Schasinglulu WARN("Could not update DT baud clock frequency\n"); 251*91f16700Schasinglulu 252*91f16700Schasinglulu return; 253*91f16700Schasinglulu } 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu #define CMDLINE_SIGNATURE "CMD:" 257*91f16700Schasinglulu 258*91f16700Schasinglulu static int fpga_dtb_set_commandline(void *fdt, const char *cmdline) 259*91f16700Schasinglulu { 260*91f16700Schasinglulu int chosen; 261*91f16700Schasinglulu const char *eol; 262*91f16700Schasinglulu char nul = 0; 263*91f16700Schasinglulu int slen, err; 264*91f16700Schasinglulu 265*91f16700Schasinglulu chosen = fdt_add_subnode(fdt, 0, "chosen"); 266*91f16700Schasinglulu if (chosen == -FDT_ERR_EXISTS) { 267*91f16700Schasinglulu chosen = fdt_path_offset(fdt, "/chosen"); 268*91f16700Schasinglulu } 269*91f16700Schasinglulu 270*91f16700Schasinglulu if (chosen < 0) { 271*91f16700Schasinglulu return chosen; 272*91f16700Schasinglulu } 273*91f16700Schasinglulu 274*91f16700Schasinglulu /* 275*91f16700Schasinglulu * There is most likely an EOL at the end of the 276*91f16700Schasinglulu * command line, make sure we terminate the line there. 277*91f16700Schasinglulu * We can't replace the EOL with a NUL byte in the 278*91f16700Schasinglulu * source, as this is in read-only memory. So we first 279*91f16700Schasinglulu * create the property without any termination, then 280*91f16700Schasinglulu * append a single NUL byte. 281*91f16700Schasinglulu */ 282*91f16700Schasinglulu eol = strchr(cmdline, '\n'); 283*91f16700Schasinglulu if (eol == NULL) { 284*91f16700Schasinglulu eol = strchr(cmdline, 0); 285*91f16700Schasinglulu } 286*91f16700Schasinglulu /* Skip the signature and omit the EOL/NUL byte. */ 287*91f16700Schasinglulu slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE)); 288*91f16700Schasinglulu /* 289*91f16700Schasinglulu * Let's limit the size of the property, just in case 290*91f16700Schasinglulu * we find the signature by accident. The Linux kernel 291*91f16700Schasinglulu * limits to 4096 characters at most (in fact 2048 for 292*91f16700Schasinglulu * arm64), so that sounds like a reasonable number. 293*91f16700Schasinglulu */ 294*91f16700Schasinglulu if (slen > 4095) { 295*91f16700Schasinglulu slen = 4095; 296*91f16700Schasinglulu } 297*91f16700Schasinglulu 298*91f16700Schasinglulu err = fdt_setprop(fdt, chosen, "bootargs", 299*91f16700Schasinglulu cmdline + strlen(CMDLINE_SIGNATURE), slen); 300*91f16700Schasinglulu if (err != 0) { 301*91f16700Schasinglulu return err; 302*91f16700Schasinglulu } 303*91f16700Schasinglulu 304*91f16700Schasinglulu return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1); 305*91f16700Schasinglulu } 306*91f16700Schasinglulu 307*91f16700Schasinglulu static void fpga_prepare_dtb(void) 308*91f16700Schasinglulu { 309*91f16700Schasinglulu void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 310*91f16700Schasinglulu const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE; 311*91f16700Schasinglulu int err; 312*91f16700Schasinglulu 313*91f16700Schasinglulu err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE); 314*91f16700Schasinglulu if (err < 0) { 315*91f16700Schasinglulu ERROR("cannot open devicetree at %p: %d\n", fdt, err); 316*91f16700Schasinglulu panic(); 317*91f16700Schasinglulu } 318*91f16700Schasinglulu 319*91f16700Schasinglulu /* Reserve memory used by Trusted Firmware. */ 320*91f16700Schasinglulu if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE, 321*91f16700Schasinglulu BL31_LIMIT - BL31_BASE)) { 322*91f16700Schasinglulu WARN("Failed to add reserved memory node to DT\n"); 323*91f16700Schasinglulu } 324*91f16700Schasinglulu 325*91f16700Schasinglulu /* Check for the command line signature. */ 326*91f16700Schasinglulu if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) { 327*91f16700Schasinglulu err = fpga_dtb_set_commandline(fdt, cmdline); 328*91f16700Schasinglulu if (err == 0) { 329*91f16700Schasinglulu INFO("using command line at 0x%x\n", 330*91f16700Schasinglulu FPGA_PRELOADED_CMD_LINE); 331*91f16700Schasinglulu } else { 332*91f16700Schasinglulu ERROR("failed to put command line into DTB: %d\n", err); 333*91f16700Schasinglulu } 334*91f16700Schasinglulu } 335*91f16700Schasinglulu 336*91f16700Schasinglulu if (err < 0) { 337*91f16700Schasinglulu ERROR("Error %d extending Device Tree\n", err); 338*91f16700Schasinglulu panic(); 339*91f16700Schasinglulu } 340*91f16700Schasinglulu 341*91f16700Schasinglulu err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU, 342*91f16700Schasinglulu FPGA_MAX_CPUS_PER_CLUSTER, 343*91f16700Schasinglulu FPGA_MAX_CLUSTER_COUNT); 344*91f16700Schasinglulu 345*91f16700Schasinglulu if (err == -EEXIST) { 346*91f16700Schasinglulu WARN("Not overwriting already existing /cpus node in DTB\n"); 347*91f16700Schasinglulu } else { 348*91f16700Schasinglulu if (err < 0) { 349*91f16700Schasinglulu ERROR("Error %d creating the /cpus DT node\n", err); 350*91f16700Schasinglulu panic(); 351*91f16700Schasinglulu } else { 352*91f16700Schasinglulu unsigned int nr_cores = fpga_get_nr_gic_cores(); 353*91f16700Schasinglulu 354*91f16700Schasinglulu INFO("Adjusting GICR DT region to cover %u cores\n", 355*91f16700Schasinglulu nr_cores); 356*91f16700Schasinglulu err = fdt_adjust_gic_redist(fdt, nr_cores, 357*91f16700Schasinglulu fpga_get_redist_base(), 358*91f16700Schasinglulu fpga_get_redist_size()); 359*91f16700Schasinglulu if (err < 0) { 360*91f16700Schasinglulu ERROR("Error %d fixing up GIC DT node\n", err); 361*91f16700Schasinglulu } 362*91f16700Schasinglulu } 363*91f16700Schasinglulu } 364*91f16700Schasinglulu 365*91f16700Schasinglulu fpga_dtb_update_clock(fdt, system_freq); 366*91f16700Schasinglulu 367*91f16700Schasinglulu /* Check whether we support the SPE PMU. Remove the DT node if not. */ 368*91f16700Schasinglulu if (!is_feat_spe_supported()) { 369*91f16700Schasinglulu int node = fdt_node_offset_by_compatible(fdt, 0, 370*91f16700Schasinglulu "arm,statistical-profiling-extension-v1"); 371*91f16700Schasinglulu 372*91f16700Schasinglulu if (node >= 0) { 373*91f16700Schasinglulu fdt_del_node(fdt, node); 374*91f16700Schasinglulu } 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /* Check whether we have an ITS. Remove the DT node if not. */ 378*91f16700Schasinglulu if (!fpga_has_its()) { 379*91f16700Schasinglulu int node = fdt_node_offset_by_compatible(fdt, 0, 380*91f16700Schasinglulu "arm,gic-v3-its"); 381*91f16700Schasinglulu 382*91f16700Schasinglulu if (node >= 0) { 383*91f16700Schasinglulu fdt_del_node(fdt, node); 384*91f16700Schasinglulu } 385*91f16700Schasinglulu } 386*91f16700Schasinglulu 387*91f16700Schasinglulu err = fdt_pack(fdt); 388*91f16700Schasinglulu if (err < 0) { 389*91f16700Schasinglulu ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err); 390*91f16700Schasinglulu } 391*91f16700Schasinglulu 392*91f16700Schasinglulu clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); 393*91f16700Schasinglulu } 394*91f16700Schasinglulu 395*91f16700Schasinglulu void bl31_plat_runtime_setup(void) 396*91f16700Schasinglulu { 397*91f16700Schasinglulu fpga_prepare_dtb(); 398*91f16700Schasinglulu } 399*91f16700Schasinglulu 400*91f16700Schasinglulu void bl31_plat_enable_mmu(uint32_t flags) 401*91f16700Schasinglulu { 402*91f16700Schasinglulu /* TODO: determine if MMU needs to be enabled */ 403*91f16700Schasinglulu } 404