blob: 38c910fa5bab458f51ff76a1b785679c06b7ba8d [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
Michal Simek2a220332021-07-13 16:39:26 +0200502#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +0100503void reset_cpu(void)
Michal Simek04b7e622015-01-15 10:01:51 +0100504{
505}
Michal Simek2a220332021-07-13 16:39:26 +0200506#endif
Michal Simek04b7e622015-01-15 10:01:51 +0100507
Michal Simek8ec30042020-08-20 10:54:45 +0200508static u8 __maybe_unused zynqmp_get_bootmode(void)
509{
510 u8 bootmode;
511 u32 reg = 0;
512 int ret;
513
514 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
515 if (ret)
516 return -EINVAL;
517
518 if (reg >> BOOT_MODE_ALT_SHIFT)
519 reg >>= BOOT_MODE_ALT_SHIFT;
520
521 bootmode = reg & BOOT_MODES_MASK;
522
523 return bootmode;
524}
525
Michal Simek342edfe2018-12-20 09:33:38 +0100526#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simek29b9b712018-05-17 14:06:06 +0200527static const struct {
528 u32 bit;
529 const char *name;
530} reset_reasons[] = {
531 { RESET_REASON_DEBUG_SYS, "DEBUG" },
532 { RESET_REASON_SOFT, "SOFT" },
533 { RESET_REASON_SRST, "SRST" },
534 { RESET_REASON_PSONLY, "PS-ONLY" },
535 { RESET_REASON_PMU, "PMU" },
536 { RESET_REASON_INTERNAL, "INTERNAL" },
537 { RESET_REASON_EXTERNAL, "EXTERNAL" },
538 {}
539};
540
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530541static int reset_reason(void)
Michal Simek29b9b712018-05-17 14:06:06 +0200542{
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530543 u32 reg;
544 int i, ret;
Michal Simek29b9b712018-05-17 14:06:06 +0200545 const char *reason = NULL;
546
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530547 ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, &reg);
548 if (ret)
549 return -EINVAL;
Michal Simek29b9b712018-05-17 14:06:06 +0200550
551 puts("Reset reason:\t");
552
553 for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530554 if (reg & reset_reasons[i].bit) {
Michal Simek29b9b712018-05-17 14:06:06 +0200555 reason = reset_reasons[i].name;
556 printf("%s ", reset_reasons[i].name);
557 break;
558 }
559 }
560
561 puts("\n");
562
563 env_set("reset_reason", reason);
564
Michal Simek0954c8c2021-02-09 08:50:22 +0100565 return 0;
Michal Simek29b9b712018-05-17 14:06:06 +0200566}
567
Michal Simek1ca66d72019-02-14 13:14:30 +0100568static int set_fdtfile(void)
569{
570 char *compatible, *fdtfile;
571 const char *suffix = ".dtb";
572 const char *vendor = "xilinx/";
Igor Lantsmane167bac2020-06-24 14:33:46 +0200573 int fdt_compat_len;
Michal Simek1ca66d72019-02-14 13:14:30 +0100574
575 if (env_get("fdtfile"))
576 return 0;
577
Igor Lantsmane167bac2020-06-24 14:33:46 +0200578 compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible",
579 &fdt_compat_len);
580 if (compatible && fdt_compat_len) {
581 char *name;
582
Michal Simek1ca66d72019-02-14 13:14:30 +0100583 debug("Compatible: %s\n", compatible);
584
Igor Lantsmane167bac2020-06-24 14:33:46 +0200585 name = strchr(compatible, ',');
586 if (!name)
587 return -EINVAL;
Michal Simek1ca66d72019-02-14 13:14:30 +0100588
Igor Lantsmane167bac2020-06-24 14:33:46 +0200589 name++;
590
591 fdtfile = calloc(1, strlen(vendor) + strlen(name) +
Michal Simek1ca66d72019-02-14 13:14:30 +0100592 strlen(suffix) + 1);
593 if (!fdtfile)
594 return -ENOMEM;
595
Igor Lantsmane167bac2020-06-24 14:33:46 +0200596 sprintf(fdtfile, "%s%s%s", vendor, name, suffix);
Michal Simek1ca66d72019-02-14 13:14:30 +0100597
598 env_set("fdtfile", fdtfile);
599 free(fdtfile);
600 }
601
602 return 0;
603}
604
Michal Simek9c91e612020-04-08 11:04:41 +0200605int board_late_init(void)
606{
Michal Simek04b7e622015-01-15 10:01:51 +0100607 u8 bootmode;
Michal Simekf183a982018-04-25 11:20:43 +0200608 struct udevice *dev;
609 int bootseq = -1;
610 int bootseq_len = 0;
Michal Simek7410b142018-04-25 11:10:34 +0200611 int env_targets_len = 0;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200612 const char *mode;
613 char *new_targets;
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530614 char *env_targets;
Siva Durga Prasad Paladugue6fd3bb2017-02-21 17:58:28 +0530615 int ret;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200616
Michal Simek482f5492018-10-05 08:55:16 +0200617#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
618 usb_ether_init();
619#endif
620
Michal Simekecfb6dc2016-04-22 14:28:54 +0200621 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
622 debug("Saved variables - Skipping\n");
623 return 0;
624 }
Michal Simek04b7e622015-01-15 10:01:51 +0100625
Michal Simekbab07b62020-07-28 12:45:47 +0200626 if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG))
627 return 0;
628
Michal Simek1ca66d72019-02-14 13:14:30 +0100629 ret = set_fdtfile();
630 if (ret)
631 return ret;
632
Michal Simek9c91e612020-04-08 11:04:41 +0200633 bootmode = zynqmp_get_bootmode();
Michal Simek04b7e622015-01-15 10:01:51 +0100634
Michal Simekc5d95232015-09-20 17:20:42 +0200635 puts("Bootmode: ");
Michal Simek04b7e622015-01-15 10:01:51 +0100636 switch (bootmode) {
Michal Simek12398ea2016-08-19 14:14:52 +0200637 case USB_MODE:
638 puts("USB_MODE\n");
T Karthik Reddy9eee8e32021-03-24 23:37:57 -0600639 mode = "usb_dfu0 usb_dfu1";
Michal Simek43380352017-12-01 15:18:24 +0100640 env_set("modeboot", "usb_dfu_spl");
Michal Simek12398ea2016-08-19 14:14:52 +0200641 break;
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530642 case JTAG_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200643 puts("JTAG_MODE\n");
Siva Durga Prasad Paladugu9c441702019-06-25 17:41:09 +0530644 mode = "jtag pxe dhcp";
Michal Simek43380352017-12-01 15:18:24 +0100645 env_set("modeboot", "jtagboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530646 break;
647 case QSPI_MODE_24BIT:
648 case QSPI_MODE_32BIT:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200649 mode = "qspi0";
Michal Simekc5d95232015-09-20 17:20:42 +0200650 puts("QSPI_MODE\n");
Michal Simek43380352017-12-01 15:18:24 +0100651 env_set("modeboot", "qspiboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530652 break;
Michal Simek02d66cd2015-04-15 15:02:28 +0200653 case EMMC_MODE:
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200654 puts("EMMC_MODE\n");
T Karthik Reddy19735c32019-12-17 06:41:42 -0700655 if (uclass_get_device_by_name(UCLASS_MMC,
656 "mmc@ff160000", &dev) &&
657 uclass_get_device_by_name(UCLASS_MMC,
658 "sdhci@ff160000", &dev)) {
659 puts("Boot from EMMC but without SD0 enabled!\n");
660 return -1;
661 }
Simon Glass75e534b2020-12-16 21:20:07 -0700662 debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev));
T Karthik Reddy19735c32019-12-17 06:41:42 -0700663
664 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700665 bootseq = dev_seq(dev);
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200666 break;
667 case SD_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200668 puts("SD_MODE\n");
Michal Simekf183a982018-04-25 11:20:43 +0200669 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530670 "mmc@ff160000", &dev) &&
671 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200672 "sdhci@ff160000", &dev)) {
673 puts("Boot from SD0 but without SD0 enabled!\n");
674 return -1;
675 }
Simon Glass75e534b2020-12-16 21:20:07 -0700676 debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev));
Michal Simekf183a982018-04-25 11:20:43 +0200677
678 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700679 bootseq = dev_seq(dev);
Michal Simek43380352017-12-01 15:18:24 +0100680 env_set("modeboot", "sdboot");
Michal Simek04b7e622015-01-15 10:01:51 +0100681 break;
Siva Durga Prasad Paladugu29a77d22016-09-21 11:45:05 +0530682 case SD1_LSHFT_MODE:
683 puts("LVL_SHFT_");
684 /* fall through */
Michal Simek108e1842015-10-05 10:51:12 +0200685 case SD_MODE1:
Michal Simekc5d95232015-09-20 17:20:42 +0200686 puts("SD_MODE1\n");
Michal Simekf183a982018-04-25 11:20:43 +0200687 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530688 "mmc@ff170000", &dev) &&
689 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200690 "sdhci@ff170000", &dev)) {
691 puts("Boot from SD1 but without SD1 enabled!\n");
692 return -1;
693 }
Simon Glass75e534b2020-12-16 21:20:07 -0700694 debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev));
Michal Simekf183a982018-04-25 11:20:43 +0200695
696 mode = "mmc";
Simon Glass75e534b2020-12-16 21:20:07 -0700697 bootseq = dev_seq(dev);
Michal Simek43380352017-12-01 15:18:24 +0100698 env_set("modeboot", "sdboot");
Michal Simek108e1842015-10-05 10:51:12 +0200699 break;
700 case NAND_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200701 puts("NAND_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200702 mode = "nand0";
Michal Simek43380352017-12-01 15:18:24 +0100703 env_set("modeboot", "nandboot");
Michal Simek108e1842015-10-05 10:51:12 +0200704 break;
Michal Simek04b7e622015-01-15 10:01:51 +0100705 default:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200706 mode = "";
Michal Simek04b7e622015-01-15 10:01:51 +0100707 printf("Invalid Boot Mode:0x%x\n", bootmode);
708 break;
709 }
710
Michal Simekf183a982018-04-25 11:20:43 +0200711 if (bootseq >= 0) {
712 bootseq_len = snprintf(NULL, 0, "%i", bootseq);
713 debug("Bootseq len: %x\n", bootseq_len);
Michal Simek7a117c72021-01-11 13:46:58 +0100714 env_set_hex("bootseq", bootseq);
Michal Simekf183a982018-04-25 11:20:43 +0200715 }
716
Michal Simekecfb6dc2016-04-22 14:28:54 +0200717 /*
718 * One terminating char + one byte for space between mode
719 * and default boot_targets
720 */
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530721 env_targets = env_get("boot_targets");
Michal Simek7410b142018-04-25 11:10:34 +0200722 if (env_targets)
723 env_targets_len = strlen(env_targets);
724
Michal Simekf183a982018-04-25 11:20:43 +0200725 new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
726 bootseq_len);
Michal Simek089b84d2018-06-13 09:42:41 +0200727 if (!new_targets)
728 return -ENOMEM;
Michal Simek7410b142018-04-25 11:10:34 +0200729
Michal Simekf183a982018-04-25 11:20:43 +0200730 if (bootseq >= 0)
731 sprintf(new_targets, "%s%x %s", mode, bootseq,
732 env_targets ? env_targets : "");
733 else
734 sprintf(new_targets, "%s %s", mode,
735 env_targets ? env_targets : "");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200736
Simon Glass6a38e412017-08-03 12:22:09 -0600737 env_set("boot_targets", new_targets);
Michal Simekecfb6dc2016-04-22 14:28:54 +0200738
Michal Simek29b9b712018-05-17 14:06:06 +0200739 reset_reason();
740
Michal Simek705d44a2020-03-31 12:39:37 +0200741 return board_late_init_xilinx();
Michal Simek04b7e622015-01-15 10:01:51 +0100742}
Michal Simek342edfe2018-12-20 09:33:38 +0100743#endif
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530744
745int checkboard(void)
746{
Michal Simek47ce9362016-01-25 11:04:21 +0100747 puts("Board: Xilinx ZynqMP\n");
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530748 return 0;
749}
Michal Simek8d4a8d42020-07-30 13:37:49 +0200750
Michal Simeke0026bf2021-05-19 15:16:19 +0200751int mmc_get_env_dev(void)
752{
753 struct udevice *dev;
754 int bootseq = 0;
755
756 switch (zynqmp_get_bootmode()) {
757 case EMMC_MODE:
758 case SD_MODE:
759 if (uclass_get_device_by_name(UCLASS_MMC,
760 "mmc@ff160000", &dev) &&
761 uclass_get_device_by_name(UCLASS_MMC,
762 "sdhci@ff160000", &dev)) {
763 return -1;
764 }
765 bootseq = dev_seq(dev);
766 break;
767 case SD1_LSHFT_MODE:
768 case SD_MODE1:
769 if (uclass_get_device_by_name(UCLASS_MMC,
770 "mmc@ff170000", &dev) &&
771 uclass_get_device_by_name(UCLASS_MMC,
772 "sdhci@ff170000", &dev)) {
773 return -1;
774 }
775 bootseq = dev_seq(dev);
776 break;
777 default:
778 break;
779 }
780
781 debug("bootseq %d\n", bootseq);
782
783 return bootseq;
784}
785
Michal Simek8d4a8d42020-07-30 13:37:49 +0200786enum env_location env_get_location(enum env_operation op, int prio)
787{
788 u32 bootmode = zynqmp_get_bootmode();
789
790 if (prio)
791 return ENVL_UNKNOWN;
792
793 switch (bootmode) {
794 case EMMC_MODE:
795 case SD_MODE:
796 case SD1_LSHFT_MODE:
797 case SD_MODE1:
798 if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
799 return ENVL_FAT;
800 if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
801 return ENVL_EXT4;
Mike Looijmans682cf082021-07-02 10:28:36 +0200802 return ENVL_NOWHERE;
Michal Simek8d4a8d42020-07-30 13:37:49 +0200803 case NAND_MODE:
804 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
805 return ENVL_NAND;
806 if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
807 return ENVL_UBI;
Mike Looijmans682cf082021-07-02 10:28:36 +0200808 return ENVL_NOWHERE;
Michal Simek8d4a8d42020-07-30 13:37:49 +0200809 case QSPI_MODE_24BIT:
810 case QSPI_MODE_32BIT:
811 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
812 return ENVL_SPI_FLASH;
Mike Looijmans682cf082021-07-02 10:28:36 +0200813 return ENVL_NOWHERE;
Michal Simek8d4a8d42020-07-30 13:37:49 +0200814 case JTAG_MODE:
815 default:
816 return ENVL_NOWHERE;
817 }
818}