1 /*
2 * Copyright (c) 2026, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <common/debug.h>
8 #include <drivers/arm/gic600_multichip.h>
9 #include <drivers/arm/sfcp.h>
10 #include <drivers/arm/smmu_v3.h>
11 #include <lib/per_cpu/per_cpu.h>
12 #include <plat/arm/common/plat_arm.h>
13 #include <plat/common/platform.h>
14
15 #include <nrd_css_fw_def3.h>
16 #include <nrd_plat.h>
17 #include <nrd_variant.h>
18
19 #define RT_OWNER 0
20
21 /*
22 * Base addr of the frame that allocated by the platform
23 * intended for remote gic to local gic interrupt
24 * message communication
25 */
26 #define NRD_RGIC2LGIC_MESSREG_HNI_BASE UL(0x5FFF0000)
27
28 #if (PLATFORM_NODE_COUNT > 1)
29 /*
30 * NUMA node related information for a platform could be populated in by any
31 * means. This could come in via device tree, transfer list or could even be
32 * hardcoded. For rdv3cfg2, this is statically defined at the moment.
33 */
34 const uintptr_t per_cpu_nodes_base[] = {
35 (uintptr_t)PER_CPU_START,
36 (uintptr_t)NRD_REMOTE_CHIP_MEM_OFFSET(1),
37 (uintptr_t)NRD_REMOTE_CHIP_MEM_OFFSET(2),
38 (uintptr_t)NRD_REMOTE_CHIP_MEM_OFFSET(3)
39
40 };
41 #endif
42
43 #if (NRD_PLATFORM_VARIANT == 2)
44 static const mmap_region_t rdv3mc_dynamic_mmap[] = {
45 #if NRD_CHIP_COUNT > 1
46 NRD_CSS_SHARED_RAM_MMAP(1),
47 NRD_CSS_PERIPH_MMAP(1),
48 #endif
49 #if NRD_CHIP_COUNT > 2
50 NRD_CSS_SHARED_RAM_MMAP(2),
51 NRD_CSS_PERIPH_MMAP(2),
52 #endif
53 #if NRD_CHIP_COUNT > 3
54 NRD_CSS_SHARED_RAM_MMAP(3),
55 NRD_CSS_PERIPH_MMAP(3),
56 #endif
57 };
58
59 static struct gic600_multichip_data rdv3mc_multichip_data __init = {
60 .base_addrs = {
61 PLAT_ARM_GICD_BASE,
62 #if NRD_CHIP_COUNT > 1
63 PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1),
64 #endif
65 #if NRD_CHIP_COUNT > 2
66 PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2),
67 #endif
68 #if NRD_CHIP_COUNT > 3
69 PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3),
70 #endif
71 },
72 .rt_owner = RT_OWNER,
73 .chip_count = NRD_CHIP_COUNT,
74 .chip_addrs = {
75 {
76 NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
77 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
78 + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
79 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
80 + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
81 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
82 + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
83 },
84 #if NRD_CHIP_COUNT > 1
85 {
86 NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
87 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
88 + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
89 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
90 + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
91 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
92 + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
93 },
94 #endif
95 #if NRD_CHIP_COUNT > 2
96 {
97 NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
98 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
99 + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
100 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
101 + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
102 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
103 + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
104 },
105 #endif
106 #if NRD_CHIP_COUNT > 3
107 {
108 NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
109 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
110 + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
111 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
112 + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
113 (NRD_RGIC2LGIC_MESSREG_HNI_BASE
114 + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
115 }
116 #endif
117 },
118 .spi_ids = {
119 {PLAT_ARM_GICD_BASE, 32, 511},
120 #if NRD_CHIP_COUNT > 1
121 {PLAT_ARM_GICD_BASE, 512, 991},
122 #endif
123 #if NRD_CHIP_COUNT > 2
124 {PLAT_ARM_GICD_BASE, 4096, 4575},
125 #endif
126 #if NRD_CHIP_COUNT > 3
127 {PLAT_ARM_GICD_BASE, 4576, 5055},
128 #endif
129 }
130 };
131 #endif /* NRD_PLATFORM_VARIANT == 2 */
132
133 static uintptr_t rdv3mc_multichip_gicr_frames[] = {
134 /* Chip 0's GICR Base */
135 PLAT_ARM_GICR_BASE,
136 #if (NRD_PLATFORM_VARIANT == 2)
137 #if NRD_CHIP_COUNT > 1
138 /* Chip 1's GICR BASE */
139 PLAT_ARM_GICR_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1),
140 #endif
141 #if NRD_CHIP_COUNT > 2
142 /* Chip 2's GICR BASE */
143 PLAT_ARM_GICR_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2),
144 #endif
145 #if NRD_CHIP_COUNT > 3
146 /* Chip 3's GICR BASE */
147 PLAT_ARM_GICR_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3),
148 #endif
149 #endif /* NRD_PLATFORM_VARIANT == 2 */
150 UL(0) /* Zero Termination */
151 };
152
153 #if (NRD_PLATFORM_VARIANT == 2)
bl31_plat_arch_setup(void)154 void __init bl31_plat_arch_setup(void)
155 {
156 #if (PLATFORM_NODE_COUNT > 1)
157 int ret;
158 #endif
159 arm_bl31_plat_arch_setup();
160 #if (PLATFORM_NODE_COUNT > 1)
161 /* Add mmap for all remote chips */
162 for (int i = 1; i < ARRAY_SIZE(per_cpu_nodes_base); i++) {
163 ret = mmap_add_dynamic_region(
164 NRD_REMOTE_CHIP_MEM_OFFSET(i),
165 NRD_REMOTE_CHIP_MEM_OFFSET(i),
166 NRD_CSS_PAGE_ALIGN_CEIL((PER_CPU_END - PER_CPU_START)),
167 MT_MEMORY | MT_RW | EL3_PAS);
168 if (ret != 0) {
169 ERROR("Failed to add per-cpu mmap (ret=%d)", ret);
170 panic();
171 }
172 }
173 #endif
174 }
175 #endif
176
bl31_platform_setup(void)177 void bl31_platform_setup(void)
178 {
179 enum sfcp_error_t sfcp_err;
180
181 /*
182 * Perform SMMUv3 GPT configuration for the GPC SMMU present in system
183 * control block on RD-V3 platforms. This SMMUv3 initialization is
184 * not fatal.
185 *
186 * Don't perform smmuv3_security_init() for this instance of SMMUv3 as
187 * the global aborts need not be configured to allow the components in
188 * system control block send transations downstream to SMMUv3.
189 */
190 if (smmuv3_init(NRD_CSS_GPC_SMMUV3_BASE) != 0) {
191 WARN("Failed initializing System SMMU.\n");
192 }
193
194 #if (NRD_PLATFORM_VARIANT == 2)
195 int ret;
196 unsigned int i;
197
198 if (plat_arm_nrd_get_multi_chip_mode() == 0) {
199 ERROR("Chip Count is %u but multi-chip mode is not enabled\n",
200 NRD_CHIP_COUNT);
201 panic();
202 } else {
203 INFO("Enabling multi-chip support for RD-V3 variant\n");
204
205 for (i = 0; i < ARRAY_SIZE(rdv3mc_dynamic_mmap); i++) {
206 ret = mmap_add_dynamic_region(
207 rdv3mc_dynamic_mmap[i].base_pa,
208 rdv3mc_dynamic_mmap[i].base_va,
209 rdv3mc_dynamic_mmap[i].size,
210 rdv3mc_dynamic_mmap[i].attr);
211 if (ret != 0) {
212 ERROR("Failed to add entry i: %d (ret=%d)\n",
213 i, ret);
214 panic();
215 }
216 }
217
218 gic600_multichip_init(&rdv3mc_multichip_data);
219 }
220 #endif /* NRD_PLATFORM_VARIANT == 2 */
221 nrd_bl31_common_platform_setup();
222
223 gic_set_gicr_frames(
224 rdv3mc_multichip_gicr_frames);
225
226 /* Initialize SFCP for communications between AP and RSE */
227 sfcp_err = sfcp_init();
228 if (sfcp_err != SFCP_ERROR_SUCCESS) {
229 WARN("Failed initializing AP-RSE comms.\n");
230 }
231 }
232
233 #if RESET_TO_BL31
234 /*
235 * The GPT library might modify the gpt regions structure to optimize
236 * the layout, so the array cannot be constant.
237 */
238 static pas_region_t pas_regions[] = {
239 NRD_PAS_SHARED_SRAM,
240 NRD_PAS_SYSTEM_NCI,
241 NRD_PAS_DEBUG_NIC,
242 NRD_PAS_NS_UART,
243 NRD_PAS_REALM_UART,
244 NRD_PAS_AP_NS_WDOG,
245 NRD_PAS_AP_ROOT_WDOG,
246 NRD_PAS_AP_SECURE_WDOG,
247 NRD_PAS_SECURE_SRAM_ERB_AP,
248 NRD_PAS_NS_SRAM_ERB_AP,
249 NRD_PAS_ROOT_SRAM_ERB_AP,
250 NRD_PAS_REALM_SRAM_ERB_AP,
251 NRD_PAS_SECURE_SRAM_ERB_SCP,
252 NRD_PAS_NS_SRAM_ERB_SCP,
253 NRD_PAS_ROOT_SRAM_ERB_SCP,
254 NRD_PAS_REALM_SRAM_ERB_SCP,
255 NRD_PAS_SECURE_SRAM_ERB_MCP,
256 NRD_PAS_NS_SRAM_ERB_MCP,
257 NRD_PAS_ROOT_SRAM_ERB_MCP,
258 NRD_PAS_REALM_SRAM_ERB_MCP,
259 NRD_PAS_SECURE_SRAM_ERB_RSE,
260 NRD_PAS_NS_SRAM_ERB_RSE,
261 NRD_PAS_ROOT_SRAM_ERB_RSE,
262 NRD_PAS_REALM_SRAM_ERB_RSE,
263 NRD_PAS_RSE_SECURE_SRAM_ERB_RSM,
264 NRD_PAS_RSE_NS_SRAM_ERB_RSM,
265 NRD_PAS_SCP_SECURE_SRAM_ERB_RSM,
266 NRD_PAS_SCP_NS_SRAM_ERB_RSM,
267 NRD_PAS_MCP_SECURE_SRAM_ERB_RSM,
268 NRD_PAS_MCP_NS_SRAM_ERB_RSM,
269 NRD_PAS_AP_SCP_ROOT_MHU,
270 NRD_PAS_AP_MCP_NS_MHU,
271 NRD_PAS_AP_MCP_SECURE_MHU,
272 NRD_PAS_AP_MCP_ROOT_MHU,
273 NRD_PAS_AP_RSE_NS_MHU,
274 NRD_PAS_AP_RSE_SECURE_MHU,
275 NRD_PAS_AP_RSE_ROOT_MHU,
276 NRD_PAS_AP_RSE_REALM_MHU,
277 NRD_PAS_SCP_MCP_RSE_CROSS_CHIP_MHU,
278 NRD_PAS_SYNCNT_MSTUPDTVAL_ADDR,
279 NRD_PAS_STM_SYSTEM_ITS,
280 NRD_PAS_SCP_MCP_RSE_SHARED_SRAM,
281 NRD_PAS_GIC,
282 NRD_PAS_NS_DRAM,
283 NRD_PAS_RMM,
284 NRD_PAS_L1GPT,
285 NRD_PAS_CMN,
286 NRD_PAS_LCP_PERIPHERAL,
287 NRD_PAS_DDR_IO,
288 NRD_PAS_SMMU_NCI_IO,
289 NRD_PAS_DRAM2_CHIP0,
290 #if NRD_CHIP_COUNT > 1
291 NRD_PAS_DRAM1_CHIP1,
292 NRD_PAS_DRAM2_CHIP1,
293 #endif
294 #if NRD_CHIP_COUNT > 2
295 NRD_PAS_DRAM1_CHIP2,
296 NRD_PAS_DRAM2_CHIP2,
297 #endif
298 #if NRD_CHIP_COUNT > 3
299 NRD_PAS_DRAM1_CHIP3,
300 NRD_PAS_DRAM2_CHIP3
301 #endif
302 };
303
304 static const arm_gpt_info_t arm_gpt_info = {
305 .pas_region_base = pas_regions,
306 .pas_region_count = (unsigned int)ARRAY_SIZE(pas_regions),
307 .l0_base = (uintptr_t)ARM_L0_GPT_BASE,
308 .l1_base = (uintptr_t)ARM_L1_GPT_BASE,
309 .l0_size = (size_t)ARM_L0_GPT_SIZE,
310 .l1_size = (size_t)ARM_L1_GPT_SIZE,
311 .pps = GPCCR_PPS_256TB,
312 .pgs = GPCCR_PGS_4K
313 };
314
plat_arm_get_gpt_info(void)315 const arm_gpt_info_t *plat_arm_get_gpt_info(void)
316 {
317 return &arm_gpt_info;
318 }
319
320 #endif /* RESET_TO_BL31 */
321