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