xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision a6d28520b5c6a86047b2bb7b0e821dfe48957a64)
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\n",
293 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
294 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE);
295 }
296 #else
297 static inline void zynqmp_print_platform_name(void) { }
298 #endif
299 
300 unsigned int zynqmp_get_bootmode(void)
301 {
302 	uint32_t r;
303 	unsigned int ret;
304 
305 	ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
306 
307 	if (ret != PM_RET_SUCCESS)
308 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
309 
310 	return r & CRL_APB_BOOT_MODE_MASK;
311 }
312 
313 void zynqmp_config_setup(void)
314 {
315 	zynqmp_print_platform_name();
316 	generic_delay_timer_init();
317 }
318 
319 unsigned int plat_get_syscnt_freq2(void)
320 {
321 	unsigned int ver = zynqmp_get_silicon_ver();
322 
323 	switch (ver) {
324 	case ZYNQMP_CSU_VERSION_VELOCE:
325 		return 10000;
326 	case ZYNQMP_CSU_VERSION_EP108:
327 		return 4000000;
328 	case ZYNQMP_CSU_VERSION_QEMU:
329 		return 50000000;
330 	default:
331 		/* Do nothing in default case */
332 		break;
333 	}
334 
335 	return mmio_read_32(IOU_SCNTRS_BASEFREQ);
336 }
337