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