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