1 /*
2 * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <arch_helpers.h>
8 #include <common/build_message.h>
9 #include <common/debug.h>
10 #include <common/desc_image_load.h>
11 #include <drivers/arm/css/sds.h>
12 #include <libfdt.h>
13
14 #include "morello_def.h"
15 #include <plat/arm/common/plat_arm.h>
16 #include <plat/common/platform.h>
17 #include <platform_def.h>
18
19 /* In client mode, a part of the DDR memory is reserved for Tag bits.
20 * Calculate the usable memory size after subtracting the Tag memory.
21 */
22 #ifdef TARGET_PLATFORM_SOC
get_mem_client_mode(uint64_t size)23 static inline uint64_t get_mem_client_mode(uint64_t size)
24 {
25 return (size - (size / 128ULL));
26 }
27 #endif
28
29 /*******************************************************************************
30 * This function inserts Platform information and firmware versions
31 * via device tree nodes as,
32 * platform-info {
33 * local-ddr-size = <0x0 0x0>;
34 *#ifdef TARGET_PLATFORM_SOC
35 * remote-ddr-size = <0x0 0x0>;
36 * remote-chip-count = <0x0>;
37 * multichip-mode = <0x0>;
38 * scc-config = <0x0>;
39 *#endif
40 * };
41 * firmware-version {
42 *#ifdef TARGET_PLATFORM_SOC
43 * mcc-fw-version = <0x0>;
44 * pcc-fw-version = <0x0>;
45 *#endif
46 * scp-fw-version = <0x0>;
47 * scp-fw-commit = <0x0>;
48 * tfa-fw-version = "unknown-dirty_00000000";
49 * };
50 ******************************************************************************/
plat_morello_append_config_node(struct morello_plat_info * plat_info,struct morello_firmware_version * fw_version)51 static int plat_morello_append_config_node(struct morello_plat_info *plat_info,
52 struct morello_firmware_version *fw_version)
53 {
54 bl_mem_params_node_t *mem_params;
55 void *fdt;
56 int nodeoffset_plat, nodeoffset_fw, err;
57 uint64_t usable_mem_size;
58
59 usable_mem_size = plat_info->local_ddr_size;
60
61 mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
62 if (mem_params == NULL) {
63 ERROR("NT_FW CONFIG base address is NULL\n");
64 return -1;
65 }
66
67 fdt = (void *)(mem_params->image_info.image_base);
68
69 /* Check the validity of the fdt */
70 if (fdt_check_header(fdt) != 0) {
71 ERROR("Invalid NT_FW_CONFIG DTB passed\n");
72 return -1;
73 }
74
75 nodeoffset_plat = fdt_subnode_offset(fdt, 0, "platform-info");
76 if (nodeoffset_plat < 0) {
77 ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
78 return -1;
79 }
80
81 nodeoffset_fw = fdt_subnode_offset(fdt, 0, "firmware-version");
82 if (nodeoffset_fw < 0) {
83 ERROR("NT_FW_CONFIG: Failed to get firmware-version node offset\n");
84 return -1;
85 }
86
87 #ifdef TARGET_PLATFORM_SOC
88 err = fdt_setprop_u64(fdt, nodeoffset_plat, "remote-ddr-size",
89 plat_info->remote_ddr_size);
90 if (err < 0) {
91 ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
92 return -1;
93 }
94
95 err = fdt_setprop_u32(fdt, nodeoffset_plat, "remote-chip-count",
96 plat_info->remote_chip_count);
97 if (err < 0) {
98 ERROR("NT_FW_CONFIG: Failed to set remote-chip-count\n");
99 return -1;
100 }
101
102 err = fdt_setprop_u32(fdt, nodeoffset_plat, "multichip-mode",
103 plat_info->multichip_mode);
104 if (err < 0) {
105 ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
106 return -1;
107 }
108
109 err = fdt_setprop_u32(fdt, nodeoffset_plat, "scc-config",
110 plat_info->scc_config);
111 if (err < 0) {
112 ERROR("NT_FW_CONFIG: Failed to set scc-config\n");
113 return -1;
114 }
115
116 if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) {
117 usable_mem_size = get_mem_client_mode(plat_info->local_ddr_size);
118 }
119
120 err = fdt_setprop_u32(fdt, nodeoffset_fw, "mcc-fw-version",
121 fw_version->mcc_fw_ver);
122 if (err < 0) {
123 ERROR("NT_FW_CONFIG: Failed to set mcc-fw-version\n");
124 return -1;
125 }
126
127 err = fdt_setprop_u32(fdt, nodeoffset_fw, "pcc-fw-version",
128 fw_version->pcc_fw_ver);
129 if (err < 0) {
130 ERROR("NT_FW_CONFIG: Failed to set pcc-fw-version\n");
131 return -1;
132 }
133 #endif
134 err = fdt_setprop_u32(fdt, nodeoffset_fw, "scp-fw-version",
135 fw_version->scp_fw_ver);
136 if (err < 0) {
137 ERROR("NT_FW_CONFIG: Failed to set scp-fw-version\n");
138 return -1;
139 }
140
141 err = fdt_setprop_u32(fdt, nodeoffset_fw, "scp-fw-commit",
142 fw_version->scp_fw_commit);
143 if (err < 0) {
144 ERROR("NT_FW_CONFIG: Failed to set scp-fw-commit\n");
145 return -1;
146 }
147
148 err = fdt_setprop_string(fdt, nodeoffset_fw, "tfa-fw-version", build_version_string);
149 if (err < 0) {
150 WARN("NT_FW_CONFIG: Unable to set tfa-fw-version\n");
151 }
152
153 err = fdt_setprop_u64(fdt, nodeoffset_plat, "local-ddr-size",
154 usable_mem_size);
155 if (err < 0) {
156 ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
157 return -1;
158 }
159
160 flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
161
162 return 0;
163 }
164
165 /*******************************************************************************
166 * This function returns the list of executable images.
167 ******************************************************************************/
plat_get_next_bl_params(void)168 bl_params_t *plat_get_next_bl_params(void)
169 {
170 int ret;
171 struct morello_plat_info plat_info;
172 struct morello_firmware_version fw_version;
173
174 ret = sds_init(SDS_SCP_AP_REGION_ID);
175 if (ret != SDS_OK) {
176 ERROR("SDS initialization failed. ret:%d\n", ret);
177 panic();
178 }
179
180 ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
181 MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
182 MORELLO_SDS_PLATFORM_INFO_OFFSET,
183 &plat_info,
184 MORELLO_SDS_PLATFORM_INFO_SIZE,
185 SDS_ACCESS_MODE_NON_CACHED);
186 if (ret != SDS_OK) {
187 ERROR("Error getting platform info from SDS. ret:%d\n", ret);
188 panic();
189 }
190
191 ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
192 MORELLO_SDS_FIRMWARE_VERSION_STRUCT_ID,
193 MORELLO_SDS_FIRMWARE_VERSION_OFFSET,
194 &fw_version,
195 MORELLO_SDS_FIRMWARE_VERSION_SIZE,
196 SDS_ACCESS_MODE_NON_CACHED);
197 if (ret != SDS_OK) {
198 ERROR("Error getting firmware version from SDS. ret:%d\n", ret);
199 panic();
200 }
201
202 /* Validate plat_info SDS */
203 #ifdef TARGET_PLATFORM_FVP
204 if (plat_info.local_ddr_size == 0U) {
205 #else
206 if ((plat_info.local_ddr_size == 0U)
207 || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
208 || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
209 || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT)
210 ){
211 #endif
212 ERROR("platform info SDS is corrupted\n");
213 panic();
214 }
215
216 ret = plat_morello_append_config_node(&plat_info, &fw_version);
217 if (ret != 0) {
218 panic();
219 }
220
221 return arm_get_next_bl_params();
222 }
223