xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision 906d58927760c70112fd8e70a7e67f2a4989e9ed)
1 /*
2  * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
3  * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <stdbool.h>
9 #include <string.h>
10 
11 #include <common/debug.h>
12 #include <drivers/generic_delay_timer.h>
13 #include <lib/mmio.h>
14 #include <lib/smccc.h>
15 #include <lib/xlat_tables/xlat_tables_v2.h>
16 #include <plat/common/platform.h>
17 #include <plat_arm.h>
18 #include <services/arm_arch_svc.h>
19 
20 #include <plat_ipi.h>
21 #include <plat_private.h>
22 #include <plat_startup.h>
23 
24 #include "zynqmp_pm_api_sys.h"
25 
26 /*
27  * Table of regions to map using the MMU.
28  * This doesn't include TZRAM as the 'mem_layout' argument passed to
29  * configure_mmu_elx() will give the available subset of that,
30  */
31 const mmap_region_t plat_zynqmp_mmap[] = {
32 	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
33 	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
34 	MAP_REGION_FLAT(CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
35 	{0}
36 };
37 
38 const mmap_region_t *plat_get_mmap(void)
39 {
40 	return plat_zynqmp_mmap;
41 }
42 
43 static uint32_t zynqmp_get_silicon_ver(void)
44 {
45 	static uint32_t ver;
46 
47 	if (ver == 0U) {
48 		ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
49 				   ZYNQMP_CSU_VERSION_OFFSET);
50 		ver &= ZYNQMP_SILICON_VER_MASK;
51 		ver >>= ZYNQMP_SILICON_VER_SHIFT;
52 	}
53 
54 	return ver;
55 }
56 
57 uint32_t get_uart_clk(void)
58 {
59 	unsigned int ver = zynqmp_get_silicon_ver();
60 	uint32_t uart_clk = 0U;
61 
62 	if (ver == ZYNQMP_CSU_VERSION_QEMU) {
63 		uart_clk = 133000000U;
64 	} else {
65 		uart_clk = 100000000U;
66 	}
67 
68 	return uart_clk;
69 }
70 
71 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
72 static const struct {
73 	uint8_t id;
74 	bool evexists;
75 	uint16_t ver;
76 	char *name;
77 } __packed zynqmp_devices[] = {
78 	{
79 		.id = 0x10,
80 		.name = "XCZU3EG",
81 	},
82 	{
83 		.id = 0x10,
84 		.ver = 0x2c,
85 		.name = "XCZU3CG",
86 	},
87 	{
88 		.id = 0x11,
89 		.name = "XCZU2EG",
90 	},
91 	{
92 		.id = 0x11,
93 		.ver = 0x2c,
94 		.name = "XCZU2CG",
95 	},
96 	{
97 		.id = 0x20,
98 		.name = "XCZU5EV",
99 		.evexists = true,
100 	},
101 	{
102 		.id = 0x20,
103 		.ver = 0x100,
104 		.name = "XCZU5EG",
105 		.evexists = true,
106 	},
107 	{
108 		.id = 0x20,
109 		.ver = 0x12c,
110 		.name = "XCZU5CG",
111 	},
112 	{
113 		.id = 0x21,
114 		.name = "XCZU4EV",
115 		.evexists = true,
116 	},
117 	{
118 		.id = 0x21,
119 		.ver = 0x100,
120 		.name = "XCZU4EG",
121 		.evexists = true,
122 	},
123 	{
124 		.id = 0x21,
125 		.ver = 0x12c,
126 		.name = "XCZU4CG",
127 	},
128 	{
129 		.id = 0x30,
130 		.name = "XCZU7EV",
131 		.evexists = true,
132 	},
133 	{
134 		.id = 0x30,
135 		.ver = 0x100,
136 		.name = "XCZU7EG",
137 		.evexists = true,
138 	},
139 	{
140 		.id = 0x30,
141 		.ver = 0x12c,
142 		.name = "XCZU7CG",
143 	},
144 	{
145 		.id = 0x38,
146 		.name = "XCZU9EG",
147 	},
148 	{
149 		.id = 0x38,
150 		.ver = 0x2c,
151 		.name = "XCZU9CG",
152 	},
153 	{
154 		.id = 0x39,
155 		.name = "XCZU6EG",
156 	},
157 	{
158 		.id = 0x39,
159 		.ver = 0x2c,
160 		.name = "XCZU6CG",
161 	},
162 	{
163 		.id = 0x40,
164 		.name = "XCZU11EG",
165 	},
166 	{
167 		.id = 0x50,
168 		.name = "XCZU15EG",
169 	},
170 	{
171 		.id = 0x58,
172 		.name = "XCZU19EG",
173 	},
174 	{
175 		.id = 0x59,
176 		.name = "XCZU17EG",
177 	},
178 	{
179 		.id = 0x60,
180 		.name = "XCZU28DR",
181 	},
182 	{
183 		.id = 0x61,
184 		.name = "XCZU21DR",
185 	},
186 	{
187 		.id = 0x62,
188 		.name = "XCZU29DR",
189 	},
190 	{
191 		.id = 0x63,
192 		.name = "XCZU23DR",
193 	},
194 	{
195 		.id = 0x64,
196 		.name = "XCZU27DR",
197 	},
198 	{
199 		.id = 0x65,
200 		.name = "XCZU25DR",
201 	},
202 	{
203 		.id = 0x66,
204 		.name = "XCZU39DR",
205 	},
206 	{
207 		.id = 0x7d,
208 		.name = "XCZU43DR",
209 	},
210 	{
211 		.id = 0x78,
212 		.name = "XCZU46DR",
213 	},
214 	{
215 		.id = 0x7f,
216 		.name = "XCZU47DR",
217 	},
218 	{
219 		.id = 0x7b,
220 		.name = "XCZU48DR",
221 	},
222 	{
223 		.id = 0x7e,
224 		.name = "XCZU49DR",
225 	},
226 };
227 
228 #define ZYNQMP_PL_STATUS_BIT	9
229 #define ZYNQMP_PL_STATUS_MASK	BIT(ZYNQMP_PL_STATUS_BIT)
230 #define ZYNQMP_CSU_VERSION_MASK	~(ZYNQMP_PL_STATUS_MASK)
231 
232 #define SILICON_ID_XCK24	0x4712093U
233 #define SILICON_ID_XCK26	0x4724093U
234 
235 static char *zynqmp_get_silicon_idcode_name(void)
236 {
237 	uint32_t id, ver, chipid[2];
238 	size_t i, j, len;
239 	const char *name = "EG/EV";
240 
241 	if (pm_get_chipid(chipid) != PM_RET_SUCCESS) {
242 		return "XCZUUNKN";
243 	}
244 
245 	id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
246 			  ZYNQMP_CSU_IDCODE_SVD_MASK);
247 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
248 	ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
249 
250 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
251 		if ((zynqmp_devices[i].id == id) &&
252 		    (zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))) {
253 			break;
254 		}
255 	}
256 
257 	if (i >= ARRAY_SIZE(zynqmp_devices)) {
258 		switch (chipid[0]) {
259 		case SILICON_ID_XCK24:
260 			return "XCK24";
261 		case SILICON_ID_XCK26:
262 			return "XCK26";
263 		default:
264 			return "XCZUUNKN";
265 		}
266 	}
267 
268 	if (!zynqmp_devices[i].evexists) {
269 		return zynqmp_devices[i].name;
270 	}
271 
272 	if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) {
273 		return zynqmp_devices[i].name;
274 	}
275 
276 	len = strlen(zynqmp_devices[i].name) - 2U;
277 	for (j = 0; j < strlen(name); j++) {
278 		zynqmp_devices[i].name[len] = name[j];
279 		len++;
280 	}
281 	zynqmp_devices[i].name[len] = '\0';
282 
283 	return zynqmp_devices[i].name;
284 }
285 
286 static unsigned int zynqmp_get_rtl_ver(void)
287 {
288 	uint32_t ver;
289 
290 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
291 	ver &= ZYNQMP_RTL_VER_MASK;
292 	ver >>= ZYNQMP_RTL_VER_SHIFT;
293 
294 	return ver;
295 }
296 
297 static char *zynqmp_print_silicon_idcode(void)
298 {
299 	uint32_t id, maskid, tmp;
300 
301 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
302 
303 	tmp = id;
304 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
305 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
306 	maskid = (ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) |
307 		 (ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT);
308 	if (tmp != maskid) {
309 		ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid);
310 		return "UNKN";
311 	}
312 	VERBOSE("IDCODE 0x%x\n", id);
313 	return zynqmp_get_silicon_idcode_name();
314 }
315 
316 int32_t plat_is_smccc_feature_available(u_register_t fid)
317 {
318 	int32_t ret = SMC_ARCH_CALL_NOT_SUPPORTED;
319 
320 	switch (fid) {
321 	case SMCCC_ARCH_SOC_ID:
322 		ret = SMC_ARCH_CALL_SUCCESS;
323 		break;
324 	default:
325 		break;
326 	}
327 
328 	return ret;
329 }
330 
331 int32_t plat_get_soc_version(void)
332 {
333 	uint32_t chip_id = zynqmp_get_silicon_ver();
334 	uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID);
335 	uint32_t result = (manfid | (chip_id & 0xFFFFU));
336 
337 	return (int32_t)result;
338 }
339 
340 int32_t plat_get_soc_revision(void)
341 {
342 	return (int32_t)mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
343 }
344 
345 static uint32_t zynqmp_get_ps_ver(void)
346 {
347 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
348 
349 	ver &= ZYNQMP_PS_VER_MASK;
350 	ver >>= ZYNQMP_PS_VER_SHIFT;
351 
352 	return ver + 1U;
353 }
354 
355 static void zynqmp_print_platform_name(void)
356 {
357 	uint32_t ver = zynqmp_get_silicon_ver();
358 	uint32_t rtl = zynqmp_get_rtl_ver();
359 	const char *label = "Unknown";
360 
361 	switch (ver) {
362 	case ZYNQMP_CSU_VERSION_QEMU:
363 		label = "QEMU";
364 		break;
365 	case ZYNQMP_CSU_VERSION_SILICON:
366 		label = "silicon";
367 		break;
368 	default:
369 		/* Do nothing in default case */
370 		break;
371 	}
372 
373 	VERBOSE("TF-A running on %s/%s at 0x%x\n",
374 		zynqmp_print_silicon_idcode(), label, BL31_BASE);
375 	VERBOSE("TF-A running on v%d/RTL%d.%d\n",
376 	       zynqmp_get_ps_ver(), (rtl & 0xf0U) >> 4U, rtl & 0xfU);
377 }
378 #else
379 static inline void zynqmp_print_platform_name(void) { }
380 #endif
381 
382 uint32_t zynqmp_get_bootmode(void)
383 {
384 	uint32_t r;
385 	enum pm_ret_status ret;
386 
387 	ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
388 
389 	if (ret != PM_RET_SUCCESS) {
390 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
391 	}
392 
393 	return r & CRL_APB_BOOT_MODE_MASK;
394 }
395 
396 void zynqmp_config_setup(void)
397 {
398 	uint64_t counter_freq;
399 
400 	/* Configure IPI data for ZynqMP */
401 	zynqmp_ipi_config_table_init();
402 
403 	zynqmp_print_platform_name();
404 
405 	/* Configure counter frequency */
406 	counter_freq = read_cntfrq_el0();
407 	if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
408 		write_cntfrq_el0(plat_get_syscnt_freq2());
409 	}
410 
411 	generic_delay_timer_init();
412 }
413 
414 uint32_t plat_get_syscnt_freq2(void)
415 {
416 	uint32_t ver = zynqmp_get_silicon_ver();
417 	uint32_t ret = 0U;
418 
419 	if (ver == ZYNQMP_CSU_VERSION_QEMU) {
420 		ret = 65000000U;
421 	} else {
422 		ret = mmio_read_32((uint64_t)IOU_SCNTRS_BASEFREQ);
423 	}
424 
425 	return ret;
426 }
427