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