1 /* 2 * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <libfdt.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <common/desc_image_load.h> 12 #include <drivers/arm/css/sds.h> 13 #include <lib/fconf/fconf.h> 14 #include <lib/fconf/fconf_dyn_cfg_getter.h> 15 #include <plat/arm/common/plat_arm.h> 16 #include <plat/common/platform.h> 17 #include <platform_def.h> 18 19 #include <nrd_variant.h> 20 21 /* 22 * Information about the isolated CPUs obtained from SDS. 23 */ 24 struct isolated_cpu_mpid_list { 25 uint64_t num_entries; /* Number of entries in the list */ 26 uint64_t mpid_list[PLATFORM_CORE_COUNT]; /* List of isolated CPU MPIDs */ 27 }; 28 29 /* Function to read isolated CPU MPID list from SDS. */ 30 void plat_arm_nrd_get_isolated_cpu_list(struct isolated_cpu_mpid_list *list) 31 { 32 int ret; 33 34 ret = sds_init(SDS_SCP_AP_REGION_ID); 35 if (ret != SDS_OK) { 36 ERROR("SDS initialization failed, error: %d\n", ret); 37 panic(); 38 } 39 40 ret = sds_struct_read(SDS_SCP_AP_REGION_ID, 41 SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries, 42 sizeof(list->num_entries), SDS_ACCESS_MODE_CACHED); 43 if (ret != SDS_OK) { 44 INFO("SDS CPU num elements read failed, error: %d\n", ret); 45 list->num_entries = 0; 46 return; 47 } 48 49 if (list->num_entries > PLATFORM_CORE_COUNT) { 50 ERROR("Isolated CPU list count %ld greater than max" 51 " number supported %d\n", 52 list->num_entries, PLATFORM_CORE_COUNT); 53 panic(); 54 } else if (list->num_entries == 0) { 55 INFO("SDS isolated CPU list is empty\n"); 56 return; 57 } 58 59 ret = sds_struct_read(SDS_SCP_AP_REGION_ID, 60 SDS_ISOLATED_CPU_LIST_ID, 61 sizeof(list->num_entries), 62 &list->mpid_list, 63 sizeof(list->mpid_list[0]) * list->num_entries, 64 SDS_ACCESS_MODE_CACHED); 65 if (ret != SDS_OK) { 66 ERROR("SDS CPU list read failed. error: %d\n", ret); 67 panic(); 68 } 69 } 70 71 /******************************************************************************* 72 * This function inserts Platform information via device tree nodes as, 73 * system-id { 74 * platform-id = <0>; 75 * config-id = <0>; 76 * isolated-cpu-list = <0> 77 * } 78 ******************************************************************************/ 79 static int plat_nrd_append_config_node(void) 80 { 81 bl_mem_params_node_t *mem_params; 82 void *fdt; 83 int nodeoffset, err; 84 unsigned int platid = 0, platcfg = 0; 85 struct isolated_cpu_mpid_list cpu_mpid_list = {0}; 86 87 mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); 88 if (mem_params == NULL) { 89 ERROR("NT_FW CONFIG base address is NULL"); 90 return -1; 91 } 92 93 fdt = (void *)(mem_params->image_info.image_base); 94 95 /* Check the validity of the fdt */ 96 if (fdt_check_header(fdt) != 0) { 97 ERROR("Invalid NT_FW_CONFIG DTB passed\n"); 98 return -1; 99 } 100 101 nodeoffset = fdt_subnode_offset(fdt, 0, "system-id"); 102 if (nodeoffset < 0) { 103 ERROR("Failed to get system-id node offset\n"); 104 return -1; 105 } 106 107 platid = plat_arm_nrd_get_platform_id(); 108 err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); 109 if (err < 0) { 110 ERROR("Failed to set platform-id\n"); 111 return -1; 112 } 113 114 platcfg = plat_arm_nrd_get_config_id(); 115 err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg); 116 if (err < 0) { 117 ERROR("Failed to set config-id\n"); 118 return -1; 119 } 120 121 platcfg = plat_arm_nrd_get_multi_chip_mode(); 122 err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg); 123 if (err < 0) { 124 ERROR("Failed to set multi-chip-mode\n"); 125 return -1; 126 } 127 128 plat_arm_nrd_get_isolated_cpu_list(&cpu_mpid_list); 129 if (cpu_mpid_list.num_entries > 0) { 130 err = fdt_setprop(fdt, nodeoffset, "isolated-cpu-list", 131 &cpu_mpid_list, 132 (sizeof(cpu_mpid_list.num_entries) * 133 (cpu_mpid_list.num_entries + 1))); 134 if (err < 0) { 135 ERROR("Failed to set isolated-cpu-list, error: %d\n", 136 err); 137 } 138 } 139 140 flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); 141 142 return 0; 143 } 144 145 /******************************************************************************* 146 * This function returns the list of executable images. 147 ******************************************************************************/ 148 bl_params_t *plat_get_next_bl_params(void) 149 { 150 struct bl_params *arm_bl_params; 151 int ret; 152 153 ret = plat_nrd_append_config_node(); 154 if (ret != 0) 155 panic(); 156 157 arm_bl_params = arm_get_next_bl_params(); 158 159 #if !EL3_PAYLOAD_BASE 160 const struct dyn_cfg_dtb_info_t *fw_config_info; 161 bl_mem_params_node_t *param_node; 162 uintptr_t fw_config_base = 0UL; 163 164 /* Get BL31 image node */ 165 param_node = get_bl_mem_params_node(BL31_IMAGE_ID); 166 assert(param_node != NULL); 167 168 /* Get fw_config load address */ 169 fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); 170 assert(fw_config_info != NULL); 171 172 fw_config_base = fw_config_info->config_addr; 173 assert(fw_config_base != 0UL); 174 175 /* 176 * Get the entry point info of next executable image and override 177 * arg1 of entry point info with fw_config base address 178 */ 179 param_node->ep_info.args.arg1 = (uint64_t)fw_config_base; 180 181 #endif 182 return arm_bl_params; 183 } 184