xref: /rk3399_ARM-atf/plat/qemu/qemu_sbsa/sbsa_platform.c (revision ecadac7cd21fa755a7d9fcaa92ec4be23dc263b2)
1*ecadac7cSMathieu Poirier /*
2*ecadac7cSMathieu Poirier  * Copyright (c) 2024-2025, Linaro Limited. All rights reserved.
3*ecadac7cSMathieu Poirier  *
4*ecadac7cSMathieu Poirier  * SPDX-License-Identifier: BSD-3-Clause
5*ecadac7cSMathieu Poirier  */
6*ecadac7cSMathieu Poirier 
7*ecadac7cSMathieu Poirier #include <assert.h>
8*ecadac7cSMathieu Poirier 
9*ecadac7cSMathieu Poirier #include <common/fdt_wrappers.h>
10*ecadac7cSMathieu Poirier #include <libfdt.h>
11*ecadac7cSMathieu Poirier 
12*ecadac7cSMathieu Poirier #include <sbsa_platform.h>
13*ecadac7cSMathieu Poirier 
14*ecadac7cSMathieu Poirier /* default platform version is 0.0 */
15*ecadac7cSMathieu Poirier static int platform_version_major;
16*ecadac7cSMathieu Poirier static int platform_version_minor;
17*ecadac7cSMathieu Poirier 
18*ecadac7cSMathieu Poirier static uint64_t gic_its_addr;
19*ecadac7cSMathieu Poirier static struct qemu_platform_info dynamic_platform_info;
20*ecadac7cSMathieu Poirier 
21*ecadac7cSMathieu Poirier void sbsa_set_gic_bases(const uintptr_t gicd_base, const uintptr_t gicr_base);
22*ecadac7cSMathieu Poirier 
23*ecadac7cSMathieu Poirier /*
24*ecadac7cSMathieu Poirier  * QEMU provides us with minimal information about hardware platform using
25*ecadac7cSMathieu Poirier  * minimalistic DeviceTree. This is not a Linux DeviceTree. It is not even
26*ecadac7cSMathieu Poirier  * a firmware DeviceTree.
27*ecadac7cSMathieu Poirier  *
28*ecadac7cSMathieu Poirier  * It is information passed from QEMU to describe the information a hardware
29*ecadac7cSMathieu Poirier  * platform would have other mechanisms to discover at runtime, that are
30*ecadac7cSMathieu Poirier  * affected by the QEMU command line.
31*ecadac7cSMathieu Poirier  *
32*ecadac7cSMathieu Poirier  * Ultimately this device tree will be replaced by IPC calls to an emulated SCP.
33*ecadac7cSMathieu Poirier  * And when we do that, we won't then have to rewrite Normal world firmware to
34*ecadac7cSMathieu Poirier  * cope.
35*ecadac7cSMathieu Poirier  */
36*ecadac7cSMathieu Poirier 
37*ecadac7cSMathieu Poirier static void read_cpu_topology_from_dt(void *dtb)
38*ecadac7cSMathieu Poirier {
39*ecadac7cSMathieu Poirier 	int node;
40*ecadac7cSMathieu Poirier 
41*ecadac7cSMathieu Poirier 	/*
42*ecadac7cSMathieu Poirier 	 * QEMU gives us this DeviceTree node when we config:
43*ecadac7cSMathieu Poirier 	 * -smp 16,sockets=2,clusters=2,cores=2,threads=2
44*ecadac7cSMathieu Poirier 	 *
45*ecadac7cSMathieu Poirier 	 * topology {
46*ecadac7cSMathieu Poirier 	 *	threads = <0x02>;
47*ecadac7cSMathieu Poirier 	 *	cores = <0x02>;
48*ecadac7cSMathieu Poirier 	 *	clusters = <0x02>;
49*ecadac7cSMathieu Poirier 	 *	sockets = <0x02>;
50*ecadac7cSMathieu Poirier 	 * };
51*ecadac7cSMathieu Poirier 	 */
52*ecadac7cSMathieu Poirier 
53*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/cpus/topology");
54*ecadac7cSMathieu Poirier 	if (node > 0) {
55*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.sockets =
56*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "sockets", 0);
57*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.clusters =
58*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "clusters", 0);
59*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.cores =
60*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "cores", 0);
61*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.threads =
62*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "threads", 0);
63*ecadac7cSMathieu Poirier 	}
64*ecadac7cSMathieu Poirier 
65*ecadac7cSMathieu Poirier 	INFO("Cpu topology: sockets: %d, clusters: %d, cores: %d, threads: %d\n",
66*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.sockets,
67*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.clusters,
68*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.cores,
69*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu_topo.threads);
70*ecadac7cSMathieu Poirier }
71*ecadac7cSMathieu Poirier 
72*ecadac7cSMathieu Poirier static void read_cpuinfo_from_dt(void *dtb)
73*ecadac7cSMathieu Poirier {
74*ecadac7cSMathieu Poirier 	int node;
75*ecadac7cSMathieu Poirier 	int prev;
76*ecadac7cSMathieu Poirier 	int cpu = 0;
77*ecadac7cSMathieu Poirier 	uintptr_t mpidr;
78*ecadac7cSMathieu Poirier 
79*ecadac7cSMathieu Poirier 	/*
80*ecadac7cSMathieu Poirier 	 * QEMU gives us this DeviceTree node:
81*ecadac7cSMathieu Poirier 	 * numa-node-id entries are only when NUMA config is used
82*ecadac7cSMathieu Poirier 	 *
83*ecadac7cSMathieu Poirier 	 *  cpus {
84*ecadac7cSMathieu Poirier 	 *	#size-cells = <0x00>;
85*ecadac7cSMathieu Poirier 	 *	#address-cells = <0x02>;
86*ecadac7cSMathieu Poirier 	 *
87*ecadac7cSMathieu Poirier 	 *	cpu@0 {
88*ecadac7cSMathieu Poirier 	 *		numa-node-id = <0x00>;
89*ecadac7cSMathieu Poirier 	 *		reg = <0x00 0x00>;
90*ecadac7cSMathieu Poirier 	 *	};
91*ecadac7cSMathieu Poirier 	 *
92*ecadac7cSMathieu Poirier 	 *	cpu@1 {
93*ecadac7cSMathieu Poirier 	 *		numa-node-id = <0x03>;
94*ecadac7cSMathieu Poirier 	 *		reg = <0x00 0x01>;
95*ecadac7cSMathieu Poirier 	 *	};
96*ecadac7cSMathieu Poirier 	 *  };
97*ecadac7cSMathieu Poirier 	 */
98*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/cpus");
99*ecadac7cSMathieu Poirier 	if (node < 0) {
100*ecadac7cSMathieu Poirier 		ERROR("No information about cpus in DeviceTree.\n");
101*ecadac7cSMathieu Poirier 		panic();
102*ecadac7cSMathieu Poirier 	}
103*ecadac7cSMathieu Poirier 
104*ecadac7cSMathieu Poirier 	/*
105*ecadac7cSMathieu Poirier 	 * QEMU numbers cpus from 0 and there can be /cpus/cpu-map present so we
106*ecadac7cSMathieu Poirier 	 * cannot use fdt_first_subnode() here
107*ecadac7cSMathieu Poirier 	 */
108*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/cpus/cpu@0");
109*ecadac7cSMathieu Poirier 
110*ecadac7cSMathieu Poirier 	while (node > 0) {
111*ecadac7cSMathieu Poirier 		if (fdt_getprop(dtb, node, "reg", NULL)) {
112*ecadac7cSMathieu Poirier 			fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL);
113*ecadac7cSMathieu Poirier 		} else {
114*ecadac7cSMathieu Poirier 			ERROR("Incomplete information for cpu %d in DeviceTree.\n", cpu);
115*ecadac7cSMathieu Poirier 			panic();
116*ecadac7cSMathieu Poirier 		}
117*ecadac7cSMathieu Poirier 
118*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu[cpu].mpidr = mpidr;
119*ecadac7cSMathieu Poirier 		dynamic_platform_info.cpu[cpu].nodeid =
120*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
121*ecadac7cSMathieu Poirier 
122*ecadac7cSMathieu Poirier 		INFO("CPU %d: node-id: %d, mpidr: %ld\n", cpu,
123*ecadac7cSMathieu Poirier 				dynamic_platform_info.cpu[cpu].nodeid, mpidr);
124*ecadac7cSMathieu Poirier 
125*ecadac7cSMathieu Poirier 		cpu++;
126*ecadac7cSMathieu Poirier 
127*ecadac7cSMathieu Poirier 		prev = node;
128*ecadac7cSMathieu Poirier 		node = fdt_next_subnode(dtb, prev);
129*ecadac7cSMathieu Poirier 	}
130*ecadac7cSMathieu Poirier 
131*ecadac7cSMathieu Poirier 	dynamic_platform_info.num_cpus = cpu;
132*ecadac7cSMathieu Poirier 	INFO("Found %d cpus\n", dynamic_platform_info.num_cpus);
133*ecadac7cSMathieu Poirier 
134*ecadac7cSMathieu Poirier 	read_cpu_topology_from_dt(dtb);
135*ecadac7cSMathieu Poirier }
136*ecadac7cSMathieu Poirier 
137*ecadac7cSMathieu Poirier static void read_meminfo_from_dt(void *dtb)
138*ecadac7cSMathieu Poirier {
139*ecadac7cSMathieu Poirier 	const fdt32_t *prop;
140*ecadac7cSMathieu Poirier 	const char *type;
141*ecadac7cSMathieu Poirier 	int prev, node;
142*ecadac7cSMathieu Poirier 	int len;
143*ecadac7cSMathieu Poirier 	uint32_t memnode = 0;
144*ecadac7cSMathieu Poirier 	uint32_t higher_value, lower_value;
145*ecadac7cSMathieu Poirier 	uint64_t cur_base, cur_size;
146*ecadac7cSMathieu Poirier 
147*ecadac7cSMathieu Poirier 	/*
148*ecadac7cSMathieu Poirier 	 * QEMU gives us this DeviceTree node:
149*ecadac7cSMathieu Poirier 	 *
150*ecadac7cSMathieu Poirier 	 *	memory@100c0000000 {
151*ecadac7cSMathieu Poirier 	 *		numa-node-id = <0x01>;
152*ecadac7cSMathieu Poirier 	 *		reg = <0x100 0xc0000000 0x00 0x40000000>;
153*ecadac7cSMathieu Poirier 	 *		device_type = "memory";
154*ecadac7cSMathieu Poirier 	 *	};
155*ecadac7cSMathieu Poirier 	 *
156*ecadac7cSMathieu Poirier 	 *	memory@10000000000 {
157*ecadac7cSMathieu Poirier 	 *		numa-node-id = <0x00>;
158*ecadac7cSMathieu Poirier 	 *		reg = <0x100 0x00 0x00 0xc0000000>;
159*ecadac7cSMathieu Poirier 	 *		device_type = "memory";
160*ecadac7cSMathieu Poirier 	 *	}
161*ecadac7cSMathieu Poirier 	 */
162*ecadac7cSMathieu Poirier 
163*ecadac7cSMathieu Poirier 	for (prev = 0;; prev = node) {
164*ecadac7cSMathieu Poirier 		node = fdt_next_node(dtb, prev, NULL);
165*ecadac7cSMathieu Poirier 		if (node < 0) {
166*ecadac7cSMathieu Poirier 			break;
167*ecadac7cSMathieu Poirier 		}
168*ecadac7cSMathieu Poirier 
169*ecadac7cSMathieu Poirier 		type = fdt_getprop(dtb, node, "device_type", &len);
170*ecadac7cSMathieu Poirier 		if (type && strncmp(type, "memory", len) == 0) {
171*ecadac7cSMathieu Poirier 			dynamic_platform_info.memory[memnode].nodeid =
172*ecadac7cSMathieu Poirier 				fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
173*ecadac7cSMathieu Poirier 
174*ecadac7cSMathieu Poirier 			/*
175*ecadac7cSMathieu Poirier 			 * Get the 'reg' property of this node and
176*ecadac7cSMathieu Poirier 			 * assume two 8 bytes for base and size.
177*ecadac7cSMathieu Poirier 			 */
178*ecadac7cSMathieu Poirier 			prop = fdt_getprop(dtb, node, "reg", &len);
179*ecadac7cSMathieu Poirier 			if (prop != 0 && len == (2 * sizeof(int64_t))) {
180*ecadac7cSMathieu Poirier 				higher_value = fdt32_to_cpu(*prop);
181*ecadac7cSMathieu Poirier 				lower_value = fdt32_to_cpu(*(prop + 1));
182*ecadac7cSMathieu Poirier 				cur_base = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
183*ecadac7cSMathieu Poirier 
184*ecadac7cSMathieu Poirier 				higher_value = fdt32_to_cpu(*(prop + 2));
185*ecadac7cSMathieu Poirier 				lower_value = fdt32_to_cpu(*(prop + 3));
186*ecadac7cSMathieu Poirier 				cur_size = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
187*ecadac7cSMathieu Poirier 
188*ecadac7cSMathieu Poirier 				dynamic_platform_info.memory[memnode].addr_base = cur_base;
189*ecadac7cSMathieu Poirier 				dynamic_platform_info.memory[memnode].addr_size = cur_size;
190*ecadac7cSMathieu Poirier 
191*ecadac7cSMathieu Poirier 				INFO("RAM %d: node-id: %d, address: 0x%lx - 0x%lx\n",
192*ecadac7cSMathieu Poirier 					memnode,
193*ecadac7cSMathieu Poirier 					dynamic_platform_info.memory[memnode].nodeid,
194*ecadac7cSMathieu Poirier 					dynamic_platform_info.memory[memnode].addr_base,
195*ecadac7cSMathieu Poirier 					dynamic_platform_info.memory[memnode].addr_base +
196*ecadac7cSMathieu Poirier 					dynamic_platform_info.memory[memnode].addr_size - 1);
197*ecadac7cSMathieu Poirier 			}
198*ecadac7cSMathieu Poirier 
199*ecadac7cSMathieu Poirier 			memnode++;
200*ecadac7cSMathieu Poirier 		}
201*ecadac7cSMathieu Poirier 	}
202*ecadac7cSMathieu Poirier 
203*ecadac7cSMathieu Poirier 	dynamic_platform_info.num_memnodes = memnode;
204*ecadac7cSMathieu Poirier }
205*ecadac7cSMathieu Poirier 
206*ecadac7cSMathieu Poirier static void read_platform_config_from_dt(void *dtb)
207*ecadac7cSMathieu Poirier {
208*ecadac7cSMathieu Poirier 	int node;
209*ecadac7cSMathieu Poirier 	const fdt64_t *data;
210*ecadac7cSMathieu Poirier 	int err;
211*ecadac7cSMathieu Poirier 	uintptr_t gicd_base;
212*ecadac7cSMathieu Poirier 	uintptr_t gicr_base;
213*ecadac7cSMathieu Poirier 
214*ecadac7cSMathieu Poirier 	/*
215*ecadac7cSMathieu Poirier 	 * QEMU gives us this DeviceTree node:
216*ecadac7cSMathieu Poirier 	 *
217*ecadac7cSMathieu Poirier 	 * intc {
218*ecadac7cSMathieu Poirier 	 *	 reg = < 0x00 0x40060000 0x00 0x10000
219*ecadac7cSMathieu Poirier 	 *		 0x00 0x40080000 0x00 0x4000000>;
220*ecadac7cSMathieu Poirier 	 *       its {
221*ecadac7cSMathieu Poirier 	 *               reg = <0x00 0x44081000 0x00 0x20000>;
222*ecadac7cSMathieu Poirier 	 *       };
223*ecadac7cSMathieu Poirier 	 * };
224*ecadac7cSMathieu Poirier 	 */
225*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/intc");
226*ecadac7cSMathieu Poirier 	if (node < 0) {
227*ecadac7cSMathieu Poirier 		return;
228*ecadac7cSMathieu Poirier 	}
229*ecadac7cSMathieu Poirier 
230*ecadac7cSMathieu Poirier 	data = fdt_getprop(dtb, node, "reg", NULL);
231*ecadac7cSMathieu Poirier 	if (data == NULL) {
232*ecadac7cSMathieu Poirier 		return;
233*ecadac7cSMathieu Poirier 	}
234*ecadac7cSMathieu Poirier 
235*ecadac7cSMathieu Poirier 	err = fdt_get_reg_props_by_index(dtb, node, 0, &gicd_base, NULL);
236*ecadac7cSMathieu Poirier 	if (err < 0) {
237*ecadac7cSMathieu Poirier 		ERROR("Failed to read GICD reg property of GIC node\n");
238*ecadac7cSMathieu Poirier 		return;
239*ecadac7cSMathieu Poirier 	}
240*ecadac7cSMathieu Poirier 	INFO("GICD base = 0x%lx\n", gicd_base);
241*ecadac7cSMathieu Poirier 
242*ecadac7cSMathieu Poirier 	err = fdt_get_reg_props_by_index(dtb, node, 1, &gicr_base, NULL);
243*ecadac7cSMathieu Poirier 	if (err < 0) {
244*ecadac7cSMathieu Poirier 		ERROR("Failed to read GICR reg property of GIC node\n");
245*ecadac7cSMathieu Poirier 		return;
246*ecadac7cSMathieu Poirier 	}
247*ecadac7cSMathieu Poirier 	INFO("GICR base = 0x%lx\n", gicr_base);
248*ecadac7cSMathieu Poirier 
249*ecadac7cSMathieu Poirier 	sbsa_set_gic_bases(gicd_base, gicr_base);
250*ecadac7cSMathieu Poirier 
251*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/intc/its");
252*ecadac7cSMathieu Poirier 	if (node < 0) {
253*ecadac7cSMathieu Poirier 		return;
254*ecadac7cSMathieu Poirier 	}
255*ecadac7cSMathieu Poirier 
256*ecadac7cSMathieu Poirier 	err = fdt_get_reg_props_by_index(dtb, node, 0, &gic_its_addr, NULL);
257*ecadac7cSMathieu Poirier 	if (err < 0) {
258*ecadac7cSMathieu Poirier 		ERROR("Failed to read GICI reg property of GIC node\n");
259*ecadac7cSMathieu Poirier 		return;
260*ecadac7cSMathieu Poirier 	}
261*ecadac7cSMathieu Poirier 	INFO("GICI base = 0x%lx\n", gic_its_addr);
262*ecadac7cSMathieu Poirier }
263*ecadac7cSMathieu Poirier 
264*ecadac7cSMathieu Poirier static void read_platform_version(void *dtb)
265*ecadac7cSMathieu Poirier {
266*ecadac7cSMathieu Poirier 	int node;
267*ecadac7cSMathieu Poirier 
268*ecadac7cSMathieu Poirier 	node = fdt_path_offset(dtb, "/");
269*ecadac7cSMathieu Poirier 	if (node >= 0) {
270*ecadac7cSMathieu Poirier 		platform_version_major =
271*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "machine-version-major", 0);
272*ecadac7cSMathieu Poirier 		platform_version_minor =
273*ecadac7cSMathieu Poirier 			fdt_read_uint32_default(dtb, node, "machine-version-minor", 0);
274*ecadac7cSMathieu Poirier 	}
275*ecadac7cSMathieu Poirier }
276*ecadac7cSMathieu Poirier 
277*ecadac7cSMathieu Poirier void sbsa_platform_init(void)
278*ecadac7cSMathieu Poirier {
279*ecadac7cSMathieu Poirier 	/* Read DeviceTree data before MMU is enabled */
280*ecadac7cSMathieu Poirier 
281*ecadac7cSMathieu Poirier 	void *dtb = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
282*ecadac7cSMathieu Poirier 	int err;
283*ecadac7cSMathieu Poirier 
284*ecadac7cSMathieu Poirier 	err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE);
285*ecadac7cSMathieu Poirier 	if (err < 0) {
286*ecadac7cSMathieu Poirier 		ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
287*ecadac7cSMathieu Poirier 		return;
288*ecadac7cSMathieu Poirier 	}
289*ecadac7cSMathieu Poirier 
290*ecadac7cSMathieu Poirier 	err = fdt_check_header(dtb);
291*ecadac7cSMathieu Poirier 	if (err < 0) {
292*ecadac7cSMathieu Poirier 		ERROR("Invalid DTB file passed\n");
293*ecadac7cSMathieu Poirier 		return;
294*ecadac7cSMathieu Poirier 	}
295*ecadac7cSMathieu Poirier 
296*ecadac7cSMathieu Poirier 	read_platform_version(dtb);
297*ecadac7cSMathieu Poirier 	INFO("Platform version: %d.%d\n", platform_version_major, platform_version_minor);
298*ecadac7cSMathieu Poirier 
299*ecadac7cSMathieu Poirier 	read_platform_config_from_dt(dtb);
300*ecadac7cSMathieu Poirier 	read_cpuinfo_from_dt(dtb);
301*ecadac7cSMathieu Poirier 	read_meminfo_from_dt(dtb);
302*ecadac7cSMathieu Poirier }
303*ecadac7cSMathieu Poirier 
304*ecadac7cSMathieu Poirier int sbsa_platform_version_major(void)
305*ecadac7cSMathieu Poirier {
306*ecadac7cSMathieu Poirier 	return platform_version_major;
307*ecadac7cSMathieu Poirier }
308*ecadac7cSMathieu Poirier 
309*ecadac7cSMathieu Poirier int sbsa_platform_version_minor(void)
310*ecadac7cSMathieu Poirier {
311*ecadac7cSMathieu Poirier 	return platform_version_minor;
312*ecadac7cSMathieu Poirier }
313*ecadac7cSMathieu Poirier 
314*ecadac7cSMathieu Poirier uint32_t sbsa_platform_num_cpus(void)
315*ecadac7cSMathieu Poirier {
316*ecadac7cSMathieu Poirier 	return dynamic_platform_info.num_cpus;
317*ecadac7cSMathieu Poirier }
318*ecadac7cSMathieu Poirier 
319*ecadac7cSMathieu Poirier uint32_t sbsa_platform_num_memnodes(void)
320*ecadac7cSMathieu Poirier {
321*ecadac7cSMathieu Poirier 	return dynamic_platform_info.num_memnodes;
322*ecadac7cSMathieu Poirier }
323*ecadac7cSMathieu Poirier 
324*ecadac7cSMathieu Poirier uint64_t sbsa_platform_gic_its_addr(void)
325*ecadac7cSMathieu Poirier {
326*ecadac7cSMathieu Poirier 	return gic_its_addr;
327*ecadac7cSMathieu Poirier }
328*ecadac7cSMathieu Poirier 
329*ecadac7cSMathieu Poirier struct platform_cpu_data sbsa_platform_cpu_node(uint64_t index)
330*ecadac7cSMathieu Poirier {
331*ecadac7cSMathieu Poirier 	return dynamic_platform_info.cpu[index];
332*ecadac7cSMathieu Poirier }
333*ecadac7cSMathieu Poirier 
334*ecadac7cSMathieu Poirier struct platform_memory_data sbsa_platform_memory_node(uint64_t index)
335*ecadac7cSMathieu Poirier {
336*ecadac7cSMathieu Poirier 	return dynamic_platform_info.memory[index];
337*ecadac7cSMathieu Poirier }
338*ecadac7cSMathieu Poirier 
339*ecadac7cSMathieu Poirier struct platform_cpu_topology sbsa_platform_cpu_topology(void)
340*ecadac7cSMathieu Poirier {
341*ecadac7cSMathieu Poirier 	return dynamic_platform_info.cpu_topo;
342*ecadac7cSMathieu Poirier }
343