xref: /rk3399_ARM-atf/plat/arm/board/neoverse_rd/common/nrd_image_load.c (revision 8b68a617bceabefc235e0f1bdad6ec3afa80309c)
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