xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision d9710aeb034ed46c8e426db0479bbce43e85b12e)
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 	char *name;
64 } zynqmp_devices[] = {
65 	{
66 		.id = 0x10,
67 		.name = "3EG",
68 	},
69 	{
70 		.id = 0x11,
71 		.name = "2EG",
72 	},
73 	{
74 		.id = 0x20,
75 		.name = "5EV",
76 	},
77 	{
78 		.id = 0x21,
79 		.name = "4EV",
80 	},
81 	{
82 		.id = 0x30,
83 		.name = "7EV",
84 	},
85 	{
86 		.id = 0x38,
87 		.name = "9EG",
88 	},
89 	{
90 		.id = 0x39,
91 		.name = "6EG",
92 	},
93 	{
94 		.id = 0x40,
95 		.name = "11EG",
96 	},
97 	{
98 		.id = 0x50,
99 		.name = "15EG",
100 	},
101 	{
102 		.id = 0x58,
103 		.name = "19EG",
104 	},
105 	{
106 		.id = 0x59,
107 		.name = "17EG",
108 	},
109 	{
110 		.id = 0x60,
111 		.name = "28DR",
112 	},
113 	{
114 		.id = 0x61,
115 		.name = "21DR",
116 	},
117 	{
118 		.id = 0x62,
119 		.name = "29DR",
120 	},
121 	{
122 		.id = 0x63,
123 		.name = "23DR",
124 	},
125 	{
126 		.id = 0x64,
127 		.name = "27DR",
128 	},
129 	{
130 		.id = 0x65,
131 		.name = "25DR",
132 	},
133 };
134 
135 static unsigned int zynqmp_get_silicon_id(void)
136 {
137 	uint32_t id;
138 
139 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
140 
141 	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
142 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
143 
144 	return id;
145 }
146 
147 static char *zynqmp_get_silicon_idcode_name(void)
148 {
149 	unsigned int id;
150 
151 	id = zynqmp_get_silicon_id();
152 	for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
153 		if (zynqmp_devices[i].id == id)
154 			return zynqmp_devices[i].name;
155 	}
156 	return "UNKN";
157 }
158 
159 static unsigned int zynqmp_get_rtl_ver(void)
160 {
161 	uint32_t ver;
162 
163 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
164 	ver &= ZYNQMP_RTL_VER_MASK;
165 	ver >>= ZYNQMP_RTL_VER_SHIFT;
166 
167 	return ver;
168 }
169 
170 static char *zynqmp_print_silicon_idcode(void)
171 {
172 	uint32_t id, maskid, tmp;
173 
174 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
175 
176 	tmp = id;
177 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
178 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
179 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
180 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
181 	if (tmp != maskid) {
182 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
183 		return "UNKN";
184 	}
185 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
186 	return zynqmp_get_silicon_idcode_name();
187 }
188 
189 static unsigned int zynqmp_get_ps_ver(void)
190 {
191 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
192 
193 	ver &= ZYNQMP_PS_VER_MASK;
194 	ver >>= ZYNQMP_PS_VER_SHIFT;
195 
196 	return ver + 1;
197 }
198 
199 static void zynqmp_print_platform_name(void)
200 {
201 	unsigned int ver = zynqmp_get_silicon_ver();
202 	unsigned int rtl = zynqmp_get_rtl_ver();
203 	char *label = "Unknown";
204 
205 	switch (ver) {
206 	case ZYNQMP_CSU_VERSION_VELOCE:
207 		label = "VELOCE";
208 		break;
209 	case ZYNQMP_CSU_VERSION_EP108:
210 		label = "EP108";
211 		break;
212 	case ZYNQMP_CSU_VERSION_QEMU:
213 		label = "QEMU";
214 		break;
215 	case ZYNQMP_CSU_VERSION_SILICON:
216 		label = "silicon";
217 		break;
218 	default:
219 		/* Do nothing in default case */
220 		break;
221 	}
222 
223 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
224 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
225 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
226 	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
227 }
228 #else
229 static inline void zynqmp_print_platform_name(void) { }
230 #endif
231 
232 /*
233  * Indicator for PMUFW discovery:
234  *   0 = No FW found
235  *   non-zero = FW is present
236  */
237 static int zynqmp_pmufw_present;
238 
239 /*
240  * zynqmp_discover_pmufw - Discover presence of PMUFW
241  *
242  * Discover the presence of PMUFW and store it for later run-time queries
243  * through zynqmp_is_pmu_up.
244  * NOTE: This discovery method is fragile and will break if:
245  *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
246  *    (be it by error or intentionally)
247  *  - XPPU/XMPU may restrict ATF's access to the PMU address space
248  */
249 static int zynqmp_discover_pmufw(void)
250 {
251 	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
252 	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
253 
254 	return !!zynqmp_pmufw_present;
255 }
256 
257 /*
258  * zynqmp_is_pmu_up - Find if PMU firmware is up and running
259  *
260  * Return 0 if firmware is not available, non 0 otherwise
261  */
262 int zynqmp_is_pmu_up(void)
263 {
264 	return zynqmp_pmufw_present;
265 }
266 
267 unsigned int zynqmp_get_bootmode(void)
268 {
269 	uint32_t r;
270 
271 	if (zynqmp_is_pmu_up())
272 		pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
273 	else
274 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
275 
276 	return r & CRL_APB_BOOT_MODE_MASK;
277 }
278 
279 void zynqmp_config_setup(void)
280 {
281 	zynqmp_discover_pmufw();
282 	zynqmp_print_platform_name();
283 	generic_delay_timer_init();
284 }
285 
286 unsigned int plat_get_syscnt_freq2(void)
287 {
288 	unsigned int ver = zynqmp_get_silicon_ver();
289 
290 	switch (ver) {
291 	case ZYNQMP_CSU_VERSION_VELOCE:
292 		return 10000;
293 	case ZYNQMP_CSU_VERSION_EP108:
294 		return 4000000;
295 	case ZYNQMP_CSU_VERSION_QEMU:
296 		return 50000000;
297 	default:
298 		/* Do nothing in default case */
299 		break;
300 	}
301 
302 	return mmio_read_32(IOU_SCNTRS_BASEFREQ);
303 }
304