blob: e880db1f8131387b4bd674dddf60acf756989545 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek84c72042015-01-15 10:01:51 +01002/*
3 * (C) Copyright 2014 - 2015 Xilinx, Inc.
4 * Michal Simek <michal.simek@xilinx.com>
Michal Simek84c72042015-01-15 10:01:51 +01005 */
6
7#include <common.h>
Simon Glass09140112020-05-10 11:40:03 -06008#include <command.h>
Simon Glass62270f42019-11-14 12:57:35 -07009#include <cpu_func.h>
Michal Simekc0adba52020-01-07 09:02:52 +010010#include <debug_uart.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060011#include <env.h>
Simon Glass52559322019-11-14 12:57:46 -070012#include <init.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060013#include <log.h>
Simon Glass90526e92020-05-10 11:39:56 -060014#include <net.h>
Michal Simek679b9942015-09-30 17:26:55 +020015#include <sata.h>
Michal Simek6fe6f132015-07-23 13:27:40 +020016#include <ahci.h>
17#include <scsi.h>
Michal Simekb72894f2016-04-22 14:28:54 +020018#include <malloc.h>
Michal Simek4490e012018-04-19 15:43:38 +020019#include <wdt.h>
Michal Simek0785dfd2015-11-05 08:34:35 +010020#include <asm/arch/clk.h>
Michal Simek84c72042015-01-15 10:01:51 +010021#include <asm/arch/hardware.h>
22#include <asm/arch/sys_proto.h>
Michal Simek2ad341e2018-01-10 09:36:09 +010023#include <asm/arch/psu_init_gpl.h>
Simon Glass90526e92020-05-10 11:39:56 -060024#include <asm/cache.h>
Michal Simek84c72042015-01-15 10:01:51 +010025#include <asm/io.h>
Michal Simek2882b392018-04-25 11:20:43 +020026#include <dm/device.h>
Michal Simek4490e012018-04-19 15:43:38 +020027#include <dm/uclass.h>
Siva Durga Prasad Paladugu16fa00a2015-08-04 13:03:26 +053028#include <usb.h>
29#include <dwc3-uboot.h>
Michal Simek47e60cb2016-02-01 15:05:58 +010030#include <zynqmppl.h>
Ibai Erkiaga009ab7b2019-09-27 11:37:01 +010031#include <zynqmp_firmware.h>
Michal Simek9feff382016-09-01 11:16:40 +020032#include <g_dnl.h>
Michal Simek80fdef12020-03-31 12:39:37 +020033#include "../common/board.h"
Michal Simek84c72042015-01-15 10:01:51 +010034
Luca Ceresolic28a9cf2019-05-21 18:06:43 +020035#include "pm_cfg_obj.h"
36
Michal Simek84c72042015-01-15 10:01:51 +010037DECLARE_GLOBAL_DATA_PTR;
38
Michal Simek47e60cb2016-02-01 15:05:58 +010039#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
40 !defined(CONFIG_SPL_BUILD)
41static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
42
43static const struct {
Michal Simek8ebdf9e2017-11-06 12:55:59 +010044 u32 id;
Michal Simek494fffe2017-08-22 14:58:53 +020045 u32 ver;
Michal Simek47e60cb2016-02-01 15:05:58 +010046 char *name;
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +053047 bool evexists;
Michal Simek47e60cb2016-02-01 15:05:58 +010048} zynqmp_devices[] = {
49 {
50 .id = 0x10,
51 .name = "3eg",
52 },
53 {
Michal Simek494fffe2017-08-22 14:58:53 +020054 .id = 0x10,
55 .ver = 0x2c,
56 .name = "3cg",
57 },
58 {
Michal Simek47e60cb2016-02-01 15:05:58 +010059 .id = 0x11,
60 .name = "2eg",
61 },
62 {
Michal Simek494fffe2017-08-22 14:58:53 +020063 .id = 0x11,
64 .ver = 0x2c,
65 .name = "2cg",
66 },
67 {
Michal Simek47e60cb2016-02-01 15:05:58 +010068 .id = 0x20,
69 .name = "5ev",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +053070 .evexists = 1,
Michal Simek47e60cb2016-02-01 15:05:58 +010071 },
72 {
Michal Simek494fffe2017-08-22 14:58:53 +020073 .id = 0x20,
74 .ver = 0x100,
75 .name = "5eg",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +053076 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +020077 },
78 {
79 .id = 0x20,
80 .ver = 0x12c,
81 .name = "5cg",
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +053082 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +020083 },
84 {
Michal Simek47e60cb2016-02-01 15:05:58 +010085 .id = 0x21,
86 .name = "4ev",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +053087 .evexists = 1,
Michal Simek47e60cb2016-02-01 15:05:58 +010088 },
89 {
Michal Simek494fffe2017-08-22 14:58:53 +020090 .id = 0x21,
91 .ver = 0x100,
92 .name = "4eg",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +053093 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +020094 },
95 {
96 .id = 0x21,
97 .ver = 0x12c,
98 .name = "4cg",
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +053099 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +0200100 },
101 {
Michal Simek47e60cb2016-02-01 15:05:58 +0100102 .id = 0x30,
103 .name = "7ev",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530104 .evexists = 1,
Michal Simek47e60cb2016-02-01 15:05:58 +0100105 },
106 {
Michal Simek494fffe2017-08-22 14:58:53 +0200107 .id = 0x30,
108 .ver = 0x100,
109 .name = "7eg",
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530110 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +0200111 },
112 {
113 .id = 0x30,
114 .ver = 0x12c,
115 .name = "7cg",
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530116 .evexists = 1,
Michal Simek494fffe2017-08-22 14:58:53 +0200117 },
118 {
Michal Simek47e60cb2016-02-01 15:05:58 +0100119 .id = 0x38,
120 .name = "9eg",
121 },
122 {
Michal Simek494fffe2017-08-22 14:58:53 +0200123 .id = 0x38,
124 .ver = 0x2c,
125 .name = "9cg",
126 },
127 {
Michal Simek47e60cb2016-02-01 15:05:58 +0100128 .id = 0x39,
129 .name = "6eg",
130 },
131 {
Michal Simek494fffe2017-08-22 14:58:53 +0200132 .id = 0x39,
133 .ver = 0x2c,
134 .name = "6cg",
135 },
136 {
Michal Simek47e60cb2016-02-01 15:05:58 +0100137 .id = 0x40,
138 .name = "11eg",
139 },
Michal Simek494fffe2017-08-22 14:58:53 +0200140 { /* For testing purpose only */
141 .id = 0x50,
142 .ver = 0x2c,
143 .name = "15cg",
144 },
Michal Simek47e60cb2016-02-01 15:05:58 +0100145 {
146 .id = 0x50,
147 .name = "15eg",
148 },
149 {
150 .id = 0x58,
151 .name = "19eg",
152 },
153 {
154 .id = 0x59,
155 .name = "17eg",
156 },
Michal Simekb030fed2017-06-02 08:08:59 +0200157 {
158 .id = 0x61,
159 .name = "21dr",
160 },
161 {
162 .id = 0x63,
163 .name = "23dr",
164 },
165 {
166 .id = 0x65,
167 .name = "25dr",
168 },
169 {
170 .id = 0x64,
171 .name = "27dr",
172 },
173 {
174 .id = 0x60,
175 .name = "28dr",
176 },
177 {
178 .id = 0x62,
179 .name = "29dr",
180 },
Siva Durga Prasad Paladuguc7490902019-03-23 15:00:06 +0530181 {
182 .id = 0x66,
183 .name = "39dr",
184 },
Siva Durga Prasad Paladugu134b0c82019-07-23 11:56:17 +0530185 {
186 .id = 0x7b,
187 .name = "48dr",
188 },
189 {
190 .id = 0x7e,
191 .name = "49dr",
192 },
Michal Simek47e60cb2016-02-01 15:05:58 +0100193};
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530194#endif
Michal Simek47e60cb2016-02-01 15:05:58 +0100195
Siva Durga Prasad Paladuguf52bf5a2017-07-25 11:51:38 +0530196int chip_id(unsigned char id)
Michal Simek47e60cb2016-02-01 15:05:58 +0100197{
198 struct pt_regs regs;
Siva Durga Prasad Paladugudb3123b2017-07-25 11:51:36 +0530199 int val = -EINVAL;
Michal Simek47e60cb2016-02-01 15:05:58 +0100200
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530201 if (current_el() != 3) {
202 regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
203 regs.regs[1] = 0;
204 regs.regs[2] = 0;
205 regs.regs[3] = 0;
Michal Simek47e60cb2016-02-01 15:05:58 +0100206
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530207 smc_call(&regs);
208
209 /*
210 * SMC returns:
211 * regs[0][31:0] = status of the operation
212 * regs[0][63:32] = CSU.IDCODE register
213 * regs[1][31:0] = CSU.version register
Michal Simek494fffe2017-08-22 14:58:53 +0200214 * regs[1][63:32] = CSU.IDCODE2 register
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530215 */
216 switch (id) {
217 case IDCODE:
218 regs.regs[0] = upper_32_bits(regs.regs[0]);
219 regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
220 ZYNQMP_CSU_IDCODE_SVD_MASK;
221 regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
222 val = regs.regs[0];
223 break;
224 case VERSION:
225 regs.regs[1] = lower_32_bits(regs.regs[1]);
226 regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
227 val = regs.regs[1];
228 break;
Michal Simek494fffe2017-08-22 14:58:53 +0200229 case IDCODE2:
230 regs.regs[1] = lower_32_bits(regs.regs[1]);
231 regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
232 val = regs.regs[1];
233 break;
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530234 default:
235 printf("%s, Invalid Req:0x%x\n", __func__, id);
236 }
237 } else {
238 switch (id) {
239 case IDCODE:
240 val = readl(ZYNQMP_CSU_IDCODE_ADDR);
241 val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
242 ZYNQMP_CSU_IDCODE_SVD_MASK;
243 val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
244 break;
245 case VERSION:
246 val = readl(ZYNQMP_CSU_VER_ADDR);
247 val &= ZYNQMP_CSU_SILICON_VER_MASK;
248 break;
249 default:
250 printf("%s, Invalid Req:0x%x\n", __func__, id);
251 }
Siva Durga Prasad Paladugudb3123b2017-07-25 11:51:36 +0530252 }
Soren Brinkmann0cba6ab2016-09-29 11:44:41 -0700253
Siva Durga Prasad Paladugudb3123b2017-07-25 11:51:36 +0530254 return val;
Michal Simek47e60cb2016-02-01 15:05:58 +0100255}
256
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530257#define ZYNQMP_VERSION_SIZE 9
258#define ZYNQMP_PL_STATUS_BIT 9
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530259#define ZYNQMP_IPDIS_VCU_BIT 8
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530260#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
261#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530262#define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \
263 ~BIT(ZYNQMP_IPDIS_VCU_BIT)
264#define MAX_VARIANTS_EV 3
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530265
Siva Durga Prasad Paladugu74ba69d2017-07-25 11:51:37 +0530266#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
267 !defined(CONFIG_SPL_BUILD)
Michal Simek47e60cb2016-02-01 15:05:58 +0100268static char *zynqmp_get_silicon_idcode_name(void)
269{
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530270 u32 i, id, ver, j;
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530271 char *buf;
272 static char name[ZYNQMP_VERSION_SIZE];
Michal Simek47e60cb2016-02-01 15:05:58 +0100273
Siva Durga Prasad Paladugudb3123b2017-07-25 11:51:36 +0530274 id = chip_id(IDCODE);
Michal Simek494fffe2017-08-22 14:58:53 +0200275 ver = chip_id(IDCODE2);
276
Michal Simek47e60cb2016-02-01 15:05:58 +0100277 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530278 if (zynqmp_devices[i].id == id) {
279 if (zynqmp_devices[i].evexists &&
280 !(ver & ZYNQMP_PL_STATUS_MASK))
281 break;
282 if (zynqmp_devices[i].ver == (ver &
283 ZYNQMP_CSU_VERSION_MASK))
284 break;
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530285 }
Michal Simek47e60cb2016-02-01 15:05:58 +0100286 }
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530287
288 if (i >= ARRAY_SIZE(zynqmp_devices))
289 return "unknown";
290
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530291 strncat(name, "zu", 2);
292 if (!zynqmp_devices[i].evexists ||
293 (ver & ZYNQMP_PL_STATUS_MASK)) {
294 strncat(name, zynqmp_devices[i].name,
295 ZYNQMP_VERSION_SIZE - 3);
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530296 return name;
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530297 }
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530298
Siva Durga Prasad Paladugu5473f242018-10-26 17:47:55 +0530299 /*
300 * Here we are means, PL not powered up and ev variant
301 * exists. So, we need to ignore VCU disable bit(8) in
302 * version and findout if its CG or EG/EV variant.
303 */
304 for (j = 0; j < MAX_VARIANTS_EV; j++, i++) {
305 if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) ==
306 (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) {
307 strncat(name, zynqmp_devices[i].name,
308 ZYNQMP_VERSION_SIZE - 3);
309 break;
310 }
311 }
312
313 if (j >= MAX_VARIANTS_EV)
314 return "unknown";
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530315
316 if (strstr(name, "eg") || strstr(name, "ev")) {
317 buf = strstr(name, "e");
318 *buf = '\0';
319 }
320
321 return name;
Michal Simek47e60cb2016-02-01 15:05:58 +0100322}
323#endif
324
Michal Simekfb4000e2017-02-07 14:32:26 +0100325int board_early_init_f(void)
326{
Michal Simek88f05a92018-01-15 12:52:59 +0100327#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
Michal Simekc0adba52020-01-07 09:02:52 +0100328 int ret;
329
Michal Simekf32e79f2018-01-10 11:48:48 +0100330 ret = psu_init();
Michal Simekc0adba52020-01-07 09:02:52 +0100331 if (ret)
332 return ret;
Michal Simekf8451f12020-03-20 08:59:02 +0100333
334 /* Delay is required for clocks to be propagated */
335 udelay(1000000);
Michal Simek55de0922017-07-12 13:08:41 +0200336#endif
337
Michal Simekc0adba52020-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 Simekfb4000e2017-02-07 14:32:26 +0100345}
346
Michal Simekc5143012020-02-11 12:43:14 +0100347static int multi_boot(void)
348{
349 u32 multiboot;
350
351 multiboot = readl(&csu_base->multi_boot);
352
353 printf("Multiboot:\t%x\n", multiboot);
354
355 return 0;
356}
357
Michal Simek84c72042015-01-15 10:01:51 +0100358int board_init(void)
359{
Michal Simek66ef85d2020-03-04 08:48:16 +0100360#if defined(CONFIG_ZYNQMP_FIRMWARE)
Ibai Erkiaga325a22d2019-09-27 11:37:04 +0100361 struct udevice *dev;
362
363 uclass_get_device_by_name(UCLASS_FIRMWARE, "zynqmp-power", &dev);
364 if (!dev)
365 panic("PMU Firmware device not found - Enable it");
Michal Simek66ef85d2020-03-04 08:48:16 +0100366#endif
Ibai Erkiaga325a22d2019-09-27 11:37:04 +0100367
Luca Ceresolic28a9cf2019-05-21 18:06:43 +0200368#if defined(CONFIG_SPL_BUILD)
369 /* Check *at build time* if the filename is an non-empty string */
370 if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
371 zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
372 zynqmp_pm_cfg_obj_size);
373#endif
374
Michal Simeka0736ef2015-06-22 14:31:06 +0200375 printf("EL Level:\tEL%d\n", current_el());
376
Michal Simek47e60cb2016-02-01 15:05:58 +0100377#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
378 !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
379 defined(CONFIG_SPL_BUILD))
380 if (current_el() != 3) {
Siva Durga Prasad Paladugu83bf2ff2018-03-02 16:20:10 +0530381 zynqmppl.name = zynqmp_get_silicon_idcode_name();
Michal Simek47e60cb2016-02-01 15:05:58 +0100382 printf("Chip ID:\t%s\n", zynqmppl.name);
383 fpga_init();
384 fpga_add(fpga_xilinx, &zynqmppl);
385 }
386#endif
387
Michal Simekc5143012020-02-11 12:43:14 +0100388 if (current_el() == 3)
389 multi_boot();
390
Michal Simek84c72042015-01-15 10:01:51 +0100391 return 0;
392}
393
394int board_early_init_r(void)
395{
396 u32 val;
397
Siva Durga Prasad Paladuguec60a272017-12-07 15:05:30 +0530398 if (current_el() != 3)
399 return 0;
400
Michal Simek90a35db2017-07-12 10:32:18 +0200401 val = readl(&crlapb_base->timestamp_ref_ctrl);
402 val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
403
Siva Durga Prasad Paladuguec60a272017-12-07 15:05:30 +0530404 if (!val) {
Michal Simek0785dfd2015-11-05 08:34:35 +0100405 val = readl(&crlapb_base->timestamp_ref_ctrl);
406 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
407 writel(val, &crlapb_base->timestamp_ref_ctrl);
Michal Simek84c72042015-01-15 10:01:51 +0100408
Michal Simek0785dfd2015-11-05 08:34:35 +0100409 /* Program freq register in System counter */
410 writel(zynqmp_get_system_timer_freq(),
411 &iou_scntr_secure->base_frequency_id_register);
412 /* And enable system counter */
413 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
414 &iou_scntr_secure->counter_control_register);
415 }
Michal Simek84c72042015-01-15 10:01:51 +0100416 return 0;
417}
418
Nitin Jain51916862018-02-16 12:56:17 +0530419unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
Simon Glass09140112020-05-10 11:40:03 -0600420 char *const argv[])
Nitin Jain51916862018-02-16 12:56:17 +0530421{
422 int ret = 0;
423
424 if (current_el() > 1) {
425 smp_kick_all_cpus();
426 dcache_disable();
427 armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
428 ES_TO_AARCH64);
429 } else {
430 printf("FAIL: current EL is not above EL1\n");
431 ret = EINVAL;
432 }
433 return ret;
434}
435
Michal Simek8d59d7f2016-02-08 09:34:53 +0100436#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
Simon Glass76b00ac2017-03-31 08:40:32 -0600437int dram_init_banksize(void)
Tom Rini361a8792016-12-09 07:56:54 -0500438{
Nitin Jain06789412018-04-20 12:30:40 +0530439 int ret;
440
441 ret = fdtdec_setup_memory_banksize();
442 if (ret)
443 return ret;
444
445 mem_map_fill();
446
447 return 0;
Michal Simek8d59d7f2016-02-08 09:34:53 +0100448}
449
450int dram_init(void)
451{
Siva Durga Prasad Paladugu12308b12018-07-16 15:56:11 +0530452 if (fdtdec_setup_mem_size_base() != 0)
Nathan Rossi950f86c2016-12-19 00:03:34 +1000453 return -EINVAL;
Michal Simek8d59d7f2016-02-08 09:34:53 +0100454
455 return 0;
456}
457#else
Nitin Jain06789412018-04-20 12:30:40 +0530458int dram_init_banksize(void)
459{
460#if defined(CONFIG_NR_DRAM_BANKS)
461 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
462 gd->bd->bi_dram[0].size = get_effective_memsize();
463#endif
464
465 mem_map_fill();
466
467 return 0;
468}
469
Michal Simek84c72042015-01-15 10:01:51 +0100470int dram_init(void)
471{
Michal Simek61dc92a2018-04-11 16:12:28 +0200472 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
473 CONFIG_SYS_SDRAM_SIZE);
Michal Simek84c72042015-01-15 10:01:51 +0100474
475 return 0;
476}
Michal Simek8d59d7f2016-02-08 09:34:53 +0100477#endif
Michal Simek84c72042015-01-15 10:01:51 +0100478
Michal Simek84c72042015-01-15 10:01:51 +0100479void reset_cpu(ulong addr)
480{
481}
482
Michal Simek0bf3f9c2018-12-20 09:33:38 +0100483#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simekd348bea2018-05-17 14:06:06 +0200484static const struct {
485 u32 bit;
486 const char *name;
487} reset_reasons[] = {
488 { RESET_REASON_DEBUG_SYS, "DEBUG" },
489 { RESET_REASON_SOFT, "SOFT" },
490 { RESET_REASON_SRST, "SRST" },
491 { RESET_REASON_PSONLY, "PS-ONLY" },
492 { RESET_REASON_PMU, "PMU" },
493 { RESET_REASON_INTERNAL, "INTERNAL" },
494 { RESET_REASON_EXTERNAL, "EXTERNAL" },
495 {}
496};
497
T Karthik Reddybe523722019-03-13 20:24:18 +0530498static int reset_reason(void)
Michal Simekd348bea2018-05-17 14:06:06 +0200499{
T Karthik Reddybe523722019-03-13 20:24:18 +0530500 u32 reg;
501 int i, ret;
Michal Simekd348bea2018-05-17 14:06:06 +0200502 const char *reason = NULL;
503
T Karthik Reddybe523722019-03-13 20:24:18 +0530504 ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, &reg);
505 if (ret)
506 return -EINVAL;
Michal Simekd348bea2018-05-17 14:06:06 +0200507
508 puts("Reset reason:\t");
509
510 for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
T Karthik Reddybe523722019-03-13 20:24:18 +0530511 if (reg & reset_reasons[i].bit) {
Michal Simekd348bea2018-05-17 14:06:06 +0200512 reason = reset_reasons[i].name;
513 printf("%s ", reset_reasons[i].name);
514 break;
515 }
516 }
517
518 puts("\n");
519
520 env_set("reset_reason", reason);
521
Michal Simek3d037522020-03-23 14:02:01 +0100522 ret = zynqmp_mmio_write((ulong)&crlapb_base->reset_reason, ~0, ~0);
T Karthik Reddybe523722019-03-13 20:24:18 +0530523 if (ret)
524 return -EINVAL;
Michal Simekd348bea2018-05-17 14:06:06 +0200525
526 return ret;
527}
528
Michal Simek91d7e0c2019-02-14 13:14:30 +0100529static int set_fdtfile(void)
530{
531 char *compatible, *fdtfile;
532 const char *suffix = ".dtb";
533 const char *vendor = "xilinx/";
534
535 if (env_get("fdtfile"))
536 return 0;
537
538 compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
539 if (compatible) {
540 debug("Compatible: %s\n", compatible);
541
542 /* Discard vendor prefix */
543 strsep(&compatible, ",");
544
545 fdtfile = calloc(1, strlen(vendor) + strlen(compatible) +
546 strlen(suffix) + 1);
547 if (!fdtfile)
548 return -ENOMEM;
549
550 sprintf(fdtfile, "%s%s%s", vendor, compatible, suffix);
551
552 env_set("fdtfile", fdtfile);
553 free(fdtfile);
554 }
555
556 return 0;
557}
558
Michal Simek51f6c522020-04-08 11:04:41 +0200559static u8 zynqmp_get_bootmode(void)
560{
561 u8 bootmode;
562 u32 reg = 0;
563 int ret;
564
565 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
566 if (ret)
567 return -EINVAL;
568
569 if (reg >> BOOT_MODE_ALT_SHIFT)
570 reg >>= BOOT_MODE_ALT_SHIFT;
571
572 bootmode = reg & BOOT_MODES_MASK;
573
574 return bootmode;
575}
576
Michal Simek84c72042015-01-15 10:01:51 +0100577int board_late_init(void)
578{
Michal Simek84c72042015-01-15 10:01:51 +0100579 u8 bootmode;
Michal Simek2882b392018-04-25 11:20:43 +0200580 struct udevice *dev;
581 int bootseq = -1;
582 int bootseq_len = 0;
Michal Simek0478b0b2018-04-25 11:10:34 +0200583 int env_targets_len = 0;
Michal Simekb72894f2016-04-22 14:28:54 +0200584 const char *mode;
585 char *new_targets;
Siva Durga Prasad Paladugu01c42d32017-12-20 16:35:06 +0530586 char *env_targets;
Siva Durga Prasad Paladugud1db89f2017-02-21 17:58:28 +0530587 int ret;
Michal Simekb72894f2016-04-22 14:28:54 +0200588
Michal Simeke615f392018-10-05 08:55:16 +0200589#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
590 usb_ether_init();
591#endif
592
Michal Simekb72894f2016-04-22 14:28:54 +0200593 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
594 debug("Saved variables - Skipping\n");
595 return 0;
596 }
Michal Simek84c72042015-01-15 10:01:51 +0100597
Michal Simek91d7e0c2019-02-14 13:14:30 +0100598 ret = set_fdtfile();
599 if (ret)
600 return ret;
601
Michal Simek51f6c522020-04-08 11:04:41 +0200602 bootmode = zynqmp_get_bootmode();
Michal Simek84c72042015-01-15 10:01:51 +0100603
Michal Simekfb909172015-09-20 17:20:42 +0200604 puts("Bootmode: ");
Michal Simek84c72042015-01-15 10:01:51 +0100605 switch (bootmode) {
Michal Simekd58fc122016-08-19 14:14:52 +0200606 case USB_MODE:
607 puts("USB_MODE\n");
608 mode = "usb";
Michal Simek07656ba2017-12-01 15:18:24 +0100609 env_set("modeboot", "usb_dfu_spl");
Michal Simekd58fc122016-08-19 14:14:52 +0200610 break;
Siva Durga Prasad Paladugu0a5bcc82015-03-13 11:10:26 +0530611 case JTAG_MODE:
Michal Simekfb909172015-09-20 17:20:42 +0200612 puts("JTAG_MODE\n");
Siva Durga Prasad Paladugu5d2274c2019-06-25 17:41:09 +0530613 mode = "jtag pxe dhcp";
Michal Simek07656ba2017-12-01 15:18:24 +0100614 env_set("modeboot", "jtagboot");
Siva Durga Prasad Paladugu0a5bcc82015-03-13 11:10:26 +0530615 break;
616 case QSPI_MODE_24BIT:
617 case QSPI_MODE_32BIT:
Michal Simekb72894f2016-04-22 14:28:54 +0200618 mode = "qspi0";
Michal Simekfb909172015-09-20 17:20:42 +0200619 puts("QSPI_MODE\n");
Michal Simek07656ba2017-12-01 15:18:24 +0100620 env_set("modeboot", "qspiboot");
Siva Durga Prasad Paladugu0a5bcc82015-03-13 11:10:26 +0530621 break;
Michal Simek39c56f52015-04-15 15:02:28 +0200622 case EMMC_MODE:
Michal Simek78678fe2015-10-05 15:59:38 +0200623 puts("EMMC_MODE\n");
T Karthik Reddy18be60b2019-12-17 06:41:42 -0700624 if (uclass_get_device_by_name(UCLASS_MMC,
625 "mmc@ff160000", &dev) &&
626 uclass_get_device_by_name(UCLASS_MMC,
627 "sdhci@ff160000", &dev)) {
628 puts("Boot from EMMC but without SD0 enabled!\n");
629 return -1;
630 }
631 debug("mmc0 device found at %p, seq %d\n", dev, dev->seq);
632
633 mode = "mmc";
634 bootseq = dev->seq;
Michal Simek78678fe2015-10-05 15:59:38 +0200635 break;
636 case SD_MODE:
Michal Simekfb909172015-09-20 17:20:42 +0200637 puts("SD_MODE\n");
Michal Simek2882b392018-04-25 11:20:43 +0200638 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue7c9de62019-01-03 15:44:24 +0530639 "mmc@ff160000", &dev) &&
640 uclass_get_device_by_name(UCLASS_MMC,
Michal Simek2882b392018-04-25 11:20:43 +0200641 "sdhci@ff160000", &dev)) {
642 puts("Boot from SD0 but without SD0 enabled!\n");
643 return -1;
644 }
645 debug("mmc0 device found at %p, seq %d\n", dev, dev->seq);
646
647 mode = "mmc";
648 bootseq = dev->seq;
Michal Simek07656ba2017-12-01 15:18:24 +0100649 env_set("modeboot", "sdboot");
Michal Simek84c72042015-01-15 10:01:51 +0100650 break;
Siva Durga Prasad Paladugue1992272016-09-21 11:45:05 +0530651 case SD1_LSHFT_MODE:
652 puts("LVL_SHFT_");
653 /* fall through */
Michal Simekaf813ac2015-10-05 10:51:12 +0200654 case SD_MODE1:
Michal Simekfb909172015-09-20 17:20:42 +0200655 puts("SD_MODE1\n");
Michal Simek2882b392018-04-25 11:20:43 +0200656 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue7c9de62019-01-03 15:44:24 +0530657 "mmc@ff170000", &dev) &&
658 uclass_get_device_by_name(UCLASS_MMC,
Michal Simek2882b392018-04-25 11:20:43 +0200659 "sdhci@ff170000", &dev)) {
660 puts("Boot from SD1 but without SD1 enabled!\n");
661 return -1;
662 }
663 debug("mmc1 device found at %p, seq %d\n", dev, dev->seq);
664
665 mode = "mmc";
666 bootseq = dev->seq;
Michal Simek07656ba2017-12-01 15:18:24 +0100667 env_set("modeboot", "sdboot");
Michal Simekaf813ac2015-10-05 10:51:12 +0200668 break;
669 case NAND_MODE:
Michal Simekfb909172015-09-20 17:20:42 +0200670 puts("NAND_MODE\n");
Michal Simekb72894f2016-04-22 14:28:54 +0200671 mode = "nand0";
Michal Simek07656ba2017-12-01 15:18:24 +0100672 env_set("modeboot", "nandboot");
Michal Simekaf813ac2015-10-05 10:51:12 +0200673 break;
Michal Simek84c72042015-01-15 10:01:51 +0100674 default:
Michal Simekb72894f2016-04-22 14:28:54 +0200675 mode = "";
Michal Simek84c72042015-01-15 10:01:51 +0100676 printf("Invalid Boot Mode:0x%x\n", bootmode);
677 break;
678 }
679
Michal Simek2882b392018-04-25 11:20:43 +0200680 if (bootseq >= 0) {
681 bootseq_len = snprintf(NULL, 0, "%i", bootseq);
682 debug("Bootseq len: %x\n", bootseq_len);
683 }
684
Michal Simekb72894f2016-04-22 14:28:54 +0200685 /*
686 * One terminating char + one byte for space between mode
687 * and default boot_targets
688 */
Siva Durga Prasad Paladugu01c42d32017-12-20 16:35:06 +0530689 env_targets = env_get("boot_targets");
Michal Simek0478b0b2018-04-25 11:10:34 +0200690 if (env_targets)
691 env_targets_len = strlen(env_targets);
692
Michal Simek2882b392018-04-25 11:20:43 +0200693 new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
694 bootseq_len);
Michal Simek1e3e68f2018-06-13 09:42:41 +0200695 if (!new_targets)
696 return -ENOMEM;
Michal Simek0478b0b2018-04-25 11:10:34 +0200697
Michal Simek2882b392018-04-25 11:20:43 +0200698 if (bootseq >= 0)
699 sprintf(new_targets, "%s%x %s", mode, bootseq,
700 env_targets ? env_targets : "");
701 else
702 sprintf(new_targets, "%s %s", mode,
703 env_targets ? env_targets : "");
Michal Simekb72894f2016-04-22 14:28:54 +0200704
Simon Glass382bee52017-08-03 12:22:09 -0600705 env_set("boot_targets", new_targets);
Michal Simekb72894f2016-04-22 14:28:54 +0200706
Michal Simekd348bea2018-05-17 14:06:06 +0200707 reset_reason();
708
Michal Simek80fdef12020-03-31 12:39:37 +0200709 return board_late_init_xilinx();
Michal Simek84c72042015-01-15 10:01:51 +0100710}
Michal Simek0bf3f9c2018-12-20 09:33:38 +0100711#endif
Siva Durga Prasad Paladugu84696ff2015-08-04 13:01:05 +0530712
713int checkboard(void)
714{
Michal Simek5af08552016-01-25 11:04:21 +0100715 puts("Board: Xilinx ZynqMP\n");
Siva Durga Prasad Paladugu84696ff2015-08-04 13:01:05 +0530716 return 0;
717}