blob: fd054beb9450b08eaae8a6aab6db4e3eb29c9386 [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
2 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmann76fcae32016-03-06 20:16:27 -08005 */
6
Soren Brinkmann76fcae32016-03-06 20:16:27 -08007#include <debug.h>
Soren Brinkmanne5bdcaa2016-06-22 09:02:56 -07008#include <generic_delay_timer.h>
Soren Brinkmann76fcae32016-03-06 20:16:27 -08009#include <mmio.h>
Soren Brinkmann76fcae32016-03-06 20:16:27 -080010#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 */
19const 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
26static unsigned int zynqmp_get_silicon_ver(void)
27{
Soren Brinkmann85863992016-09-16 10:34:47 -070028 static unsigned int ver;
Soren Brinkmann76fcae32016-03-06 20:16:27 -080029
Soren Brinkmann85863992016-09-16 10:34:47 -070030 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 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -080036
37 return ver;
38}
39
40unsigned 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;
Jonathan Wrightff957ed2018-03-14 15:24:00 +000051 default:
52 /* Do nothing in default case */
53 break;
Soren Brinkmann76fcae32016-03-06 20:16:27 -080054 }
55
56 return 100000000;
57}
58
Soren Brinkmann76fcae32016-03-06 20:16:27 -080059#if LOG_LEVEL >= LOG_LEVEL_NOTICE
60static 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
Soren Brinkmanncb366812016-09-22 12:21:11 -0700110static 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
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800122static 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
134static 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
145static 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 |
Soren Brinkmann31114132016-05-20 07:05:00 -0700153 ZYNQMP_CSU_IDCODE_FAMILY_MASK;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800154 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
Soren Brinkmann31114132016-05-20 07:05:00 -0700155 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800156 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
164static 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
174static 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;
Jonathan Wrightff957ed2018-03-14 15:24:00 +0000193 default:
194 /* Do nothing in default case */
195 break;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800196 }
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
204static 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 */
212static 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 */
224static 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 */
237int zynqmp_is_pmu_up(void)
238{
239 return zynqmp_pmufw_present;
240}
241
Soren Brinkmannb43d9432016-04-18 11:49:42 -0700242unsigned 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
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800249void zynqmp_config_setup(void)
250{
251 zynqmp_discover_pmufw();
252 zynqmp_print_platform_name();
Soren Brinkmanne5bdcaa2016-06-22 09:02:56 -0700253 generic_delay_timer_init();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800254}
255
Antonio Nino Diaze82e29c2016-05-19 10:00:28 +0100256unsigned int plat_get_syscnt_freq2(void)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800257{
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700258 unsigned int ver = zynqmp_get_silicon_ver();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800259
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700260 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;
Jonathan Wrightff957ed2018-03-14 15:24:00 +0000267 default:
268 /* Do nothing in default case */
269 break;
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700270 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800271
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700272 return mmio_read_32(IOU_SCNTRS_BASEFREQ);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800273}