xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision 7623e085cb5396054b72f1ea3f02e8c7a34568b5)
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 unsigned int ver;
46 
47 	if (!ver) {
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 
61 	if (ver == ZYNQMP_CSU_VERSION_QEMU) {
62 		return 133000000;
63 	} else {
64 		return 100000000;
65 	}
66 }
67 
68 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
69 static const struct {
70 	uint8_t id;
71 	bool evexists;
72 	uint16_t ver;
73 	char *name;
74 } __packed zynqmp_devices[] = {
75 	{
76 		.id = 0x10,
77 		.name = "XCZU3EG",
78 	},
79 	{
80 		.id = 0x10,
81 		.ver = 0x2c,
82 		.name = "XCZU3CG",
83 	},
84 	{
85 		.id = 0x11,
86 		.name = "XCZU2EG",
87 	},
88 	{
89 		.id = 0x11,
90 		.ver = 0x2c,
91 		.name = "XCZU2CG",
92 	},
93 	{
94 		.id = 0x20,
95 		.name = "XCZU5EV",
96 		.evexists = true,
97 	},
98 	{
99 		.id = 0x20,
100 		.ver = 0x100,
101 		.name = "XCZU5EG",
102 		.evexists = true,
103 	},
104 	{
105 		.id = 0x20,
106 		.ver = 0x12c,
107 		.name = "XCZU5CG",
108 	},
109 	{
110 		.id = 0x21,
111 		.name = "XCZU4EV",
112 		.evexists = true,
113 	},
114 	{
115 		.id = 0x21,
116 		.ver = 0x100,
117 		.name = "XCZU4EG",
118 		.evexists = true,
119 	},
120 	{
121 		.id = 0x21,
122 		.ver = 0x12c,
123 		.name = "XCZU4CG",
124 	},
125 	{
126 		.id = 0x30,
127 		.name = "XCZU7EV",
128 		.evexists = true,
129 	},
130 	{
131 		.id = 0x30,
132 		.ver = 0x100,
133 		.name = "XCZU7EG",
134 		.evexists = true,
135 	},
136 	{
137 		.id = 0x30,
138 		.ver = 0x12c,
139 		.name = "XCZU7CG",
140 	},
141 	{
142 		.id = 0x38,
143 		.name = "XCZU9EG",
144 	},
145 	{
146 		.id = 0x38,
147 		.ver = 0x2c,
148 		.name = "XCZU9CG",
149 	},
150 	{
151 		.id = 0x39,
152 		.name = "XCZU6EG",
153 	},
154 	{
155 		.id = 0x39,
156 		.ver = 0x2c,
157 		.name = "XCZU6CG",
158 	},
159 	{
160 		.id = 0x40,
161 		.name = "XCZU11EG",
162 	},
163 	{
164 		.id = 0x50,
165 		.name = "XCZU15EG",
166 	},
167 	{
168 		.id = 0x58,
169 		.name = "XCZU19EG",
170 	},
171 	{
172 		.id = 0x59,
173 		.name = "XCZU17EG",
174 	},
175 	{
176 		.id = 0x60,
177 		.name = "XCZU28DR",
178 	},
179 	{
180 		.id = 0x61,
181 		.name = "XCZU21DR",
182 	},
183 	{
184 		.id = 0x62,
185 		.name = "XCZU29DR",
186 	},
187 	{
188 		.id = 0x63,
189 		.name = "XCZU23DR",
190 	},
191 	{
192 		.id = 0x64,
193 		.name = "XCZU27DR",
194 	},
195 	{
196 		.id = 0x65,
197 		.name = "XCZU25DR",
198 	},
199 	{
200 		.id = 0x66,
201 		.name = "XCZU39DR",
202 	},
203 	{
204 		.id = 0x7d,
205 		.name = "XCZU43DR",
206 	},
207 	{
208 		.id = 0x78,
209 		.name = "XCZU46DR",
210 	},
211 	{
212 		.id = 0x7f,
213 		.name = "XCZU47DR",
214 	},
215 	{
216 		.id = 0x7b,
217 		.name = "XCZU48DR",
218 	},
219 	{
220 		.id = 0x7e,
221 		.name = "XCZU49DR",
222 	},
223 };
224 
225 #define ZYNQMP_PL_STATUS_BIT	9
226 #define ZYNQMP_PL_STATUS_MASK	BIT(ZYNQMP_PL_STATUS_BIT)
227 #define ZYNQMP_CSU_VERSION_MASK	~(ZYNQMP_PL_STATUS_MASK)
228 
229 #define SILICON_ID_XCK24	0x4712093U
230 #define SILICON_ID_XCK26	0x4724093U
231 
232 static char *zynqmp_get_silicon_idcode_name(void)
233 {
234 	uint32_t id, ver, chipid[2];
235 	size_t i, j, len;
236 	const char *name = "EG/EV";
237 
238 	if (pm_get_chipid(chipid) != PM_RET_SUCCESS) {
239 		return "XCZUUNKN";
240 	}
241 
242 	id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
243 			  ZYNQMP_CSU_IDCODE_SVD_MASK);
244 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
245 	ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
246 
247 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
248 		if ((zynqmp_devices[i].id == id) &&
249 		    (zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))) {
250 			break;
251 		}
252 	}
253 
254 	if (i >= ARRAY_SIZE(zynqmp_devices)) {
255 		switch (chipid[0]) {
256 		case SILICON_ID_XCK24:
257 			return "XCK24";
258 		case SILICON_ID_XCK26:
259 			return "XCK26";
260 		default:
261 			return "XCZUUNKN";
262 		}
263 	}
264 
265 	if (!zynqmp_devices[i].evexists) {
266 		return zynqmp_devices[i].name;
267 	}
268 
269 	if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) {
270 		return zynqmp_devices[i].name;
271 	}
272 
273 	len = strlen(zynqmp_devices[i].name) - 2;
274 	for (j = 0; j < strlen(name); j++) {
275 		zynqmp_devices[i].name[len] = name[j];
276 		len++;
277 	}
278 	zynqmp_devices[i].name[len] = '\0';
279 
280 	return zynqmp_devices[i].name;
281 }
282 
283 static unsigned int zynqmp_get_rtl_ver(void)
284 {
285 	uint32_t ver;
286 
287 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
288 	ver &= ZYNQMP_RTL_VER_MASK;
289 	ver >>= ZYNQMP_RTL_VER_SHIFT;
290 
291 	return ver;
292 }
293 
294 static char *zynqmp_print_silicon_idcode(void)
295 {
296 	uint32_t id, maskid, tmp;
297 
298 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
299 
300 	tmp = id;
301 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
302 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
303 	maskid = (ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) |
304 		 (ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT);
305 	if (tmp != maskid) {
306 		ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid);
307 		return "UNKN";
308 	}
309 	VERBOSE("IDCODE 0x%x\n", id);
310 	return zynqmp_get_silicon_idcode_name();
311 }
312 
313 int32_t plat_is_smccc_feature_available(u_register_t fid)
314 {
315 	switch (fid) {
316 	case SMCCC_ARCH_SOC_ID:
317 		return SMC_ARCH_CALL_SUCCESS;
318 	default:
319 		return SMC_ARCH_CALL_NOT_SUPPORTED;
320 	}
321 
322 	return SMC_ARCH_CALL_NOT_SUPPORTED;
323 }
324 
325 int32_t plat_get_soc_version(void)
326 {
327 	uint32_t chip_id = zynqmp_get_silicon_ver();
328 	uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID);
329 
330 	return (int32_t)(manfid | (chip_id & 0xFFFF));
331 }
332 
333 int32_t plat_get_soc_revision(void)
334 {
335 	return mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
336 }
337 
338 static uint32_t zynqmp_get_ps_ver(void)
339 {
340 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
341 
342 	ver &= ZYNQMP_PS_VER_MASK;
343 	ver >>= ZYNQMP_PS_VER_SHIFT;
344 
345 	return ver + 1U;
346 }
347 
348 static void zynqmp_print_platform_name(void)
349 {
350 	uint32_t ver = zynqmp_get_silicon_ver();
351 	uint32_t rtl = zynqmp_get_rtl_ver();
352 	const char *label = "Unknown";
353 
354 	switch (ver) {
355 	case ZYNQMP_CSU_VERSION_QEMU:
356 		label = "QEMU";
357 		break;
358 	case ZYNQMP_CSU_VERSION_SILICON:
359 		label = "silicon";
360 		break;
361 	default:
362 		/* Do nothing in default case */
363 		break;
364 	}
365 
366 	VERBOSE("TF-A running on %s/%s at 0x%x\n",
367 		zynqmp_print_silicon_idcode(), label, BL31_BASE);
368 	VERBOSE("TF-A running on v%d/RTL%d.%d\n",
369 	       zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf);
370 }
371 #else
372 static inline void zynqmp_print_platform_name(void) { }
373 #endif
374 
375 uint32_t zynqmp_get_bootmode(void)
376 {
377 	uint32_t r;
378 	unsigned int ret;
379 
380 	ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
381 
382 	if (ret != PM_RET_SUCCESS) {
383 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
384 	}
385 
386 	return r & CRL_APB_BOOT_MODE_MASK;
387 }
388 
389 void zynqmp_config_setup(void)
390 {
391 	uint64_t counter_freq;
392 
393 	/* Configure IPI data for ZynqMP */
394 	zynqmp_ipi_config_table_init();
395 
396 	zynqmp_print_platform_name();
397 
398 	/* Configure counter frequency */
399 	counter_freq = read_cntfrq_el0();
400 	if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
401 		write_cntfrq_el0(plat_get_syscnt_freq2());
402 	}
403 
404 	generic_delay_timer_init();
405 }
406 
407 uint32_t plat_get_syscnt_freq2(void)
408 {
409 	uint32_t ver = zynqmp_get_silicon_ver();
410 
411 	if (ver == ZYNQMP_CSU_VERSION_QEMU) {
412 		return 65000000;
413 	} else {
414 		return mmio_read_32(IOU_SCNTRS_BASEFREQ);
415 	}
416 }
417