xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision 466675c23daf37f6f9971b7321910e47c0c0b794)
1 /*
2  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <debug.h>
32 #include <generic_delay_timer.h>
33 #include <mmio.h>
34 #include <platform.h>
35 #include <xlat_tables.h>
36 #include "../zynqmp_private.h"
37 
38 /*
39  * Table of regions to map using the MMU.
40  * This doesn't include TZRAM as the 'mem_layout' argument passed to
41  * configure_mmu_elx() will give the available subset of that,
42  */
43 const mmap_region_t plat_arm_mmap[] = {
44 	{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
45 	{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
46 	{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
47 	{0}
48 };
49 
50 static unsigned int zynqmp_get_silicon_ver(void)
51 {
52 	static unsigned int ver;
53 
54 	if (!ver) {
55 		ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
56 				   ZYNQMP_CSU_VERSION_OFFSET);
57 		ver &= ZYNQMP_SILICON_VER_MASK;
58 		ver >>= ZYNQMP_SILICON_VER_SHIFT;
59 	}
60 
61 	return ver;
62 }
63 
64 unsigned int zynqmp_get_uart_clk(void)
65 {
66 	unsigned int ver = zynqmp_get_silicon_ver();
67 
68 	switch (ver) {
69 	case ZYNQMP_CSU_VERSION_VELOCE:
70 		return 48000;
71 	case ZYNQMP_CSU_VERSION_EP108:
72 		return 25000000;
73 	case ZYNQMP_CSU_VERSION_QEMU:
74 		return 133000000;
75 	}
76 
77 	return 100000000;
78 }
79 
80 static unsigned int zynqmp_get_system_timer_freq(void)
81 {
82 	unsigned int ver = zynqmp_get_silicon_ver();
83 
84 	switch (ver) {
85 	case ZYNQMP_CSU_VERSION_VELOCE:
86 		return 10000;
87 	case ZYNQMP_CSU_VERSION_EP108:
88 		return 4000000;
89 	case ZYNQMP_CSU_VERSION_QEMU:
90 		return 50000000;
91 	}
92 
93 	return 100000000;
94 }
95 
96 unsigned int zynqmp_get_silicon_id(void)
97 {
98 	uint32_t id;
99 
100 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
101 
102 	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
103 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
104 
105 	return id;
106 }
107 
108 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
109 static const struct {
110 	unsigned int id;
111 	char *name;
112 } zynqmp_devices[] = {
113 	{
114 		.id = 0x10,
115 		.name = "3EG",
116 	},
117 	{
118 		.id = 0x11,
119 		.name = "2EG",
120 	},
121 	{
122 		.id = 0x20,
123 		.name = "5EV",
124 	},
125 	{
126 		.id = 0x21,
127 		.name = "4EV",
128 	},
129 	{
130 		.id = 0x30,
131 		.name = "7EV",
132 	},
133 	{
134 		.id = 0x38,
135 		.name = "9EG",
136 	},
137 	{
138 		.id = 0x39,
139 		.name = "6EG",
140 	},
141 	{
142 		.id = 0x40,
143 		.name = "11EG",
144 	},
145 	{
146 		.id = 0x50,
147 		.name = "15EG",
148 	},
149 	{
150 		.id = 0x58,
151 		.name = "19EG",
152 	},
153 	{
154 		.id = 0x59,
155 		.name = "17EG",
156 	},
157 };
158 
159 static char *zynqmp_get_silicon_idcode_name(void)
160 {
161 	unsigned int id;
162 
163 	id = zynqmp_get_silicon_id();
164 	for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
165 		if (zynqmp_devices[i].id == id)
166 			return zynqmp_devices[i].name;
167 	}
168 	return "UNKN";
169 }
170 
171 static unsigned int zynqmp_get_rtl_ver(void)
172 {
173 	uint32_t ver;
174 
175 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
176 	ver &= ZYNQMP_RTL_VER_MASK;
177 	ver >>= ZYNQMP_RTL_VER_SHIFT;
178 
179 	return ver;
180 }
181 
182 static char *zynqmp_print_silicon_idcode(void)
183 {
184 	uint32_t id, maskid, tmp;
185 
186 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
187 
188 	tmp = id;
189 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
190 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
191 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
192 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
193 	if (tmp != maskid) {
194 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
195 		return "UNKN";
196 	}
197 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
198 	return zynqmp_get_silicon_idcode_name();
199 }
200 
201 static unsigned int zynqmp_get_ps_ver(void)
202 {
203 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
204 
205 	ver &= ZYNQMP_PS_VER_MASK;
206 	ver >>= ZYNQMP_PS_VER_SHIFT;
207 
208 	return ver + 1;
209 }
210 
211 static void zynqmp_print_platform_name(void)
212 {
213 	unsigned int ver = zynqmp_get_silicon_ver();
214 	unsigned int rtl = zynqmp_get_rtl_ver();
215 	char *label = "Unknown";
216 
217 	switch (ver) {
218 	case ZYNQMP_CSU_VERSION_VELOCE:
219 		label = "VELOCE";
220 		break;
221 	case ZYNQMP_CSU_VERSION_EP108:
222 		label = "EP108";
223 		break;
224 	case ZYNQMP_CSU_VERSION_QEMU:
225 		label = "QEMU";
226 		break;
227 	case ZYNQMP_CSU_VERSION_SILICON:
228 		label = "silicon";
229 		break;
230 	}
231 
232 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
233 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
234 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
235 	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
236 }
237 #else
238 static inline void zynqmp_print_platform_name(void) { }
239 #endif
240 
241 /*
242  * Indicator for PMUFW discovery:
243  *   0 = No FW found
244  *   non-zero = FW is present
245  */
246 static int zynqmp_pmufw_present;
247 
248 /*
249  * zynqmp_discover_pmufw - Discover presence of PMUFW
250  *
251  * Discover the presence of PMUFW and store it for later run-time queries
252  * through zynqmp_is_pmu_up.
253  * NOTE: This discovery method is fragile and will break if:
254  *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
255  *    (be it by error or intentionally)
256  *  - XPPU/XMPU may restrict ATF's access to the PMU address space
257  */
258 static int zynqmp_discover_pmufw(void)
259 {
260 	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
261 	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
262 
263 	return !!zynqmp_pmufw_present;
264 }
265 
266 /*
267  * zynqmp_is_pmu_up - Find if PMU firmware is up and running
268  *
269  * Return 0 if firmware is not available, non 0 otherwise
270  */
271 int zynqmp_is_pmu_up(void)
272 {
273 	return zynqmp_pmufw_present;
274 }
275 
276 unsigned int zynqmp_get_bootmode(void)
277 {
278 	uint32_t r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
279 
280 	return r & CRL_APB_BOOT_MODE_MASK;
281 }
282 
283 void zynqmp_config_setup(void)
284 {
285 	zynqmp_discover_pmufw();
286 	zynqmp_print_platform_name();
287 
288 	/* Global timer init - Program time stamp reference clk */
289 	uint32_t val = mmio_read_32(CRL_APB_TIMESTAMP_REF_CTRL);
290 	val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
291 	mmio_write_32(CRL_APB_TIMESTAMP_REF_CTRL, val);
292 
293 	/* Program freq register in System counter and enable system counter. */
294 	mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq());
295 	mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN);
296 
297 	generic_delay_timer_init();
298 }
299 
300 unsigned int plat_get_syscnt_freq2(void)
301 {
302 	unsigned int counter_base_frequency;
303 
304 	/* FIXME: Read the frequency from Frequency modes table */
305 	counter_base_frequency = zynqmp_get_system_timer_freq();
306 
307 	return counter_base_frequency;
308 }
309