xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/aarch64/zynqmp_common.c (revision 532ed6183868036e4a4f83cd7a71b93266a3bdb7)
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 <mmio.h>
33 #include <platform.h>
34 #include <xlat_tables.h>
35 #include "../zynqmp_private.h"
36 
37 /*
38  * Table of regions to map using the MMU.
39  * This doesn't include TZRAM as the 'mem_layout' argument passed to
40  * configure_mmu_elx() will give the available subset of that,
41  */
42 const mmap_region_t plat_arm_mmap[] = {
43 	{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
44 	{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
45 	{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
46 	{0}
47 };
48 
49 static unsigned int zynqmp_get_silicon_ver(void)
50 {
51 	unsigned int ver;
52 
53 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
54 	ver &= ZYNQMP_SILICON_VER_MASK;
55 	ver >>= ZYNQMP_SILICON_VER_SHIFT;
56 
57 	return ver;
58 }
59 
60 unsigned int zynqmp_get_uart_clk(void)
61 {
62 	unsigned int ver = zynqmp_get_silicon_ver();
63 
64 	switch (ver) {
65 	case ZYNQMP_CSU_VERSION_VELOCE:
66 		return 48000;
67 	case ZYNQMP_CSU_VERSION_EP108:
68 		return 25000000;
69 	case ZYNQMP_CSU_VERSION_QEMU:
70 		return 133000000;
71 	}
72 
73 	return 100000000;
74 }
75 
76 static unsigned int zynqmp_get_system_timer_freq(void)
77 {
78 	unsigned int ver = zynqmp_get_silicon_ver();
79 
80 	switch (ver) {
81 	case ZYNQMP_CSU_VERSION_VELOCE:
82 		return 10000;
83 	case ZYNQMP_CSU_VERSION_EP108:
84 		return 4000000;
85 	case ZYNQMP_CSU_VERSION_QEMU:
86 		return 50000000;
87 	}
88 
89 	return 100000000;
90 }
91 
92 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
93 static const struct {
94 	unsigned int id;
95 	char *name;
96 } zynqmp_devices[] = {
97 	{
98 		.id = 0x10,
99 		.name = "3EG",
100 	},
101 	{
102 		.id = 0x11,
103 		.name = "2EG",
104 	},
105 	{
106 		.id = 0x20,
107 		.name = "5EV",
108 	},
109 	{
110 		.id = 0x21,
111 		.name = "4EV",
112 	},
113 	{
114 		.id = 0x30,
115 		.name = "7EV",
116 	},
117 	{
118 		.id = 0x38,
119 		.name = "9EG",
120 	},
121 	{
122 		.id = 0x39,
123 		.name = "6EG",
124 	},
125 	{
126 		.id = 0x40,
127 		.name = "11EG",
128 	},
129 	{
130 		.id = 0x50,
131 		.name = "15EG",
132 	},
133 	{
134 		.id = 0x58,
135 		.name = "19EG",
136 	},
137 	{
138 		.id = 0x59,
139 		.name = "17EG",
140 	},
141 };
142 
143 static unsigned int zynqmp_get_silicon_id(void)
144 {
145 	uint32_t id;
146 
147 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
148 
149 	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
150 	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
151 
152 	return id;
153 }
154 
155 static char *zynqmp_get_silicon_idcode_name(void)
156 {
157 	unsigned int id;
158 
159 	id = zynqmp_get_silicon_id();
160 	for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
161 		if (zynqmp_devices[i].id == id)
162 			return zynqmp_devices[i].name;
163 	}
164 	return "UNKN";
165 }
166 
167 static unsigned int zynqmp_get_rtl_ver(void)
168 {
169 	uint32_t ver;
170 
171 	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
172 	ver &= ZYNQMP_RTL_VER_MASK;
173 	ver >>= ZYNQMP_RTL_VER_SHIFT;
174 
175 	return ver;
176 }
177 
178 static char *zynqmp_print_silicon_idcode(void)
179 {
180 	uint32_t id, maskid, tmp;
181 
182 	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
183 
184 	tmp = id;
185 	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
186 	       ZYNQMP_CSU_IDCODE_FAMILY_MASK;
187 	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
188 		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
189 	if (tmp != maskid) {
190 		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
191 		return "UNKN";
192 	}
193 	VERBOSE("Xilinx IDCODE 0x%x\n", id);
194 	return zynqmp_get_silicon_idcode_name();
195 }
196 
197 static unsigned int zynqmp_get_ps_ver(void)
198 {
199 	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
200 
201 	ver &= ZYNQMP_PS_VER_MASK;
202 	ver >>= ZYNQMP_PS_VER_SHIFT;
203 
204 	return ver + 1;
205 }
206 
207 static void zynqmp_print_platform_name(void)
208 {
209 	unsigned int ver = zynqmp_get_silicon_ver();
210 	unsigned int rtl = zynqmp_get_rtl_ver();
211 	char *label = "Unknown";
212 
213 	switch (ver) {
214 	case ZYNQMP_CSU_VERSION_VELOCE:
215 		label = "VELOCE";
216 		break;
217 	case ZYNQMP_CSU_VERSION_EP108:
218 		label = "EP108";
219 		break;
220 	case ZYNQMP_CSU_VERSION_QEMU:
221 		label = "QEMU";
222 		break;
223 	case ZYNQMP_CSU_VERSION_SILICON:
224 		label = "silicon";
225 		break;
226 	}
227 
228 	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
229 	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
230 	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
231 	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
232 }
233 #else
234 static inline void zynqmp_print_platform_name(void) { }
235 #endif
236 
237 /*
238  * Indicator for PMUFW discovery:
239  *   0 = No FW found
240  *   non-zero = FW is present
241  */
242 static int zynqmp_pmufw_present;
243 
244 /*
245  * zynqmp_discover_pmufw - Discover presence of PMUFW
246  *
247  * Discover the presence of PMUFW and store it for later run-time queries
248  * through zynqmp_is_pmu_up.
249  * NOTE: This discovery method is fragile and will break if:
250  *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
251  *    (be it by error or intentionally)
252  *  - XPPU/XMPU may restrict ATF's access to the PMU address space
253  */
254 static int zynqmp_discover_pmufw(void)
255 {
256 	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
257 	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
258 
259 	return !!zynqmp_pmufw_present;
260 }
261 
262 /*
263  * zynqmp_is_pmu_up - Find if PMU firmware is up and running
264  *
265  * Return 0 if firmware is not available, non 0 otherwise
266  */
267 int zynqmp_is_pmu_up(void)
268 {
269 	return zynqmp_pmufw_present;
270 }
271 
272 unsigned int zynqmp_get_bootmode(void)
273 {
274 	uint32_t 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 
284 	/* Global timer init - Program time stamp reference clk */
285 	uint32_t val = mmio_read_32(CRL_APB_TIMESTAMP_REF_CTRL);
286 	val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
287 	mmio_write_32(CRL_APB_TIMESTAMP_REF_CTRL, val);
288 
289 	/* Program freq register in System counter and enable system counter. */
290 	mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq());
291 	mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN);
292 }
293 
294 unsigned int plat_get_syscnt_freq2(void)
295 {
296 	unsigned int counter_base_frequency;
297 
298 	/* FIXME: Read the frequency from Frequency modes table */
299 	counter_base_frequency = zynqmp_get_system_timer_freq();
300 
301 	return counter_base_frequency;
302 }
303