xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision c95b2dfae4d93a5c927a241cfaf8c746a352bd7d)
1 /*
2  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <debug.h>
8 #include <generic_delay_timer.h>
9 #include <mmio.h>
10 #include <platform.h>
11 #include <xlat_tables.h>
12 #include "../zynqmp_private.h"
13 #include "pm_api_sys.h"
14 
15 /*
16  * Table of regions to map using the MMU.
17  * This doesn't include TZRAM as the 'mem_layout' argument passed to
18  * configure_mmu_elx() will give the available subset of that,
19  */
20 const mmap_region_t plat_arm_mmap[] = {
21 	{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
22 	{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
23 	{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
24 	{0}
25 };
26 
27 static unsigned int zynqmp_get_silicon_ver(void)
28 {
29 	static unsigned int ver;
30 
31 	if (!ver) {
32 		ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
33 				   ZYNQMP_CSU_VERSION_OFFSET);
34 		ver &= ZYNQMP_SILICON_VER_MASK;
35 		ver >>= ZYNQMP_SILICON_VER_SHIFT;
36 	}
37 
38 	return ver;
39 }
40 
41 unsigned int zynqmp_get_uart_clk(void)
42 {
43 	unsigned int ver = zynqmp_get_silicon_ver();
44 
45 	switch (ver) {
46 	case ZYNQMP_CSU_VERSION_VELOCE:
47 		return 48000;
48 	case ZYNQMP_CSU_VERSION_EP108:
49 		return 25000000;
50 	case ZYNQMP_CSU_VERSION_QEMU:
51 		return 133000000;
52 	default:
53 		/* Do nothing in default case */
54 		break;
55 	}
56 
57 	return 100000000;
58 }
59 
60 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
61 static const struct {
62 	unsigned int id;
63 	unsigned int ver;
64 	char *name;
65 } zynqmp_devices[] = {
66 	{
67 		.id = 0x10,
68 		.name = "3EG",
69 	},
70 	{
71 		.id = 0x10,
72 		.ver = 0x2c,
73 		.name = "3CG",
74 	},
75 	{
76 		.id = 0x11,
77 		.name = "2EG",
78 	},
79 	{
80 		.id = 0x11,
81 		.ver = 0x2c,
82 		.name = "2CG",
83 	},
84 	{
85 		.id = 0x20,
86 		.name = "5EV",
87 	},
88 	{
89 		.id = 0x20,
90 		.ver = 0x100,
91 		.name = "5EG",
92 	},
93 	{
94 		.id = 0x20,
95 		.ver = 0x12c,
96 		.name = "5CG",
97 	},
98 	{
99 		.id = 0x21,
100 		.name = "4EV",
101 	},
102 	{
103 		.id = 0x21,
104 		.ver = 0x100,
105 		.name = "4EG",
106 	},
107 	{
108 		.id = 0x21,
109 		.ver = 0x12c,
110 		.name = "4CG",
111 	},
112 	{
113 		.id = 0x30,
114 		.name = "7EV",
115 	},
116 	{
117 		.id = 0x30,
118 		.ver = 0x100,
119 		.name = "7EG",
120 	},
121 	{
122 		.id = 0x30,
123 		.ver = 0x12c,
124 		.name = "7CG",
125 	},
126 	{
127 		.id = 0x38,
128 		.name = "9EG",
129 	},
130 	{
131 		.id = 0x38,
132 		.ver = 0x2c,
133 		.name = "9CG",
134 	},
135 	{
136 		.id = 0x39,
137 		.name = "6EG",
138 	},
139 	{
140 		.id = 0x39,
141 		.ver = 0x2c,
142 		.name = "6CG",
143 	},
144 	{
145 		.id = 0x40,
146 		.name = "11EG",
147 	},
148 	{ /* For testing purpose only */
149 		.id = 0x50,
150 		.ver = 0x2c,
151 		.name = "15CG",
152 	},
153 	{
154 		.id = 0x50,
155 		.name = "15EG",
156 	},
157 	{
158 		.id = 0x58,
159 		.name = "19EG",
160 	},
161 	{
162 		.id = 0x59,
163 		.name = "17EG",
164 	},
165 	{
166 		.id = 0x60,
167 		.name = "28DR",
168 	},
169 	{
170 		.id = 0x61,
171 		.name = "21DR",
172 	},
173 	{
174 		.id = 0x62,
175 		.name = "29DR",
176 	},
177 	{
178 		.id = 0x63,
179 		.name = "23DR",
180 	},
181 	{
182 		.id = 0x64,
183 		.name = "27DR",
184 	},
185 	{
186 		.id = 0x65,
187 		.name = "25DR",
188 	},
189 };
190 
191 static unsigned int zynqmp_get_silicon_id(void)
192 {
193 	uint32_t id;
194 
195 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
196 
197 	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
198 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
199 
200 	return id;
201 }
202 
203 static unsigned int zynqmp_get_silicon_id2(void)
204 {
205 	uint32_t id;
206 
207 	id = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET);
208 	id &= EFUSE_IPDISABLE_VERSION;
209 
210 	return id;
211 }
212 
213 static char *zynqmp_get_silicon_idcode_name(void)
214 {
215 	unsigned int id, ver;
216 	size_t i;
217 
218 	id = zynqmp_get_silicon_id();
219 	ver = zynqmp_get_silicon_id2();
220 
221 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
222 		if (zynqmp_devices[i].id == id && zynqmp_devices[i].ver == ver)
223 			return zynqmp_devices[i].name;
224 	}
225 	return "UNKN";
226 }
227 
228 static unsigned int zynqmp_get_rtl_ver(void)
229 {
230 	uint32_t ver;
231 
232 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
233 	ver &= ZYNQMP_RTL_VER_MASK;
234 	ver >>= ZYNQMP_RTL_VER_SHIFT;
235 
236 	return ver;
237 }
238 
239 static char *zynqmp_print_silicon_idcode(void)
240 {
241 	uint32_t id, maskid, tmp;
242 
243 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
244 
245 	tmp = id;
246 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
247 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
248 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
249 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
250 	if (tmp != maskid) {
251 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
252 		return "UNKN";
253 	}
254 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
255 	return zynqmp_get_silicon_idcode_name();
256 }
257 
258 static unsigned int zynqmp_get_ps_ver(void)
259 {
260 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
261 
262 	ver &= ZYNQMP_PS_VER_MASK;
263 	ver >>= ZYNQMP_PS_VER_SHIFT;
264 
265 	return ver + 1;
266 }
267 
268 static void zynqmp_print_platform_name(void)
269 {
270 	unsigned int ver = zynqmp_get_silicon_ver();
271 	unsigned int rtl = zynqmp_get_rtl_ver();
272 	char *label = "Unknown";
273 
274 	switch (ver) {
275 	case ZYNQMP_CSU_VERSION_VELOCE:
276 		label = "VELOCE";
277 		break;
278 	case ZYNQMP_CSU_VERSION_EP108:
279 		label = "EP108";
280 		break;
281 	case ZYNQMP_CSU_VERSION_QEMU:
282 		label = "QEMU";
283 		break;
284 	case ZYNQMP_CSU_VERSION_SILICON:
285 		label = "silicon";
286 		break;
287 	default:
288 		/* Do nothing in default case */
289 		break;
290 	}
291 
292 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
293 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
294 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
295 	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
296 }
297 #else
298 static inline void zynqmp_print_platform_name(void) { }
299 #endif
300 
301 /*
302  * Indicator for PMUFW discovery:
303  *   0 = No FW found
304  *   non-zero = FW is present
305  */
306 static int zynqmp_pmufw_present;
307 
308 /*
309  * zynqmp_discover_pmufw - Discover presence of PMUFW
310  *
311  * Discover the presence of PMUFW and store it for later run-time queries
312  * through zynqmp_is_pmu_up.
313  * NOTE: This discovery method is fragile and will break if:
314  *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
315  *    (be it by error or intentionally)
316  *  - XPPU/XMPU may restrict ATF's access to the PMU address space
317  */
318 static int zynqmp_discover_pmufw(void)
319 {
320 	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
321 	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
322 
323 	return !!zynqmp_pmufw_present;
324 }
325 
326 /*
327  * zynqmp_is_pmu_up - Find if PMU firmware is up and running
328  *
329  * Return 0 if firmware is not available, non 0 otherwise
330  */
331 int zynqmp_is_pmu_up(void)
332 {
333 	return zynqmp_pmufw_present;
334 }
335 
336 unsigned int zynqmp_get_bootmode(void)
337 {
338 	uint32_t r;
339 
340 	if (zynqmp_is_pmu_up())
341 		pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
342 	else
343 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
344 
345 	return r & CRL_APB_BOOT_MODE_MASK;
346 }
347 
348 void zynqmp_config_setup(void)
349 {
350 	zynqmp_discover_pmufw();
351 	zynqmp_print_platform_name();
352 	generic_delay_timer_init();
353 }
354 
355 unsigned int plat_get_syscnt_freq2(void)
356 {
357 	unsigned int ver = zynqmp_get_silicon_ver();
358 
359 	switch (ver) {
360 	case ZYNQMP_CSU_VERSION_VELOCE:
361 		return 10000;
362 	case ZYNQMP_CSU_VERSION_EP108:
363 		return 4000000;
364 	case ZYNQMP_CSU_VERSION_QEMU:
365 		return 50000000;
366 	default:
367 		/* Do nothing in default case */
368 		break;
369 	}
370 
371 	return mmio_read_32(IOU_SCNTRS_BASEFREQ);
372 }
373