xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision c3cf06f1a3a9b9ee8ac7a0ae505f95c45f7dca84)
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 <stdbool.h>
12 #include <string.h>
13 #include <xlat_tables.h>
14 #include "../zynqmp_private.h"
15 #include "pm_api_sys.h"
16 
17 /*
18  * Table of regions to map using the MMU.
19  * This doesn't include TZRAM as the 'mem_layout' argument passed to
20  * configure_mmu_elx() will give the available subset of that,
21  */
22 const mmap_region_t plat_arm_mmap[] = {
23 	{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
24 	{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
25 	{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
26 	{0}
27 };
28 
29 static unsigned int zynqmp_get_silicon_ver(void)
30 {
31 	static unsigned int ver;
32 
33 	if (!ver) {
34 		ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
35 				   ZYNQMP_CSU_VERSION_OFFSET);
36 		ver &= ZYNQMP_SILICON_VER_MASK;
37 		ver >>= ZYNQMP_SILICON_VER_SHIFT;
38 	}
39 
40 	return ver;
41 }
42 
43 unsigned int zynqmp_get_uart_clk(void)
44 {
45 	unsigned int ver = zynqmp_get_silicon_ver();
46 
47 	if (ver == ZYNQMP_CSU_VERSION_QEMU)
48 		return 133000000;
49 	else
50 		return 100000000;
51 }
52 
53 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
54 static const struct {
55 	unsigned int id;
56 	unsigned int ver;
57 	char *name;
58 	bool evexists;
59 } zynqmp_devices[] = {
60 	{
61 		.id = 0x10,
62 		.name = "3EG",
63 	},
64 	{
65 		.id = 0x10,
66 		.ver = 0x2c,
67 		.name = "3CG",
68 	},
69 	{
70 		.id = 0x11,
71 		.name = "2EG",
72 	},
73 	{
74 		.id = 0x11,
75 		.ver = 0x2c,
76 		.name = "2CG",
77 	},
78 	{
79 		.id = 0x20,
80 		.name = "5EV",
81 		.evexists = true,
82 	},
83 	{
84 		.id = 0x20,
85 		.ver = 0x100,
86 		.name = "5EG",
87 		.evexists = true,
88 	},
89 	{
90 		.id = 0x20,
91 		.ver = 0x12c,
92 		.name = "5CG",
93 	},
94 	{
95 		.id = 0x21,
96 		.name = "4EV",
97 		.evexists = true,
98 	},
99 	{
100 		.id = 0x21,
101 		.ver = 0x100,
102 		.name = "4EG",
103 		.evexists = true,
104 	},
105 	{
106 		.id = 0x21,
107 		.ver = 0x12c,
108 		.name = "4CG",
109 	},
110 	{
111 		.id = 0x30,
112 		.name = "7EV",
113 		.evexists = true,
114 	},
115 	{
116 		.id = 0x30,
117 		.ver = 0x100,
118 		.name = "7EG",
119 		.evexists = true,
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 #define ZYNQMP_PL_STATUS_BIT	9
192 #define ZYNQMP_PL_STATUS_MASK	BIT(ZYNQMP_PL_STATUS_BIT)
193 #define ZYNQMP_CSU_VERSION_MASK	~(ZYNQMP_PL_STATUS_MASK)
194 
195 static char *zynqmp_get_silicon_idcode_name(void)
196 {
197 	uint32_t id, ver, chipid[2];
198 	size_t i, j, len;
199 	const char *name = "EG/EV";
200 
201 #ifdef IMAGE_BL32
202 	/*
203 	 * For BL32, get the chip id info directly by reading corresponding
204 	 * registers instead of making pm call. This has limitation
205 	 * that these registers should be configured to have access
206 	 * from APU which is default case.
207 	 */
208 	chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
209 	chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET);
210 #else
211 	if (pm_get_chipid(chipid) != PM_RET_SUCCESS)
212 		return "UNKN";
213 #endif
214 
215 	id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
216 			  ZYNQMP_CSU_IDCODE_SVD_MASK);
217 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
218 	ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
219 
220 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
221 		if (zynqmp_devices[i].id == id &&
222 		    zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))
223 			break;
224 	}
225 
226 	if (i >= ARRAY_SIZE(zynqmp_devices))
227 		return "UNKN";
228 
229 	if (!zynqmp_devices[i].evexists)
230 		return zynqmp_devices[i].name;
231 
232 	if (ver & ZYNQMP_PL_STATUS_MASK)
233 		return zynqmp_devices[i].name;
234 
235 	len = strlen(zynqmp_devices[i].name) - 2;
236 	for (j = 0; j < strlen(name); j++) {
237 		zynqmp_devices[i].name[len] = name[j];
238 		len++;
239 	}
240 	zynqmp_devices[i].name[len] = '\0';
241 
242 	return zynqmp_devices[i].name;
243 }
244 
245 static unsigned int zynqmp_get_rtl_ver(void)
246 {
247 	uint32_t ver;
248 
249 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
250 	ver &= ZYNQMP_RTL_VER_MASK;
251 	ver >>= ZYNQMP_RTL_VER_SHIFT;
252 
253 	return ver;
254 }
255 
256 static char *zynqmp_print_silicon_idcode(void)
257 {
258 	uint32_t id, maskid, tmp;
259 
260 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
261 
262 	tmp = id;
263 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
264 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
265 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
266 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
267 	if (tmp != maskid) {
268 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
269 		return "UNKN";
270 	}
271 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
272 	return zynqmp_get_silicon_idcode_name();
273 }
274 
275 static unsigned int zynqmp_get_ps_ver(void)
276 {
277 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
278 
279 	ver &= ZYNQMP_PS_VER_MASK;
280 	ver >>= ZYNQMP_PS_VER_SHIFT;
281 
282 	return ver + 1;
283 }
284 
285 static void zynqmp_print_platform_name(void)
286 {
287 	unsigned int ver = zynqmp_get_silicon_ver();
288 	unsigned int rtl = zynqmp_get_rtl_ver();
289 	char *label = "Unknown";
290 
291 	switch (ver) {
292 	case ZYNQMP_CSU_VERSION_QEMU:
293 		label = "QEMU";
294 		break;
295 	case ZYNQMP_CSU_VERSION_SILICON:
296 		label = "silicon";
297 		break;
298 	default:
299 		/* Do nothing in default case */
300 		break;
301 	}
302 
303 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x\n",
304 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
305 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE);
306 }
307 #else
308 static inline void zynqmp_print_platform_name(void) { }
309 #endif
310 
311 unsigned int zynqmp_get_bootmode(void)
312 {
313 	uint32_t r;
314 	unsigned int ret;
315 
316 	ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
317 
318 	if (ret != PM_RET_SUCCESS)
319 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
320 
321 	return r & CRL_APB_BOOT_MODE_MASK;
322 }
323 
324 void zynqmp_config_setup(void)
325 {
326 	zynqmp_print_platform_name();
327 	generic_delay_timer_init();
328 }
329 
330 unsigned int plat_get_syscnt_freq2(void)
331 {
332 	unsigned int ver = zynqmp_get_silicon_ver();
333 
334 	if (ver == ZYNQMP_CSU_VERSION_QEMU)
335 		return 50000000;
336 	else
337 		return mmio_read_32(IOU_SCNTRS_BASEFREQ);
338 }
339