blob: 7a2a4f6daaff9d570591a5c1b0726586518e2fa0 [file] [log] [blame]
Soren Brinkmannc8284402016-03-06 20:16:27 -08001/*
2 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmannc8284402016-03-06 20:16:27 -08005 */
6
Soren Brinkmannc8284402016-03-06 20:16:27 -08007#include <debug.h>
Soren Brinkmanne1cb4da2016-06-22 09:02:56 -07008#include <generic_delay_timer.h>
Soren Brinkmannc8284402016-03-06 20:16:27 -08009#include <mmio.h>
Soren Brinkmannc8284402016-03-06 20:16:27 -080010#include <platform.h>
11#include <xlat_tables.h>
12#include "../zynqmp_private.h"
Siva Durga Prasad Paladugu29bd0e62017-02-20 17:55:50 +053013#include "pm_api_sys.h"
Soren Brinkmannc8284402016-03-06 20:16:27 -080014
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 */
20const 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
27static unsigned int zynqmp_get_silicon_ver(void)
28{
Soren Brinkmann466675c2016-09-16 10:34:47 -070029 static unsigned int ver;
Soren Brinkmannc8284402016-03-06 20:16:27 -080030
Soren Brinkmann466675c2016-09-16 10:34:47 -070031 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 }
Soren Brinkmannc8284402016-03-06 20:16:27 -080037
38 return ver;
39}
40
41unsigned 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;
Jonathan Wright649c48f2018-03-14 15:24:00 +000052 default:
53 /* Do nothing in default case */
54 break;
Soren Brinkmannc8284402016-03-06 20:16:27 -080055 }
56
57 return 100000000;
58}
59
Soren Brinkmannc8284402016-03-06 20:16:27 -080060#if LOG_LEVEL >= LOG_LEVEL_NOTICE
61static 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 },
Siva Durga Prasad Paladugud9710ae2017-06-06 12:54:52 +0530109 {
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 },
Soren Brinkmannc8284402016-03-06 20:16:27 -0800133};
134
Soren Brinkmann46cb6842016-09-22 12:21:11 -0700135static 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
Soren Brinkmannc8284402016-03-06 20:16:27 -0800147static 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
159static 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
170static 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 |
Soren Brinkmann648fe992016-05-20 07:05:00 -0700178 ZYNQMP_CSU_IDCODE_FAMILY_MASK;
Soren Brinkmannc8284402016-03-06 20:16:27 -0800179 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
Soren Brinkmann648fe992016-05-20 07:05:00 -0700180 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
Soren Brinkmannc8284402016-03-06 20:16:27 -0800181 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
189static 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
199static 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;
Jonathan Wright649c48f2018-03-14 15:24:00 +0000218 default:
219 /* Do nothing in default case */
220 break;
Soren Brinkmannc8284402016-03-06 20:16:27 -0800221 }
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
229static 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 */
237static 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 */
249static 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 */
262int zynqmp_is_pmu_up(void)
263{
264 return zynqmp_pmufw_present;
265}
266
Soren Brinkmann2cb5bac2016-04-18 11:49:42 -0700267unsigned int zynqmp_get_bootmode(void)
268{
Siva Durga Prasad Paladugu29bd0e62017-02-20 17:55:50 +0530269 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);
Soren Brinkmann2cb5bac2016-04-18 11:49:42 -0700275
276 return r & CRL_APB_BOOT_MODE_MASK;
277}
278
Soren Brinkmannc8284402016-03-06 20:16:27 -0800279void zynqmp_config_setup(void)
280{
281 zynqmp_discover_pmufw();
282 zynqmp_print_platform_name();
Soren Brinkmanne1cb4da2016-06-22 09:02:56 -0700283 generic_delay_timer_init();
Soren Brinkmannc8284402016-03-06 20:16:27 -0800284}
285
Antonio Nino Diazf3d3b312016-05-19 10:00:28 +0100286unsigned int plat_get_syscnt_freq2(void)
Soren Brinkmannc8284402016-03-06 20:16:27 -0800287{
Soren Brinkmanne89f4af2016-09-16 10:31:06 -0700288 unsigned int ver = zynqmp_get_silicon_ver();
Soren Brinkmannc8284402016-03-06 20:16:27 -0800289
Soren Brinkmanne89f4af2016-09-16 10:31:06 -0700290 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;
Jonathan Wright649c48f2018-03-14 15:24:00 +0000297 default:
298 /* Do nothing in default case */
299 break;
Soren Brinkmanne89f4af2016-09-16 10:31:06 -0700300 }
Soren Brinkmannc8284402016-03-06 20:16:27 -0800301
Soren Brinkmanne89f4af2016-09-16 10:31:06 -0700302 return mmio_read_32(IOU_SCNTRS_BASEFREQ);
Soren Brinkmannc8284402016-03-06 20:16:27 -0800303}