1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2013-2023, 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 <common/debug.h> 9*91f16700Schasinglulu #include <drivers/arm/smmu_v3.h> 10*91f16700Schasinglulu #include <fconf_hw_config_getter.h> 11*91f16700Schasinglulu #include <lib/fconf/fconf.h> 12*91f16700Schasinglulu #include <lib/fconf/fconf_dyn_cfg_getter.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu #include <plat/arm/common/arm_config.h> 15*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include "fvp_private.h" 19*91f16700Schasinglulu 20*91f16700Schasinglulu static const struct dyn_cfg_dtb_info_t *hw_config_info __unused; 21*91f16700Schasinglulu 22*91f16700Schasinglulu void __init bl31_early_platform_setup2(u_register_t arg0, 23*91f16700Schasinglulu u_register_t arg1, u_register_t arg2, u_register_t arg3) 24*91f16700Schasinglulu { 25*91f16700Schasinglulu /* Initialize the console to provide early debug support */ 26*91f16700Schasinglulu arm_console_boot_init(); 27*91f16700Schasinglulu 28*91f16700Schasinglulu #if !RESET_TO_BL31 && !RESET_TO_BL2 29*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *soc_fw_config_info; 30*91f16700Schasinglulu 31*91f16700Schasinglulu INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); 32*91f16700Schasinglulu /* Fill the properties struct with the info from the config dtb */ 33*91f16700Schasinglulu fconf_populate("FW_CONFIG", arg1); 34*91f16700Schasinglulu 35*91f16700Schasinglulu soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); 36*91f16700Schasinglulu if (soc_fw_config_info != NULL) { 37*91f16700Schasinglulu arg1 = soc_fw_config_info->config_addr; 38*91f16700Schasinglulu } 39*91f16700Schasinglulu 40*91f16700Schasinglulu /* 41*91f16700Schasinglulu * arg2 is currently holding the 'secure' address of HW_CONFIG. 42*91f16700Schasinglulu * But arm_bl31_early_platform_setup() below expects the 'non-secure' 43*91f16700Schasinglulu * address of HW_CONFIG (which it will pass to BL33). 44*91f16700Schasinglulu * This why we need to override arg2 here. 45*91f16700Schasinglulu */ 46*91f16700Schasinglulu hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); 47*91f16700Schasinglulu assert(hw_config_info != NULL); 48*91f16700Schasinglulu assert(hw_config_info->secondary_config_addr != 0UL); 49*91f16700Schasinglulu arg2 = hw_config_info->secondary_config_addr; 50*91f16700Schasinglulu #endif /* !RESET_TO_BL31 && !RESET_TO_BL2 */ 51*91f16700Schasinglulu 52*91f16700Schasinglulu arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* Initialize the platform config for future decision making */ 55*91f16700Schasinglulu fvp_config_setup(); 56*91f16700Schasinglulu 57*91f16700Schasinglulu /* 58*91f16700Schasinglulu * Initialize the correct interconnect for this cluster during cold 59*91f16700Schasinglulu * boot. No need for locks as no other CPU is active. 60*91f16700Schasinglulu */ 61*91f16700Schasinglulu fvp_interconnect_init(); 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* 64*91f16700Schasinglulu * Enable coherency in interconnect for the primary CPU's cluster. 65*91f16700Schasinglulu * Earlier bootloader stages might already do this (e.g. Trusted 66*91f16700Schasinglulu * Firmware's BL1 does it) but we can't assume so. There is no harm in 67*91f16700Schasinglulu * executing this code twice anyway. 68*91f16700Schasinglulu * FVP PSCI code will enable coherency for other clusters. 69*91f16700Schasinglulu */ 70*91f16700Schasinglulu fvp_interconnect_enable(); 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Initialize System level generic or SP804 timer */ 73*91f16700Schasinglulu fvp_timer_init(); 74*91f16700Schasinglulu 75*91f16700Schasinglulu /* On FVP RevC, initialize SMMUv3 */ 76*91f16700Schasinglulu if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) 77*91f16700Schasinglulu smmuv3_init(PLAT_FVP_SMMUV3_BASE); 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu void __init bl31_plat_arch_setup(void) 81*91f16700Schasinglulu { 82*91f16700Schasinglulu int rc __unused; 83*91f16700Schasinglulu uintptr_t hw_config_base_align __unused; 84*91f16700Schasinglulu size_t mapped_size_align __unused; 85*91f16700Schasinglulu 86*91f16700Schasinglulu arm_bl31_plat_arch_setup(); 87*91f16700Schasinglulu 88*91f16700Schasinglulu /* 89*91f16700Schasinglulu * For RESET_TO_BL31 systems, BL31 is the first bootloader to run. 90*91f16700Schasinglulu * So there is no BL2 to load the HW_CONFIG dtb into memory before 91*91f16700Schasinglulu * control is passed to BL31. The code below relies on dynamic mapping 92*91f16700Schasinglulu * capability, which is not supported by xlat tables lib V1. 93*91f16700Schasinglulu * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support 94*91f16700Schasinglulu * gets deprecated. 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu #if !RESET_TO_BL31 && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1 97*91f16700Schasinglulu assert(hw_config_info != NULL); 98*91f16700Schasinglulu assert(hw_config_info->config_addr != 0UL); 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Page aligned address and size if necessary */ 101*91f16700Schasinglulu hw_config_base_align = page_align(hw_config_info->config_addr, DOWN); 102*91f16700Schasinglulu mapped_size_align = page_align(hw_config_info->config_max_size, UP); 103*91f16700Schasinglulu 104*91f16700Schasinglulu if ((hw_config_info->config_addr != hw_config_base_align) && 105*91f16700Schasinglulu (hw_config_info->config_max_size == mapped_size_align)) { 106*91f16700Schasinglulu mapped_size_align += PAGE_SIZE; 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* 110*91f16700Schasinglulu * map dynamically HW config region with its aligned base address and 111*91f16700Schasinglulu * size 112*91f16700Schasinglulu */ 113*91f16700Schasinglulu rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align, 114*91f16700Schasinglulu hw_config_base_align, 115*91f16700Schasinglulu mapped_size_align, 116*91f16700Schasinglulu MT_RO_DATA); 117*91f16700Schasinglulu if (rc != 0) { 118*91f16700Schasinglulu ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc); 119*91f16700Schasinglulu panic(); 120*91f16700Schasinglulu } 121*91f16700Schasinglulu 122*91f16700Schasinglulu /* Populate HW_CONFIG device tree with the mapped address */ 123*91f16700Schasinglulu fconf_populate("HW_CONFIG", hw_config_info->config_addr); 124*91f16700Schasinglulu 125*91f16700Schasinglulu /* unmap the HW_CONFIG memory region */ 126*91f16700Schasinglulu rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align); 127*91f16700Schasinglulu if (rc != 0) { 128*91f16700Schasinglulu ERROR("Error while unmapping HW_CONFIG device tree (%d).\n", 129*91f16700Schasinglulu rc); 130*91f16700Schasinglulu panic(); 131*91f16700Schasinglulu } 132*91f16700Schasinglulu #endif /* !RESET_TO_BL31 && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1 */ 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu unsigned int plat_get_syscnt_freq2(void) 136*91f16700Schasinglulu { 137*91f16700Schasinglulu unsigned int counter_base_frequency; 138*91f16700Schasinglulu 139*91f16700Schasinglulu #if !RESET_TO_BL31 && !RESET_TO_BL2 140*91f16700Schasinglulu /* Get the frequency through FCONF API for HW_CONFIG */ 141*91f16700Schasinglulu counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq); 142*91f16700Schasinglulu if (counter_base_frequency > 0U) { 143*91f16700Schasinglulu return counter_base_frequency; 144*91f16700Schasinglulu } 145*91f16700Schasinglulu #endif 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* Read the frequency from Frequency modes table */ 148*91f16700Schasinglulu counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* The first entry of the frequency modes table must not be 0 */ 151*91f16700Schasinglulu if (counter_base_frequency == 0U) { 152*91f16700Schasinglulu panic(); 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu return counter_base_frequency; 156*91f16700Schasinglulu } 157