xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision e71fe2a3f21947319570c16df14a97724cc1f6a5)
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 
111 static unsigned int zynqmp_get_silicon_id(void)
112 {
113 	uint32_t id;
114 
115 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
116 
117 	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
118 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
119 
120 	return id;
121 }
122 
123 static char *zynqmp_get_silicon_idcode_name(void)
124 {
125 	unsigned int id;
126 
127 	id = zynqmp_get_silicon_id();
128 	for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
129 		if (zynqmp_devices[i].id == id)
130 			return zynqmp_devices[i].name;
131 	}
132 	return "UNKN";
133 }
134 
135 static unsigned int zynqmp_get_rtl_ver(void)
136 {
137 	uint32_t ver;
138 
139 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
140 	ver &= ZYNQMP_RTL_VER_MASK;
141 	ver >>= ZYNQMP_RTL_VER_SHIFT;
142 
143 	return ver;
144 }
145 
146 static char *zynqmp_print_silicon_idcode(void)
147 {
148 	uint32_t id, maskid, tmp;
149 
150 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
151 
152 	tmp = id;
153 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
154 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
155 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
156 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
157 	if (tmp != maskid) {
158 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
159 		return "UNKN";
160 	}
161 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
162 	return zynqmp_get_silicon_idcode_name();
163 }
164 
165 static unsigned int zynqmp_get_ps_ver(void)
166 {
167 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
168 
169 	ver &= ZYNQMP_PS_VER_MASK;
170 	ver >>= ZYNQMP_PS_VER_SHIFT;
171 
172 	return ver + 1;
173 }
174 
175 static void zynqmp_print_platform_name(void)
176 {
177 	unsigned int ver = zynqmp_get_silicon_ver();
178 	unsigned int rtl = zynqmp_get_rtl_ver();
179 	char *label = "Unknown";
180 
181 	switch (ver) {
182 	case ZYNQMP_CSU_VERSION_VELOCE:
183 		label = "VELOCE";
184 		break;
185 	case ZYNQMP_CSU_VERSION_EP108:
186 		label = "EP108";
187 		break;
188 	case ZYNQMP_CSU_VERSION_QEMU:
189 		label = "QEMU";
190 		break;
191 	case ZYNQMP_CSU_VERSION_SILICON:
192 		label = "silicon";
193 		break;
194 	default:
195 		/* Do nothing in default case */
196 		break;
197 	}
198 
199 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
200 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
201 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
202 	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
203 }
204 #else
205 static inline void zynqmp_print_platform_name(void) { }
206 #endif
207 
208 /*
209  * Indicator for PMUFW discovery:
210  *   0 = No FW found
211  *   non-zero = FW is present
212  */
213 static int zynqmp_pmufw_present;
214 
215 /*
216  * zynqmp_discover_pmufw - Discover presence of PMUFW
217  *
218  * Discover the presence of PMUFW and store it for later run-time queries
219  * through zynqmp_is_pmu_up.
220  * NOTE: This discovery method is fragile and will break if:
221  *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
222  *    (be it by error or intentionally)
223  *  - XPPU/XMPU may restrict ATF's access to the PMU address space
224  */
225 static int zynqmp_discover_pmufw(void)
226 {
227 	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
228 	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
229 
230 	return !!zynqmp_pmufw_present;
231 }
232 
233 /*
234  * zynqmp_is_pmu_up - Find if PMU firmware is up and running
235  *
236  * Return 0 if firmware is not available, non 0 otherwise
237  */
238 int zynqmp_is_pmu_up(void)
239 {
240 	return zynqmp_pmufw_present;
241 }
242 
243 unsigned int zynqmp_get_bootmode(void)
244 {
245 	uint32_t r;
246 
247 	if (zynqmp_is_pmu_up())
248 		pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
249 	else
250 		r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
251 
252 	return r & CRL_APB_BOOT_MODE_MASK;
253 }
254 
255 void zynqmp_config_setup(void)
256 {
257 	zynqmp_discover_pmufw();
258 	zynqmp_print_platform_name();
259 	generic_delay_timer_init();
260 }
261 
262 unsigned int plat_get_syscnt_freq2(void)
263 {
264 	unsigned int ver = zynqmp_get_silicon_ver();
265 
266 	switch (ver) {
267 	case ZYNQMP_CSU_VERSION_VELOCE:
268 		return 10000;
269 	case ZYNQMP_CSU_VERSION_EP108:
270 		return 4000000;
271 	case ZYNQMP_CSU_VERSION_QEMU:
272 		return 50000000;
273 	default:
274 		/* Do nothing in default case */
275 		break;
276 	}
277 
278 	return mmio_read_32(IOU_SCNTRS_BASEFREQ);
279 }
280