1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-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 9*91f16700Schasinglulu #include <bl32/sp_min/platform_sp_min.h> 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <lib/fconf/fconf.h> 12*91f16700Schasinglulu #include <lib/fconf/fconf_dyn_cfg_getter.h> 13*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include "../fvp_private.h" 16*91f16700Schasinglulu 17*91f16700Schasinglulu void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, 18*91f16700Schasinglulu u_register_t arg2, u_register_t arg3) 19*91f16700Schasinglulu { 20*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *tos_fw_config_info __unused; 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* Initialize the console to provide early debug support */ 23*91f16700Schasinglulu arm_console_boot_init(); 24*91f16700Schasinglulu 25*91f16700Schasinglulu #if !RESET_TO_SP_MIN && !RESET_TO_BL2 26*91f16700Schasinglulu 27*91f16700Schasinglulu INFO("SP_MIN FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); 28*91f16700Schasinglulu /* Fill the properties struct with the info from the config dtb */ 29*91f16700Schasinglulu fconf_populate("FW_CONFIG", arg1); 30*91f16700Schasinglulu 31*91f16700Schasinglulu tos_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TOS_FW_CONFIG_ID); 32*91f16700Schasinglulu if (tos_fw_config_info != NULL) { 33*91f16700Schasinglulu arg1 = tos_fw_config_info->config_addr; 34*91f16700Schasinglulu } 35*91f16700Schasinglulu #endif /* !RESET_TO_SP_MIN && !RESET_TO_BL2 */ 36*91f16700Schasinglulu 37*91f16700Schasinglulu arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); 38*91f16700Schasinglulu 39*91f16700Schasinglulu /* Initialize the platform config for future decision making */ 40*91f16700Schasinglulu fvp_config_setup(); 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* 43*91f16700Schasinglulu * Initialize the correct interconnect for this cluster during cold 44*91f16700Schasinglulu * boot. No need for locks as no other CPU is active. 45*91f16700Schasinglulu */ 46*91f16700Schasinglulu fvp_interconnect_init(); 47*91f16700Schasinglulu 48*91f16700Schasinglulu /* 49*91f16700Schasinglulu * Enable coherency in interconnect for the primary CPU's cluster. 50*91f16700Schasinglulu * Earlier bootloader stages might already do this (e.g. Trusted 51*91f16700Schasinglulu * Firmware's BL1 does it) but we can't assume so. There is no harm in 52*91f16700Schasinglulu * executing this code twice anyway. 53*91f16700Schasinglulu * FVP PSCI code will enable coherency for other clusters. 54*91f16700Schasinglulu */ 55*91f16700Schasinglulu fvp_interconnect_enable(); 56*91f16700Schasinglulu } 57*91f16700Schasinglulu 58*91f16700Schasinglulu void sp_min_plat_arch_setup(void) 59*91f16700Schasinglulu { 60*91f16700Schasinglulu int rc __unused; 61*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *hw_config_info __unused; 62*91f16700Schasinglulu uintptr_t hw_config_base_align __unused; 63*91f16700Schasinglulu size_t mapped_size_align __unused; 64*91f16700Schasinglulu 65*91f16700Schasinglulu arm_sp_min_plat_arch_setup(); 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* 68*91f16700Schasinglulu * For RESET_TO_SP_MIN systems, SP_MIN(BL32) is the first bootloader 69*91f16700Schasinglulu * to run. So there is no BL2 to load the HW_CONFIG dtb into memory 70*91f16700Schasinglulu * before control is passed to SP_MIN. 71*91f16700Schasinglulu * Also, BL2 skips loading HW_CONFIG dtb for 72*91f16700Schasinglulu * RESET_TO_BL2 builds. 73*91f16700Schasinglulu * The code below relies on dynamic mapping capability, 74*91f16700Schasinglulu * which is not supported by xlat tables lib V1. 75*91f16700Schasinglulu * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support 76*91f16700Schasinglulu * gets deprecated. 77*91f16700Schasinglulu */ 78*91f16700Schasinglulu #if !RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1 79*91f16700Schasinglulu hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); 80*91f16700Schasinglulu assert(hw_config_info != NULL); 81*91f16700Schasinglulu assert(hw_config_info->config_addr != 0UL); 82*91f16700Schasinglulu 83*91f16700Schasinglulu INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", 84*91f16700Schasinglulu (void *)hw_config_info->config_addr); 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* 87*91f16700Schasinglulu * Preferably we expect this address and size are page aligned, 88*91f16700Schasinglulu * but if they are not then align it. 89*91f16700Schasinglulu */ 90*91f16700Schasinglulu hw_config_base_align = page_align(hw_config_info->config_addr, DOWN); 91*91f16700Schasinglulu mapped_size_align = page_align(hw_config_info->config_max_size, UP); 92*91f16700Schasinglulu 93*91f16700Schasinglulu if ((hw_config_info->config_addr != hw_config_base_align) && 94*91f16700Schasinglulu (hw_config_info->config_max_size == mapped_size_align)) { 95*91f16700Schasinglulu mapped_size_align += PAGE_SIZE; 96*91f16700Schasinglulu } 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* 99*91f16700Schasinglulu * map dynamically HW config region with its aligned base address and 100*91f16700Schasinglulu * size 101*91f16700Schasinglulu */ 102*91f16700Schasinglulu rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align, 103*91f16700Schasinglulu hw_config_base_align, 104*91f16700Schasinglulu mapped_size_align, 105*91f16700Schasinglulu MT_RO_DATA); 106*91f16700Schasinglulu if (rc != 0) { 107*91f16700Schasinglulu ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc); 108*91f16700Schasinglulu panic(); 109*91f16700Schasinglulu } 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Populate HW_CONFIG device tree with the mapped address */ 112*91f16700Schasinglulu fconf_populate("HW_CONFIG", hw_config_info->config_addr); 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* unmap the HW_CONFIG memory region */ 115*91f16700Schasinglulu rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align); 116*91f16700Schasinglulu if (rc != 0) { 117*91f16700Schasinglulu ERROR("Error while unmapping HW_CONFIG device tree (%d).\n", 118*91f16700Schasinglulu rc); 119*91f16700Schasinglulu panic(); 120*91f16700Schasinglulu } 121*91f16700Schasinglulu #endif /*!RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1*/ 122*91f16700Schasinglulu } 123