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