blob: 1748fec2e4d9b2c8d6941415b64a8e63fe0437a6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek04b7e622015-01-15 10:01:51 +01002/*
3 * (C) Copyright 2014 - 2015 Xilinx, Inc.
4 * Michal Simek <michal.simek@xilinx.com>
Michal Simek04b7e622015-01-15 10:01:51 +01005 */
6
7#include <common.h>
Simon Glassed38aef2020-05-10 11:40:03 -06008#include <command.h>
Simon Glass370382c2019-11-14 12:57:35 -07009#include <cpu_func.h>
Michal Simek09a7d7d2020-01-07 09:02:52 +010010#include <debug_uart.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060011#include <env.h>
Michal Simek8d4a8d42020-07-30 13:37:49 +020012#include <env_internal.h>
Simon Glassa7b51302019-11-14 12:57:46 -070013#include <init.h>
Michal Simek97ab9612021-05-31 11:03:19 +020014#include <image.h>
15#include <lmb.h>
Simon Glass0f2af882020-05-10 11:40:05 -060016#include <log.h>
Simon Glass274e0b02020-05-10 11:39:56 -060017#include <net.h>
Michal Simekd54b1af2015-09-30 17:26:55 +020018#include <sata.h>
Michal Simekb216cc12015-07-23 13:27:40 +020019#include <ahci.h>
20#include <scsi.h>
Michal Simekecfb6dc2016-04-22 14:28:54 +020021#include <malloc.h>
Michal Simekbf0f9ca2018-04-19 15:43:38 +020022#include <wdt.h>
Michal Simekc23d3f82015-11-05 08:34:35 +010023#include <asm/arch/clk.h>
Michal Simek04b7e622015-01-15 10:01:51 +010024#include <asm/arch/hardware.h>
25#include <asm/arch/sys_proto.h>
Michal Simekf2f08642018-01-10 09:36:09 +010026#include <asm/arch/psu_init_gpl.h>
Simon Glass274e0b02020-05-10 11:39:56 -060027#include <asm/cache.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060028#include <asm/global_data.h>
Michal Simek04b7e622015-01-15 10:01:51 +010029#include <asm/io.h>
Simon Glass6b9f0102020-05-10 11:40:06 -060030#include <asm/ptrace.h>
Michal Simekf183a982018-04-25 11:20:43 +020031#include <dm/device.h>
Michal Simekbf0f9ca2018-04-19 15:43:38 +020032#include <dm/uclass.h>
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +053033#include <usb.h>
34#include <dwc3-uboot.h>
Michal Simek8111aff2016-02-01 15:05:58 +010035#include <zynqmppl.h>
Ibai Erkiagac8a3efa2019-09-27 11:37:01 +010036#include <zynqmp_firmware.h>
Michal Simek76d0a772016-09-01 11:16:40 +020037#include <g_dnl.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060038#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060039#include <linux/delay.h>
40#include <linux/sizes.h>
Michal Simek705d44a2020-03-31 12:39:37 +020041#include "../common/board.h"
Michal Simek04b7e622015-01-15 10:01:51 +010042
Luca Ceresoli23e65002019-05-21 18:06:43 +020043#include "pm_cfg_obj.h"
44
Ibai Erkiaga4f736182020-08-04 23:17:31 +010045#define ZYNQMP_VERSION_SIZE 7
Michal Simekc702a742020-10-21 12:23:17 +020046#define EFUSE_VCU_DIS_MASK 0x100
47#define EFUSE_VCU_DIS_SHIFT 8
48#define EFUSE_GPU_DIS_MASK 0x20
49#define EFUSE_GPU_DIS_SHIFT 5
50#define IDCODE2_PL_INIT_MASK 0x200
51#define IDCODE2_PL_INIT_SHIFT 9
Ibai Erkiaga4f736182020-08-04 23:17:31 +010052
Michal Simek04b7e622015-01-15 10:01:51 +010053DECLARE_GLOBAL_DATA_PTR;
54
Michal Simek1aab1142020-09-09 14:41:56 +020055#if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
Michal Simek8111aff2016-02-01 15:05:58 +010056static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
57
Ibai Erkiaga4f736182020-08-04 23:17:31 +010058enum {
59 ZYNQMP_VARIANT_EG = BIT(0U),
60 ZYNQMP_VARIANT_EV = BIT(1U),
61 ZYNQMP_VARIANT_CG = BIT(2U),
62 ZYNQMP_VARIANT_DR = BIT(3U),
63};
64
Michal Simek8111aff2016-02-01 15:05:58 +010065static const struct {
Michal Simek6908b862017-11-06 12:55:59 +010066 u32 id;
Ibai Erkiaga4f736182020-08-04 23:17:31 +010067 u8 device;
68 u8 variants;
Michal Simek8111aff2016-02-01 15:05:58 +010069} zynqmp_devices[] = {
70 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010071 .id = 0x04711093,
72 .device = 2,
73 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
Michal Simek50d8cef2017-08-22 14:58:53 +020074 },
75 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010076 .id = 0x04710093,
77 .device = 3,
78 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
Michal Simek8111aff2016-02-01 15:05:58 +010079 },
80 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010081 .id = 0x04721093,
82 .device = 4,
83 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
84 ZYNQMP_VARIANT_EV,
Michal Simek50d8cef2017-08-22 14:58:53 +020085 },
86 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010087 .id = 0x04720093,
88 .device = 5,
89 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
90 ZYNQMP_VARIANT_EV,
Michal Simek50d8cef2017-08-22 14:58:53 +020091 },
92 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010093 .id = 0x04739093,
94 .device = 6,
95 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
Michal Simek8111aff2016-02-01 15:05:58 +010096 },
97 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +010098 .id = 0x04730093,
99 .device = 7,
100 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
101 ZYNQMP_VARIANT_EV,
Michal Simek50d8cef2017-08-22 14:58:53 +0200102 },
103 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100104 .id = 0x04738093,
105 .device = 9,
Michal Simek3626f2c2020-10-02 14:42:05 +0200106 .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
Michal Simek50d8cef2017-08-22 14:58:53 +0200107 },
108 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100109 .id = 0x04740093,
110 .device = 11,
111 .variants = ZYNQMP_VARIANT_EG,
Michal Simek8111aff2016-02-01 15:05:58 +0100112 },
113 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100114 .id = 0x04750093,
115 .device = 15,
116 .variants = ZYNQMP_VARIANT_EG,
Michal Simek50d8cef2017-08-22 14:58:53 +0200117 },
118 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100119 .id = 0x04759093,
120 .device = 17,
121 .variants = ZYNQMP_VARIANT_EG,
Michal Simek50d8cef2017-08-22 14:58:53 +0200122 },
123 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100124 .id = 0x04758093,
125 .device = 19,
126 .variants = ZYNQMP_VARIANT_EG,
Michal Simek8111aff2016-02-01 15:05:58 +0100127 },
128 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100129 .id = 0x047E1093,
130 .device = 21,
131 .variants = ZYNQMP_VARIANT_DR,
Michal Simek50d8cef2017-08-22 14:58:53 +0200132 },
133 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100134 .id = 0x047E3093,
135 .device = 23,
136 .variants = ZYNQMP_VARIANT_DR,
Michal Simek8111aff2016-02-01 15:05:58 +0100137 },
138 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100139 .id = 0x047E5093,
140 .device = 25,
141 .variants = ZYNQMP_VARIANT_DR,
Michal Simek50d8cef2017-08-22 14:58:53 +0200142 },
143 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100144 .id = 0x047E4093,
145 .device = 27,
146 .variants = ZYNQMP_VARIANT_DR,
Michal Simek8111aff2016-02-01 15:05:58 +0100147 },
148 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100149 .id = 0x047E0093,
150 .device = 28,
151 .variants = ZYNQMP_VARIANT_DR,
Michal Simek8111aff2016-02-01 15:05:58 +0100152 },
153 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100154 .id = 0x047E2093,
155 .device = 29,
156 .variants = ZYNQMP_VARIANT_DR,
Michal Simek8111aff2016-02-01 15:05:58 +0100157 },
Michal Simekb510e532017-06-02 08:08:59 +0200158 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100159 .id = 0x047E6093,
160 .device = 39,
161 .variants = ZYNQMP_VARIANT_DR,
Michal Simekb510e532017-06-02 08:08:59 +0200162 },
163 {
Michal Simek3fd2ed32020-09-11 09:22:15 +0200164 .id = 0x047FD093,
165 .device = 43,
166 .variants = ZYNQMP_VARIANT_DR,
Michal Simekb510e532017-06-02 08:08:59 +0200167 },
168 {
Michal Simek3fd2ed32020-09-11 09:22:15 +0200169 .id = 0x047F8093,
170 .device = 46,
171 .variants = ZYNQMP_VARIANT_DR,
Michal Simekb510e532017-06-02 08:08:59 +0200172 },
173 {
Michal Simek3fd2ed32020-09-11 09:22:15 +0200174 .id = 0x047FF093,
175 .device = 47,
176 .variants = ZYNQMP_VARIANT_DR,
Michal Simekb510e532017-06-02 08:08:59 +0200177 },
178 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100179 .id = 0x047FB093,
180 .device = 48,
181 .variants = ZYNQMP_VARIANT_DR,
Michal Simekb510e532017-06-02 08:08:59 +0200182 },
183 {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100184 .id = 0x047FE093,
185 .device = 49,
186 .variants = ZYNQMP_VARIANT_DR,
Siva Durga Prasad Paladugu85f61a82019-07-23 11:56:17 +0530187 },
T Karthik Reddy83df2cb2021-05-13 07:13:25 -0600188 {
189 .id = 0x046d0093,
190 .device = 67,
191 .variants = ZYNQMP_VARIANT_DR,
192 },
Michal Simek8111aff2016-02-01 15:05:58 +0100193};
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530194
Michal Simek005cac02020-10-05 09:35:40 +0200195static const struct {
196 u32 id;
197 char *name;
198} zynqmp_svd_devices[] = {
199 {
200 .id = 0x04714093,
201 .name = "xck24"
202 },
203 {
204 .id = 0x04724093,
205 .name = "xck26",
206 },
207};
208
209static char *zynqmp_detect_svd_name(u32 idcode)
210{
211 u32 i;
212
213 for (i = 0; i < ARRAY_SIZE(zynqmp_svd_devices); i++) {
214 if (zynqmp_svd_devices[i].id == (idcode & 0x0FFFFFFF))
215 return zynqmp_svd_devices[i].name;
216 }
217
218 return "unknown";
219}
220
Michal Simek8111aff2016-02-01 15:05:58 +0100221static char *zynqmp_get_silicon_idcode_name(void)
222{
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100223 u32 i;
224 u32 idcode, idcode2;
Michal Simek051b8bc2020-08-05 12:41:35 +0200225 char name[ZYNQMP_VERSION_SIZE];
Ibai Erkiagac318ecb2020-08-04 23:17:30 +0100226 u32 ret_payload[PAYLOAD_ARG_CNT];
Michal Simekb5c3b0d2020-10-07 15:13:17 +0200227 int ret;
Ibai Erkiagac318ecb2020-08-04 23:17:30 +0100228
Michal Simek23c0def2020-10-21 12:16:02 +0200229 ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
230 if (ret) {
231 debug("%s: Getting chipid failed\n", __func__);
232 return "unknown";
233 }
Ibai Erkiagac318ecb2020-08-04 23:17:30 +0100234
235 /*
236 * Firmware returns:
237 * payload[0][31:0] = status of the operation
238 * payload[1]] = IDCODE
239 * payload[2][19:0] = Version
240 * payload[2][28:20] = EXTENDED_IDCODE
241 * payload[2][29] = PL_INIT
242 */
243
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100244 idcode = ret_payload[1];
245 idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
Michal Simekc76c96f2020-10-21 12:16:50 +0200246 debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode,
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100247 idcode2);
Michal Simek50d8cef2017-08-22 14:58:53 +0200248
Michal Simek8111aff2016-02-01 15:05:58 +0100249 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100250 if (zynqmp_devices[i].id == (idcode & 0x0FFFFFFF))
251 break;
Michal Simek8111aff2016-02-01 15:05:58 +0100252 }
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530253
254 if (i >= ARRAY_SIZE(zynqmp_devices))
Michal Simek005cac02020-10-05 09:35:40 +0200255 return zynqmp_detect_svd_name(idcode);
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530256
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100257 /* Add device prefix to the name */
Michal Simekb5c3b0d2020-10-07 15:13:17 +0200258 ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d",
259 zynqmp_devices[i].device);
Michal Simekd2281672020-10-21 12:17:44 +0200260 if (ret < 0)
Michal Simekb5c3b0d2020-10-07 15:13:17 +0200261 return "unknown";
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530262
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100263 if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) {
264 /* Devices with EV variant might be EG/CG/EV family */
265 if (idcode2 & IDCODE2_PL_INIT_MASK) {
266 u32 family = ((idcode2 & EFUSE_VCU_DIS_MASK) >>
267 EFUSE_VCU_DIS_SHIFT) << 1 |
268 ((idcode2 & EFUSE_GPU_DIS_MASK) >>
269 EFUSE_GPU_DIS_SHIFT);
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530270
Ibai Erkiaga4f736182020-08-04 23:17:31 +0100271 /*
272 * Get family name based on extended idcode values as
273 * determined on UG1087, EXTENDED_IDCODE register
274 * description
275 */
276 switch (family) {
277 case 0x00:
278 strncat(name, "ev", 2);
279 break;
280 case 0x10:
281 strncat(name, "eg", 2);
282 break;
283 case 0x11:
284 strncat(name, "cg", 2);
285 break;
286 default:
287 /* Do not append family name*/
288 break;
289 }
290 } else {
291 /*
292 * When PL powered down the VCU Disable efuse cannot be
293 * read. So, ignore the bit and just findout if it is CG
294 * or EG/EV variant.
295 */
296 strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" :
297 "e", 2);
298 }
299 } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_CG) {
300 /* Devices with CG variant might be EG or CG family */
301 strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" : "eg", 2);
302 } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EG) {
303 strncat(name, "eg", 2);
304 } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_DR) {
305 strncat(name, "dr", 2);
306 } else {
307 debug("Variant not identified\n");
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530308 }
309
Michal Simek051b8bc2020-08-05 12:41:35 +0200310 return strdup(name);
Michal Simek8111aff2016-02-01 15:05:58 +0100311}
312#endif
313
Michal Simek8b353302017-02-07 14:32:26 +0100314int board_early_init_f(void)
315{
Michal Simek1a1ab5a2018-01-15 12:52:59 +0100316#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
Michal Simek09a7d7d2020-01-07 09:02:52 +0100317 int ret;
318
Michal Simekc8785f22018-01-10 11:48:48 +0100319 ret = psu_init();
Michal Simek09a7d7d2020-01-07 09:02:52 +0100320 if (ret)
321 return ret;
Michal Simek1f55e572020-03-20 08:59:02 +0100322
Adrian Fiergolski8e87ecf2021-06-08 12:37:23 +0200323 /*
324 * PS_SYSMON_ANALOG_BUS register determines mapping between SysMon
325 * supply sense channel to SysMon supply registers inside the IP.
326 * This register must be programmed to complete SysMon IP
327 * configuration. The default register configuration after
328 * power-up is incorrect. Hence, fix this by writing the
329 * correct value - 0x3210.
330 */
331 writel(ZYNQMP_PS_SYSMON_ANALOG_BUS_VAL,
332 ZYNQMP_AMS_PS_SYSMON_ANALOG_BUS);
333
Michal Simek1f55e572020-03-20 08:59:02 +0100334 /* Delay is required for clocks to be propagated */
335 udelay(1000000);
Michal Simeke0f36102017-07-12 13:08:41 +0200336#endif
337
Michal Simek09a7d7d2020-01-07 09:02:52 +0100338#ifdef CONFIG_DEBUG_UART
339 /* Uart debug for sure */
340 debug_uart_init();
341 puts("Debug uart enabled\n"); /* or printch() */
342#endif
343
344 return 0;
Michal Simek8b353302017-02-07 14:32:26 +0100345}
346
Michal Simek46900462020-02-11 12:43:14 +0100347static int multi_boot(void)
348{
349 u32 multiboot;
350
351 multiboot = readl(&csu_base->multi_boot);
352
Michal Simekc55f2d52020-05-27 12:50:33 +0200353 printf("Multiboot:\t%d\n", multiboot);
Michal Simek46900462020-02-11 12:43:14 +0100354
355 return 0;
356}
357
Mike Looijmans9863e2f2019-10-18 07:34:13 +0200358#define PS_SYSMON_ANALOG_BUS_VAL 0x3210
359#define PS_SYSMON_ANALOG_BUS_REG 0xFFA50914
360
Michal Simek04b7e622015-01-15 10:01:51 +0100361int board_init(void)
362{
Michal Simek826d7eca2020-03-04 08:48:16 +0100363#if defined(CONFIG_ZYNQMP_FIRMWARE)
Ibai Erkiaga2d9b95b2019-09-27 11:37:04 +0100364 struct udevice *dev;
365
366 uclass_get_device_by_name(UCLASS_FIRMWARE, "zynqmp-power", &dev);
367 if (!dev)
368 panic("PMU Firmware device not found - Enable it");
Michal Simek826d7eca2020-03-04 08:48:16 +0100369#endif
Ibai Erkiaga2d9b95b2019-09-27 11:37:04 +0100370
Luca Ceresoli23e65002019-05-21 18:06:43 +0200371#if defined(CONFIG_SPL_BUILD)
372 /* Check *at build time* if the filename is an non-empty string */
373 if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
374 zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
375 zynqmp_pm_cfg_obj_size);
Michal Simekae9dc112021-02-02 16:34:48 +0100376 printf("Silicon version:\t%d\n", zynqmp_get_silicon_version());
Michal Simek394ee242020-08-03 13:01:45 +0200377#else
378 if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
379 xilinx_read_eeprom();
Luca Ceresoli23e65002019-05-21 18:06:43 +0200380#endif
381
Michal Simekfb7242d2015-06-22 14:31:06 +0200382 printf("EL Level:\tEL%d\n", current_el());
383
Mike Looijmans9863e2f2019-10-18 07:34:13 +0200384 /* Bug in ROM sets wrong value in this register */
385 writel(PS_SYSMON_ANALOG_BUS_VAL, PS_SYSMON_ANALOG_BUS_REG);
386
Michal Simek1aab1142020-09-09 14:41:56 +0200387#if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
Ibai Erkiagae91ca7c2020-08-04 23:17:29 +0100388 zynqmppl.name = zynqmp_get_silicon_idcode_name();
389 printf("Chip ID:\t%s\n", zynqmppl.name);
390 fpga_init();
391 fpga_add(fpga_xilinx, &zynqmppl);
Michal Simekbf0f9ca2018-04-19 15:43:38 +0200392#endif
393
Michal Simek46900462020-02-11 12:43:14 +0100394 if (current_el() == 3)
395 multi_boot();
396
Michal Simek04b7e622015-01-15 10:01:51 +0100397 return 0;
398}
399
400int board_early_init_r(void)
401{
402 u32 val;
403
Siva Durga Prasad Paladugu64d90002017-12-07 15:05:30 +0530404 if (current_el() != 3)
405 return 0;
406
Michal Simek245d5282017-07-12 10:32:18 +0200407 val = readl(&crlapb_base->timestamp_ref_ctrl);
408 val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
409
Siva Durga Prasad Paladugu64d90002017-12-07 15:05:30 +0530410 if (!val) {
Michal Simekc23d3f82015-11-05 08:34:35 +0100411 val = readl(&crlapb_base->timestamp_ref_ctrl);
412 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
413 writel(val, &crlapb_base->timestamp_ref_ctrl);
Michal Simek04b7e622015-01-15 10:01:51 +0100414
Michal Simekc23d3f82015-11-05 08:34:35 +0100415 /* Program freq register in System counter */
416 writel(zynqmp_get_system_timer_freq(),
417 &iou_scntr_secure->base_frequency_id_register);
418 /* And enable system counter */
419 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
420 &iou_scntr_secure->counter_control_register);
421 }
Michal Simek04b7e622015-01-15 10:01:51 +0100422 return 0;
423}
424
Nitin Jainb2eb59b2018-02-16 12:56:17 +0530425unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
Simon Glassed38aef2020-05-10 11:40:03 -0600426 char *const argv[])
Nitin Jainb2eb59b2018-02-16 12:56:17 +0530427{
428 int ret = 0;
429
430 if (current_el() > 1) {
431 smp_kick_all_cpus();
432 dcache_disable();
433 armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
434 ES_TO_AARCH64);
435 } else {
436 printf("FAIL: current EL is not above EL1\n");
437 ret = EINVAL;
438 }
439 return ret;
440}
441
Michal Simek8faa66a2016-02-08 09:34:53 +0100442#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
Simon Glass2f949c32017-03-31 08:40:32 -0600443int dram_init_banksize(void)
Michal Simek8faa66a2016-02-08 09:34:53 +0100444{
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530445 int ret;
446
447 ret = fdtdec_setup_memory_banksize();
448 if (ret)
449 return ret;
450
451 mem_map_fill();
452
453 return 0;
Tom Riniedcfdbd2016-12-09 07:56:54 -0500454}
Michal Simek8faa66a2016-02-08 09:34:53 +0100455
Tom Riniedcfdbd2016-12-09 07:56:54 -0500456int dram_init(void)
457{
Siva Durga Prasad Paladugub3d55ea2018-07-16 15:56:11 +0530458 if (fdtdec_setup_mem_size_base() != 0)
Nathan Rossiac04bfa2016-12-19 00:03:34 +1000459 return -EINVAL;
Tom Riniedcfdbd2016-12-09 07:56:54 -0500460
461 return 0;
Michal Simek8faa66a2016-02-08 09:34:53 +0100462}
Michal Simek97ab9612021-05-31 11:03:19 +0200463
464ulong board_get_usable_ram_top(ulong total_size)
465{
466 phys_size_t size;
467 phys_addr_t reg;
468 struct lmb lmb;
469
470 /* found enough not-reserved memory to relocated U-Boot */
471 lmb_init(&lmb);
472 lmb_add(&lmb, gd->ram_base, gd->ram_size);
473 boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
474 size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE),
475 reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
476
477 if (!reg)
478 reg = gd->ram_top - size;
479
480 return reg + size;
481}
Michal Simek8faa66a2016-02-08 09:34:53 +0100482#else
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530483int dram_init_banksize(void)
484{
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530485 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
486 gd->bd->bi_dram[0].size = get_effective_memsize();
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530487
488 mem_map_fill();
489
490 return 0;
491}
492
Michal Simek04b7e622015-01-15 10:01:51 +0100493int dram_init(void)
494{
Michal Simek1b846212018-04-11 16:12:28 +0200495 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
496 CONFIG_SYS_SDRAM_SIZE);
Michal Simek04b7e622015-01-15 10:01:51 +0100497
498 return 0;
499}
Michal Simek8faa66a2016-02-08 09:34:53 +0100500#endif
Michal Simek04b7e622015-01-15 10:01:51 +0100501
Harald Seiler6f14d5f2020-12-15 16:47:52 +0100502void reset_cpu(void)
Michal Simek04b7e622015-01-15 10:01:51 +0100503{
504}
505
Michal Simek8ec30042020-08-20 10:54:45 +0200506static u8 __maybe_unused zynqmp_get_bootmode(void)
507{
508 u8 bootmode;
509 u32 reg = 0;
510 int ret;
511
512 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
513 if (ret)
514 return -EINVAL;
515
516 if (reg >> BOOT_MODE_ALT_SHIFT)
517 reg >>= BOOT_MODE_ALT_SHIFT;
518
519 bootmode = reg & BOOT_MODES_MASK;
520
521 return bootmode;
522}
523
Michal Simek342edfe2018-12-20 09:33:38 +0100524#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simek29b9b712018-05-17 14:06:06 +0200525static const struct {
526 u32 bit;
527 const char *name;
528} reset_reasons[] = {
529 { RESET_REASON_DEBUG_SYS, "DEBUG" },
530 { RESET_REASON_SOFT, "SOFT" },
531 { RESET_REASON_SRST, "SRST" },
532 { RESET_REASON_PSONLY, "PS-ONLY" },
533 { RESET_REASON_PMU, "PMU" },
534 { RESET_REASON_INTERNAL, "INTERNAL" },
535 { RESET_REASON_EXTERNAL, "EXTERNAL" },
536 {}
537};
538
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530539static int reset_reason(void)
Michal Simek29b9b712018-05-17 14:06:06 +0200540{
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530541 u32 reg;
542 int i, ret;
Michal Simek29b9b712018-05-17 14:06:06 +0200543 const char *reason = NULL;
544
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530545 ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, &reg);
546 if (ret)
547 return -EINVAL;
Michal Simek29b9b712018-05-17 14:06:06 +0200548
549 puts("Reset reason:\t");
550
551 for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530552 if (reg & reset_reasons[i].bit) {
Michal Simek29b9b712018-05-17 14:06:06 +0200553 reason = reset_reasons[i].name;
554 printf("%s ", reset_reasons[i].name);
555 break;
556 }
557 }
558
559 puts("\n");
560
561 env_set("reset_reason", reason);
562
Michal Simek0954c8c2021-02-09 08:50:22 +0100563 return 0;
Michal Simek29b9b712018-05-17 14:06:06 +0200564}
565
Michal Simek1ca66d72019-02-14 13:14:30 +0100566static int set_fdtfile(void)
567{
568 char *compatible, *fdtfile;
569 const char *suffix = ".dtb";
570 const char *vendor = "xilinx/";
Igor Lantsmane167bac2020-06-24 14:33:46 +0200571 int fdt_compat_len;
Michal Simek1ca66d72019-02-14 13:14:30 +0100572
573 if (env_get("fdtfile"))
574 return 0;
575
Igor Lantsmane167bac2020-06-24 14:33:46 +0200576 compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible",
577 &fdt_compat_len);
578 if (compatible && fdt_compat_len) {
579 char *name;
580
Michal Simek1ca66d72019-02-14 13:14:30 +0100581 debug("Compatible: %s\n", compatible);
582
Igor Lantsmane167bac2020-06-24 14:33:46 +0200583 name = strchr(compatible, ',');
584 if (!name)
585 return -EINVAL;
Michal Simek1ca66d72019-02-14 13:14:30 +0100586
Igor Lantsmane167bac2020-06-24 14:33:46 +0200587 name++;
588
589 fdtfile = calloc(1, strlen(vendor) + strlen(name) +
Michal Simek1ca66d72019-02-14 13:14:30 +0100590 strlen(suffix) + 1);
591 if (!fdtfile)
592 return -ENOMEM;
593
Igor Lantsmane167bac2020-06-24 14:33:46 +0200594 sprintf(fdtfile, "%s%s%s", vendor, name, suffix);
Michal Simek1ca66d72019-02-14 13:14:30 +0100595
596 env_set("fdtfile", fdtfile);
597 free(fdtfile);
598 }
599
600 return 0;
601}
602
Michal Simek9c91e612020-04-08 11:04:41 +0200603int board_late_init(void)
604{
Michal Simek04b7e622015-01-15 10:01:51 +0100605 u8 bootmode;
Michal Simekf183a982018-04-25 11:20:43 +0200606 struct udevice *dev;
607 int bootseq = -1;
608 int bootseq_len = 0;
Michal Simek7410b142018-04-25 11:10:34 +0200609 int env_targets_len = 0;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200610 const char *mode;
611 char *new_targets;
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530612 char *env_targets;
Siva Durga Prasad Paladugue6fd3bb2017-02-21 17:58:28 +0530613 int ret;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200614
Michal Simek482f5492018-10-05 08:55:16 +0200615#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
616 usb_ether_init();
617#endif
618
Michal Simekecfb6dc2016-04-22 14:28:54 +0200619 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
620 debug("Saved variables - Skipping\n");
621 return 0;
622 }
Michal Simek04b7e622015-01-15 10:01:51 +0100623
Michal Simekbab07b62020-07-28 12:45:47 +0200624 if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG))
625 return 0;
626
Michal Simek1ca66d72019-02-14 13:14:30 +0100627 ret = set_fdtfile();
628 if (ret)
629 return ret;
630
Michal Simek9c91e612020-04-08 11:04:41 +0200631 bootmode = zynqmp_get_bootmode();
Michal Simek04b7e622015-01-15 10:01:51 +0100632
Michal Simekc5d95232015-09-20 17:20:42 +0200633 puts("Bootmode: ");
Michal Simek04b7e622015-01-15 10:01:51 +0100634 switch (bootmode) {
Michal Simek12398ea2016-08-19 14:14:52 +0200635 case USB_MODE:
636 puts("USB_MODE\n");
T Karthik Reddy9eee8e32021-03-24 23:37:57 -0600637 mode = "usb_dfu0 usb_dfu1";
Michal Simek43380352017-12-01 15:18:24 +0100638 env_set("modeboot", "usb_dfu_spl");
Michal Simek12398ea2016-08-19 14:14:52 +0200639 break;
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530640 case JTAG_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200641 puts("JTAG_MODE\n");
Siva Durga Prasad Paladugu9c441702019-06-25 17:41:09 +0530642 mode = "jtag pxe dhcp";
Michal Simek43380352017-12-01 15:18:24 +0100643 env_set("modeboot", "jtagboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530644 break;
645 case QSPI_MODE_24BIT:
646 case QSPI_MODE_32BIT:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200647 mode = "qspi0";
Michal Simekc5d95232015-09-20 17:20:42 +0200648 puts("QSPI_MODE\n");
Michal Simek43380352017-12-01 15:18:24 +0100649 env_set("modeboot", "qspiboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530650 break;
Michal Simek02d66cd2015-04-15 15:02:28 +0200651 case EMMC_MODE:
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200652 puts("EMMC_MODE\n");
T Karthik Reddy19735c32019-12-17 06:41:42 -0700653 if (uclass_get_device_by_name(UCLASS_MMC,
654 "mmc@ff160000", &dev) &&
655 uclass_get_device_by_name(UCLASS_MMC,
656 "sdhci@ff160000", &dev)) {
657 puts("Boot from EMMC but without SD0 enabled!\n");
658 return -1;
659 }
Simon Glass75e534b2020-12-16 21:20:07 -0700660 debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev));
T Karthik Reddy19735c32019-12-17 06:41:42 -0700661
662 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700663 bootseq = dev_seq(dev);
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200664 break;
665 case SD_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200666 puts("SD_MODE\n");
Michal Simekf183a982018-04-25 11:20:43 +0200667 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530668 "mmc@ff160000", &dev) &&
669 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200670 "sdhci@ff160000", &dev)) {
671 puts("Boot from SD0 but without SD0 enabled!\n");
672 return -1;
673 }
Simon Glass75e534b2020-12-16 21:20:07 -0700674 debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev));
Michal Simekf183a982018-04-25 11:20:43 +0200675
676 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700677 bootseq = dev_seq(dev);
Michal Simek43380352017-12-01 15:18:24 +0100678 env_set("modeboot", "sdboot");
Michal Simek04b7e622015-01-15 10:01:51 +0100679 break;
Siva Durga Prasad Paladugu29a77d22016-09-21 11:45:05 +0530680 case SD1_LSHFT_MODE:
681 puts("LVL_SHFT_");
682 /* fall through */
Michal Simek108e1842015-10-05 10:51:12 +0200683 case SD_MODE1:
Michal Simekc5d95232015-09-20 17:20:42 +0200684 puts("SD_MODE1\n");
Michal Simekf183a982018-04-25 11:20:43 +0200685 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530686 "mmc@ff170000", &dev) &&
687 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200688 "sdhci@ff170000", &dev)) {
689 puts("Boot from SD1 but without SD1 enabled!\n");
690 return -1;
691 }
Simon Glass75e534b2020-12-16 21:20:07 -0700692 debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev));
Michal Simekf183a982018-04-25 11:20:43 +0200693
694 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700695 bootseq = dev_seq(dev);
Michal Simek43380352017-12-01 15:18:24 +0100696 env_set("modeboot", "sdboot");
Michal Simek108e1842015-10-05 10:51:12 +0200697 break;
698 case NAND_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200699 puts("NAND_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200700 mode = "nand0";
Michal Simek43380352017-12-01 15:18:24 +0100701 env_set("modeboot", "nandboot");
Michal Simek108e1842015-10-05 10:51:12 +0200702 break;
Michal Simek04b7e622015-01-15 10:01:51 +0100703 default:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200704 mode = "";
Michal Simek04b7e622015-01-15 10:01:51 +0100705 printf("Invalid Boot Mode:0x%x\n", bootmode);
706 break;
707 }
708
Michal Simekf183a982018-04-25 11:20:43 +0200709 if (bootseq >= 0) {
710 bootseq_len = snprintf(NULL, 0, "%i", bootseq);
711 debug("Bootseq len: %x\n", bootseq_len);
Michal Simek7a117c72021-01-11 13:46:58 +0100712 env_set_hex("bootseq", bootseq);
Michal Simekf183a982018-04-25 11:20:43 +0200713 }
714
Michal Simekecfb6dc2016-04-22 14:28:54 +0200715 /*
716 * One terminating char + one byte for space between mode
717 * and default boot_targets
718 */
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530719 env_targets = env_get("boot_targets");
Michal Simek7410b142018-04-25 11:10:34 +0200720 if (env_targets)
721 env_targets_len = strlen(env_targets);
722
Michal Simekf183a982018-04-25 11:20:43 +0200723 new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
724 bootseq_len);
Michal Simek089b84d2018-06-13 09:42:41 +0200725 if (!new_targets)
726 return -ENOMEM;
Michal Simek7410b142018-04-25 11:10:34 +0200727
Michal Simekf183a982018-04-25 11:20:43 +0200728 if (bootseq >= 0)
729 sprintf(new_targets, "%s%x %s", mode, bootseq,
730 env_targets ? env_targets : "");
731 else
732 sprintf(new_targets, "%s %s", mode,
733 env_targets ? env_targets : "");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200734
Simon Glass6a38e412017-08-03 12:22:09 -0600735 env_set("boot_targets", new_targets);
Michal Simekecfb6dc2016-04-22 14:28:54 +0200736
Michal Simek29b9b712018-05-17 14:06:06 +0200737 reset_reason();
738
Michal Simek705d44a2020-03-31 12:39:37 +0200739 return board_late_init_xilinx();
Michal Simek04b7e622015-01-15 10:01:51 +0100740}
Michal Simek342edfe2018-12-20 09:33:38 +0100741#endif
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530742
743int checkboard(void)
744{
Michal Simek47ce9362016-01-25 11:04:21 +0100745 puts("Board: Xilinx ZynqMP\n");
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530746 return 0;
747}
Michal Simek8d4a8d42020-07-30 13:37:49 +0200748
Michal Simeke0026bf2021-05-19 15:16:19 +0200749int mmc_get_env_dev(void)
750{
751 struct udevice *dev;
752 int bootseq = 0;
753
754 switch (zynqmp_get_bootmode()) {
755 case EMMC_MODE:
756 case SD_MODE:
757 if (uclass_get_device_by_name(UCLASS_MMC,
758 "mmc@ff160000", &dev) &&
759 uclass_get_device_by_name(UCLASS_MMC,
760 "sdhci@ff160000", &dev)) {
761 return -1;
762 }
763 bootseq = dev_seq(dev);
764 break;
765 case SD1_LSHFT_MODE:
766 case SD_MODE1:
767 if (uclass_get_device_by_name(UCLASS_MMC,
768 "mmc@ff170000", &dev) &&
769 uclass_get_device_by_name(UCLASS_MMC,
770 "sdhci@ff170000", &dev)) {
771 return -1;
772 }
773 bootseq = dev_seq(dev);
774 break;
775 default:
776 break;
777 }
778
779 debug("bootseq %d\n", bootseq);
780
781 return bootseq;
782}
783
Michal Simek8d4a8d42020-07-30 13:37:49 +0200784enum env_location env_get_location(enum env_operation op, int prio)
785{
786 u32 bootmode = zynqmp_get_bootmode();
787
788 if (prio)
789 return ENVL_UNKNOWN;
790
791 switch (bootmode) {
792 case EMMC_MODE:
793 case SD_MODE:
794 case SD1_LSHFT_MODE:
795 case SD_MODE1:
796 if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
797 return ENVL_FAT;
798 if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
799 return ENVL_EXT4;
800 return ENVL_UNKNOWN;
801 case NAND_MODE:
802 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
803 return ENVL_NAND;
804 if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
805 return ENVL_UBI;
806 return ENVL_UNKNOWN;
807 case QSPI_MODE_24BIT:
808 case QSPI_MODE_32BIT:
809 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
810 return ENVL_SPI_FLASH;
811 return ENVL_UNKNOWN;
812 case JTAG_MODE:
813 default:
814 return ENVL_NOWHERE;
815 }
816}