14ced5956SRohit Mathew /*
2*37cc7fa5SNishant Sharma * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
34ced5956SRohit Mathew *
44ced5956SRohit Mathew * SPDX-License-Identifier: BSD-3-Clause
54ced5956SRohit Mathew */
64ced5956SRohit Mathew
74ced5956SRohit Mathew #include <libfdt.h>
84ced5956SRohit Mathew
94ced5956SRohit Mathew #include <arch_helpers.h>
104ced5956SRohit Mathew #include <common/debug.h>
114ced5956SRohit Mathew #include <common/desc_image_load.h>
124ced5956SRohit Mathew #include <drivers/arm/css/sds.h>
13*37cc7fa5SNishant Sharma #include <lib/fconf/fconf.h>
14*37cc7fa5SNishant Sharma #include <lib/fconf/fconf_dyn_cfg_getter.h>
154ced5956SRohit Mathew #include <plat/arm/common/plat_arm.h>
164ced5956SRohit Mathew #include <plat/common/platform.h>
174ced5956SRohit Mathew #include <platform_def.h>
184ced5956SRohit Mathew
194ced5956SRohit Mathew #include <nrd_variant.h>
204ced5956SRohit Mathew
214ced5956SRohit Mathew /*
224ced5956SRohit Mathew * Information about the isolated CPUs obtained from SDS.
234ced5956SRohit Mathew */
244ced5956SRohit Mathew struct isolated_cpu_mpid_list {
254ced5956SRohit Mathew uint64_t num_entries; /* Number of entries in the list */
264ced5956SRohit Mathew uint64_t mpid_list[PLATFORM_CORE_COUNT]; /* List of isolated CPU MPIDs */
274ced5956SRohit Mathew };
284ced5956SRohit Mathew
294ced5956SRohit Mathew /* Function to read isolated CPU MPID list from SDS. */
plat_arm_nrd_get_isolated_cpu_list(struct isolated_cpu_mpid_list * list)3040ea4208SRohit Mathew void plat_arm_nrd_get_isolated_cpu_list(struct isolated_cpu_mpid_list *list)
314ced5956SRohit Mathew {
324ced5956SRohit Mathew int ret;
334ced5956SRohit Mathew
344ced5956SRohit Mathew ret = sds_init(SDS_SCP_AP_REGION_ID);
354ced5956SRohit Mathew if (ret != SDS_OK) {
364ced5956SRohit Mathew ERROR("SDS initialization failed, error: %d\n", ret);
374ced5956SRohit Mathew panic();
384ced5956SRohit Mathew }
394ced5956SRohit Mathew
404ced5956SRohit Mathew ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
414ced5956SRohit Mathew SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries,
424ced5956SRohit Mathew sizeof(list->num_entries), SDS_ACCESS_MODE_CACHED);
434ced5956SRohit Mathew if (ret != SDS_OK) {
444ced5956SRohit Mathew INFO("SDS CPU num elements read failed, error: %d\n", ret);
454ced5956SRohit Mathew list->num_entries = 0;
464ced5956SRohit Mathew return;
474ced5956SRohit Mathew }
484ced5956SRohit Mathew
494ced5956SRohit Mathew if (list->num_entries > PLATFORM_CORE_COUNT) {
504ced5956SRohit Mathew ERROR("Isolated CPU list count %ld greater than max"
514ced5956SRohit Mathew " number supported %d\n",
524ced5956SRohit Mathew list->num_entries, PLATFORM_CORE_COUNT);
534ced5956SRohit Mathew panic();
544ced5956SRohit Mathew } else if (list->num_entries == 0) {
554ced5956SRohit Mathew INFO("SDS isolated CPU list is empty\n");
564ced5956SRohit Mathew return;
574ced5956SRohit Mathew }
584ced5956SRohit Mathew
594ced5956SRohit Mathew ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
604ced5956SRohit Mathew SDS_ISOLATED_CPU_LIST_ID,
614ced5956SRohit Mathew sizeof(list->num_entries),
624ced5956SRohit Mathew &list->mpid_list,
634ced5956SRohit Mathew sizeof(list->mpid_list[0]) * list->num_entries,
644ced5956SRohit Mathew SDS_ACCESS_MODE_CACHED);
654ced5956SRohit Mathew if (ret != SDS_OK) {
664ced5956SRohit Mathew ERROR("SDS CPU list read failed. error: %d\n", ret);
674ced5956SRohit Mathew panic();
684ced5956SRohit Mathew }
694ced5956SRohit Mathew }
704ced5956SRohit Mathew
714ced5956SRohit Mathew /*******************************************************************************
724ced5956SRohit Mathew * This function inserts Platform information via device tree nodes as,
734ced5956SRohit Mathew * system-id {
744ced5956SRohit Mathew * platform-id = <0>;
754ced5956SRohit Mathew * config-id = <0>;
764ced5956SRohit Mathew * isolated-cpu-list = <0>
774ced5956SRohit Mathew * }
784ced5956SRohit Mathew ******************************************************************************/
plat_nrd_append_config_node(void)7940ea4208SRohit Mathew static int plat_nrd_append_config_node(void)
804ced5956SRohit Mathew {
814ced5956SRohit Mathew bl_mem_params_node_t *mem_params;
824ced5956SRohit Mathew void *fdt;
834ced5956SRohit Mathew int nodeoffset, err;
844ced5956SRohit Mathew unsigned int platid = 0, platcfg = 0;
854ced5956SRohit Mathew struct isolated_cpu_mpid_list cpu_mpid_list = {0};
864ced5956SRohit Mathew
874ced5956SRohit Mathew mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
884ced5956SRohit Mathew if (mem_params == NULL) {
894ced5956SRohit Mathew ERROR("NT_FW CONFIG base address is NULL");
904ced5956SRohit Mathew return -1;
914ced5956SRohit Mathew }
924ced5956SRohit Mathew
934ced5956SRohit Mathew fdt = (void *)(mem_params->image_info.image_base);
944ced5956SRohit Mathew
954ced5956SRohit Mathew /* Check the validity of the fdt */
964ced5956SRohit Mathew if (fdt_check_header(fdt) != 0) {
974ced5956SRohit Mathew ERROR("Invalid NT_FW_CONFIG DTB passed\n");
984ced5956SRohit Mathew return -1;
994ced5956SRohit Mathew }
1004ced5956SRohit Mathew
1014ced5956SRohit Mathew nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
1024ced5956SRohit Mathew if (nodeoffset < 0) {
1034ced5956SRohit Mathew ERROR("Failed to get system-id node offset\n");
1044ced5956SRohit Mathew return -1;
1054ced5956SRohit Mathew }
1064ced5956SRohit Mathew
10740ea4208SRohit Mathew platid = plat_arm_nrd_get_platform_id();
1084ced5956SRohit Mathew err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
1094ced5956SRohit Mathew if (err < 0) {
1104ced5956SRohit Mathew ERROR("Failed to set platform-id\n");
1114ced5956SRohit Mathew return -1;
1124ced5956SRohit Mathew }
1134ced5956SRohit Mathew
11440ea4208SRohit Mathew platcfg = plat_arm_nrd_get_config_id();
1154ced5956SRohit Mathew err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
1164ced5956SRohit Mathew if (err < 0) {
1174ced5956SRohit Mathew ERROR("Failed to set config-id\n");
1184ced5956SRohit Mathew return -1;
1194ced5956SRohit Mathew }
1204ced5956SRohit Mathew
12140ea4208SRohit Mathew platcfg = plat_arm_nrd_get_multi_chip_mode();
1224ced5956SRohit Mathew err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg);
1234ced5956SRohit Mathew if (err < 0) {
1244ced5956SRohit Mathew ERROR("Failed to set multi-chip-mode\n");
1254ced5956SRohit Mathew return -1;
1264ced5956SRohit Mathew }
1274ced5956SRohit Mathew
12840ea4208SRohit Mathew plat_arm_nrd_get_isolated_cpu_list(&cpu_mpid_list);
1294ced5956SRohit Mathew if (cpu_mpid_list.num_entries > 0) {
1304ced5956SRohit Mathew err = fdt_setprop(fdt, nodeoffset, "isolated-cpu-list",
1314ced5956SRohit Mathew &cpu_mpid_list,
1324ced5956SRohit Mathew (sizeof(cpu_mpid_list.num_entries) *
1334ced5956SRohit Mathew (cpu_mpid_list.num_entries + 1)));
1344ced5956SRohit Mathew if (err < 0) {
1354ced5956SRohit Mathew ERROR("Failed to set isolated-cpu-list, error: %d\n",
1364ced5956SRohit Mathew err);
1374ced5956SRohit Mathew }
1384ced5956SRohit Mathew }
1394ced5956SRohit Mathew
1404ced5956SRohit Mathew flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
1414ced5956SRohit Mathew
1424ced5956SRohit Mathew return 0;
1434ced5956SRohit Mathew }
1444ced5956SRohit Mathew
1454ced5956SRohit Mathew /*******************************************************************************
1464ced5956SRohit Mathew * This function returns the list of executable images.
1474ced5956SRohit Mathew ******************************************************************************/
plat_get_next_bl_params(void)1484ced5956SRohit Mathew bl_params_t *plat_get_next_bl_params(void)
1494ced5956SRohit Mathew {
150*37cc7fa5SNishant Sharma struct bl_params *arm_bl_params;
1514ced5956SRohit Mathew int ret;
1524ced5956SRohit Mathew
15340ea4208SRohit Mathew ret = plat_nrd_append_config_node();
1544ced5956SRohit Mathew if (ret != 0)
1554ced5956SRohit Mathew panic();
1564ced5956SRohit Mathew
157*37cc7fa5SNishant Sharma arm_bl_params = arm_get_next_bl_params();
158*37cc7fa5SNishant Sharma
159*37cc7fa5SNishant Sharma #if !EL3_PAYLOAD_BASE
160*37cc7fa5SNishant Sharma const struct dyn_cfg_dtb_info_t *fw_config_info;
161*37cc7fa5SNishant Sharma bl_mem_params_node_t *param_node;
162*37cc7fa5SNishant Sharma uintptr_t fw_config_base = 0UL;
163*37cc7fa5SNishant Sharma
164*37cc7fa5SNishant Sharma /* Get BL31 image node */
165*37cc7fa5SNishant Sharma param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
166*37cc7fa5SNishant Sharma assert(param_node != NULL);
167*37cc7fa5SNishant Sharma
168*37cc7fa5SNishant Sharma /* Get fw_config load address */
169*37cc7fa5SNishant Sharma fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
170*37cc7fa5SNishant Sharma assert(fw_config_info != NULL);
171*37cc7fa5SNishant Sharma
172*37cc7fa5SNishant Sharma fw_config_base = fw_config_info->config_addr;
173*37cc7fa5SNishant Sharma assert(fw_config_base != 0UL);
174*37cc7fa5SNishant Sharma
175*37cc7fa5SNishant Sharma /*
176*37cc7fa5SNishant Sharma * Get the entry point info of next executable image and override
177*37cc7fa5SNishant Sharma * arg1 of entry point info with fw_config base address
178*37cc7fa5SNishant Sharma */
179*37cc7fa5SNishant Sharma param_node->ep_info.args.arg1 = (uint64_t)fw_config_base;
180*37cc7fa5SNishant Sharma
181*37cc7fa5SNishant Sharma #endif
182*37cc7fa5SNishant Sharma return arm_bl_params;
1834ced5956SRohit Mathew }
184