blob: d7a7d4e2e8f0396bab04a2055c4484ae43602be7 [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;
51 }
52
53 return 100000000;
54}
55
Soren Brinkmann76fcae32016-03-06 20:16:27 -080056#if LOG_LEVEL >= LOG_LEVEL_NOTICE
57static const struct {
58 unsigned int id;
59 char *name;
60} zynqmp_devices[] = {
61 {
62 .id = 0x10,
63 .name = "3EG",
64 },
65 {
66 .id = 0x11,
67 .name = "2EG",
68 },
69 {
70 .id = 0x20,
71 .name = "5EV",
72 },
73 {
74 .id = 0x21,
75 .name = "4EV",
76 },
77 {
78 .id = 0x30,
79 .name = "7EV",
80 },
81 {
82 .id = 0x38,
83 .name = "9EG",
84 },
85 {
86 .id = 0x39,
87 .name = "6EG",
88 },
89 {
90 .id = 0x40,
91 .name = "11EG",
92 },
93 {
94 .id = 0x50,
95 .name = "15EG",
96 },
97 {
98 .id = 0x58,
99 .name = "19EG",
100 },
101 {
102 .id = 0x59,
103 .name = "17EG",
104 },
105};
106
Soren Brinkmanncb366812016-09-22 12:21:11 -0700107static unsigned int zynqmp_get_silicon_id(void)
108{
109 uint32_t id;
110
111 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
112
113 id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
114 id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
115
116 return id;
117}
118
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800119static char *zynqmp_get_silicon_idcode_name(void)
120{
121 unsigned int id;
122
123 id = zynqmp_get_silicon_id();
124 for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
125 if (zynqmp_devices[i].id == id)
126 return zynqmp_devices[i].name;
127 }
128 return "UNKN";
129}
130
131static unsigned int zynqmp_get_rtl_ver(void)
132{
133 uint32_t ver;
134
135 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
136 ver &= ZYNQMP_RTL_VER_MASK;
137 ver >>= ZYNQMP_RTL_VER_SHIFT;
138
139 return ver;
140}
141
142static char *zynqmp_print_silicon_idcode(void)
143{
144 uint32_t id, maskid, tmp;
145
146 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
147
148 tmp = id;
149 tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
Soren Brinkmann31114132016-05-20 07:05:00 -0700150 ZYNQMP_CSU_IDCODE_FAMILY_MASK;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800151 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
Soren Brinkmann31114132016-05-20 07:05:00 -0700152 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800153 if (tmp != maskid) {
154 ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
155 return "UNKN";
156 }
157 VERBOSE("Xilinx IDCODE 0x%x\n", id);
158 return zynqmp_get_silicon_idcode_name();
159}
160
161static unsigned int zynqmp_get_ps_ver(void)
162{
163 uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
164
165 ver &= ZYNQMP_PS_VER_MASK;
166 ver >>= ZYNQMP_PS_VER_SHIFT;
167
168 return ver + 1;
169}
170
171static void zynqmp_print_platform_name(void)
172{
173 unsigned int ver = zynqmp_get_silicon_ver();
174 unsigned int rtl = zynqmp_get_rtl_ver();
175 char *label = "Unknown";
176
177 switch (ver) {
178 case ZYNQMP_CSU_VERSION_VELOCE:
179 label = "VELOCE";
180 break;
181 case ZYNQMP_CSU_VERSION_EP108:
182 label = "EP108";
183 break;
184 case ZYNQMP_CSU_VERSION_QEMU:
185 label = "QEMU";
186 break;
187 case ZYNQMP_CSU_VERSION_SILICON:
188 label = "silicon";
189 break;
190 }
191
192 NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
193 zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
194 (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
195 zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
196}
197#else
198static inline void zynqmp_print_platform_name(void) { }
199#endif
200
201/*
202 * Indicator for PMUFW discovery:
203 * 0 = No FW found
204 * non-zero = FW is present
205 */
206static int zynqmp_pmufw_present;
207
208/*
209 * zynqmp_discover_pmufw - Discover presence of PMUFW
210 *
211 * Discover the presence of PMUFW and store it for later run-time queries
212 * through zynqmp_is_pmu_up.
213 * NOTE: This discovery method is fragile and will break if:
214 * - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
215 * (be it by error or intentionally)
216 * - XPPU/XMPU may restrict ATF's access to the PMU address space
217 */
218static int zynqmp_discover_pmufw(void)
219{
220 zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
221 zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
222
223 return !!zynqmp_pmufw_present;
224}
225
226/*
227 * zynqmp_is_pmu_up - Find if PMU firmware is up and running
228 *
229 * Return 0 if firmware is not available, non 0 otherwise
230 */
231int zynqmp_is_pmu_up(void)
232{
233 return zynqmp_pmufw_present;
234}
235
Soren Brinkmannb43d9432016-04-18 11:49:42 -0700236unsigned int zynqmp_get_bootmode(void)
237{
238 uint32_t r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
239
240 return r & CRL_APB_BOOT_MODE_MASK;
241}
242
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800243void zynqmp_config_setup(void)
244{
245 zynqmp_discover_pmufw();
246 zynqmp_print_platform_name();
Soren Brinkmanne5bdcaa2016-06-22 09:02:56 -0700247 generic_delay_timer_init();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800248}
249
Antonio Nino Diaze82e29c2016-05-19 10:00:28 +0100250unsigned int plat_get_syscnt_freq2(void)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800251{
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700252 unsigned int ver = zynqmp_get_silicon_ver();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800253
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700254 switch (ver) {
255 case ZYNQMP_CSU_VERSION_VELOCE:
256 return 10000;
257 case ZYNQMP_CSU_VERSION_EP108:
258 return 4000000;
259 case ZYNQMP_CSU_VERSION_QEMU:
260 return 50000000;
261 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800262
Soren Brinkmanncfcb1a22016-09-16 10:31:06 -0700263 return mmio_read_32(IOU_SCNTRS_BASEFREQ);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800264}