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