blob: d649daba96d49ac9a0cfbc391b508621ffcf5050 [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 Glass5e6201b2019-08-01 09:46:51 -06008#include <env.h>
Michal Simekd54b1af2015-09-30 17:26:55 +02009#include <sata.h>
Michal Simekb216cc12015-07-23 13:27:40 +020010#include <ahci.h>
11#include <scsi.h>
Michal Simekecfb6dc2016-04-22 14:28:54 +020012#include <malloc.h>
Michal Simekbf0f9ca2018-04-19 15:43:38 +020013#include <wdt.h>
Michal Simekc23d3f82015-11-05 08:34:35 +010014#include <asm/arch/clk.h>
Michal Simek04b7e622015-01-15 10:01:51 +010015#include <asm/arch/hardware.h>
16#include <asm/arch/sys_proto.h>
Michal Simekf2f08642018-01-10 09:36:09 +010017#include <asm/arch/psu_init_gpl.h>
Michal Simek04b7e622015-01-15 10:01:51 +010018#include <asm/io.h>
Michal Simekf183a982018-04-25 11:20:43 +020019#include <dm/device.h>
Michal Simekbf0f9ca2018-04-19 15:43:38 +020020#include <dm/uclass.h>
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +053021#include <usb.h>
22#include <dwc3-uboot.h>
Michal Simek8111aff2016-02-01 15:05:58 +010023#include <zynqmppl.h>
Michal Simek76d0a772016-09-01 11:16:40 +020024#include <g_dnl.h>
Michal Simek04b7e622015-01-15 10:01:51 +010025
Luca Ceresoli23e65002019-05-21 18:06:43 +020026#include "pm_cfg_obj.h"
27
Michal Simek04b7e622015-01-15 10:01:51 +010028DECLARE_GLOBAL_DATA_PTR;
29
Michal Simek8111aff2016-02-01 15:05:58 +010030#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
31 !defined(CONFIG_SPL_BUILD)
32static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
33
34static const struct {
Michal Simek6908b862017-11-06 12:55:59 +010035 u32 id;
Michal Simek50d8cef2017-08-22 14:58:53 +020036 u32 ver;
Michal Simek8111aff2016-02-01 15:05:58 +010037 char *name;
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053038 bool evexists;
Michal Simek8111aff2016-02-01 15:05:58 +010039} zynqmp_devices[] = {
40 {
41 .id = 0x10,
42 .name = "3eg",
43 },
44 {
Michal Simek50d8cef2017-08-22 14:58:53 +020045 .id = 0x10,
46 .ver = 0x2c,
47 .name = "3cg",
48 },
49 {
Michal Simek8111aff2016-02-01 15:05:58 +010050 .id = 0x11,
51 .name = "2eg",
52 },
53 {
Michal Simek50d8cef2017-08-22 14:58:53 +020054 .id = 0x11,
55 .ver = 0x2c,
56 .name = "2cg",
57 },
58 {
Michal Simek8111aff2016-02-01 15:05:58 +010059 .id = 0x20,
60 .name = "5ev",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053061 .evexists = 1,
Michal Simek8111aff2016-02-01 15:05:58 +010062 },
63 {
Michal Simek50d8cef2017-08-22 14:58:53 +020064 .id = 0x20,
65 .ver = 0x100,
66 .name = "5eg",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053067 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +020068 },
69 {
70 .id = 0x20,
71 .ver = 0x12c,
72 .name = "5cg",
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +053073 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +020074 },
75 {
Michal Simek8111aff2016-02-01 15:05:58 +010076 .id = 0x21,
77 .name = "4ev",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053078 .evexists = 1,
Michal Simek8111aff2016-02-01 15:05:58 +010079 },
80 {
Michal Simek50d8cef2017-08-22 14:58:53 +020081 .id = 0x21,
82 .ver = 0x100,
83 .name = "4eg",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053084 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +020085 },
86 {
87 .id = 0x21,
88 .ver = 0x12c,
89 .name = "4cg",
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +053090 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +020091 },
92 {
Michal Simek8111aff2016-02-01 15:05:58 +010093 .id = 0x30,
94 .name = "7ev",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +053095 .evexists = 1,
Michal Simek8111aff2016-02-01 15:05:58 +010096 },
97 {
Michal Simek50d8cef2017-08-22 14:58:53 +020098 .id = 0x30,
99 .ver = 0x100,
100 .name = "7eg",
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530101 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +0200102 },
103 {
104 .id = 0x30,
105 .ver = 0x12c,
106 .name = "7cg",
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530107 .evexists = 1,
Michal Simek50d8cef2017-08-22 14:58:53 +0200108 },
109 {
Michal Simek8111aff2016-02-01 15:05:58 +0100110 .id = 0x38,
111 .name = "9eg",
112 },
113 {
Michal Simek50d8cef2017-08-22 14:58:53 +0200114 .id = 0x38,
115 .ver = 0x2c,
116 .name = "9cg",
117 },
118 {
Michal Simek8111aff2016-02-01 15:05:58 +0100119 .id = 0x39,
120 .name = "6eg",
121 },
122 {
Michal Simek50d8cef2017-08-22 14:58:53 +0200123 .id = 0x39,
124 .ver = 0x2c,
125 .name = "6cg",
126 },
127 {
Michal Simek8111aff2016-02-01 15:05:58 +0100128 .id = 0x40,
129 .name = "11eg",
130 },
Michal Simek50d8cef2017-08-22 14:58:53 +0200131 { /* For testing purpose only */
132 .id = 0x50,
133 .ver = 0x2c,
134 .name = "15cg",
135 },
Michal Simek8111aff2016-02-01 15:05:58 +0100136 {
137 .id = 0x50,
138 .name = "15eg",
139 },
140 {
141 .id = 0x58,
142 .name = "19eg",
143 },
144 {
145 .id = 0x59,
146 .name = "17eg",
147 },
Michal Simekb510e532017-06-02 08:08:59 +0200148 {
149 .id = 0x61,
150 .name = "21dr",
151 },
152 {
153 .id = 0x63,
154 .name = "23dr",
155 },
156 {
157 .id = 0x65,
158 .name = "25dr",
159 },
160 {
161 .id = 0x64,
162 .name = "27dr",
163 },
164 {
165 .id = 0x60,
166 .name = "28dr",
167 },
168 {
169 .id = 0x62,
170 .name = "29dr",
171 },
Siva Durga Prasad Paladugu70866b42019-03-23 15:00:06 +0530172 {
173 .id = 0x66,
174 .name = "39dr",
175 },
Michal Simek8111aff2016-02-01 15:05:58 +0100176};
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530177#endif
Michal Simek8111aff2016-02-01 15:05:58 +0100178
Siva Durga Prasad Paladugucd35d522017-07-25 11:51:38 +0530179int chip_id(unsigned char id)
Michal Simek8111aff2016-02-01 15:05:58 +0100180{
181 struct pt_regs regs;
Siva Durga Prasad Paladugu9f0a8e92017-07-25 11:51:36 +0530182 int val = -EINVAL;
Michal Simek8111aff2016-02-01 15:05:58 +0100183
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530184 if (current_el() != 3) {
185 regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
186 regs.regs[1] = 0;
187 regs.regs[2] = 0;
188 regs.regs[3] = 0;
Michal Simek8111aff2016-02-01 15:05:58 +0100189
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530190 smc_call(&regs);
191
192 /*
193 * SMC returns:
194 * regs[0][31:0] = status of the operation
195 * regs[0][63:32] = CSU.IDCODE register
196 * regs[1][31:0] = CSU.version register
Michal Simek50d8cef2017-08-22 14:58:53 +0200197 * regs[1][63:32] = CSU.IDCODE2 register
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530198 */
199 switch (id) {
200 case IDCODE:
201 regs.regs[0] = upper_32_bits(regs.regs[0]);
202 regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
203 ZYNQMP_CSU_IDCODE_SVD_MASK;
204 regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
205 val = regs.regs[0];
206 break;
207 case VERSION:
208 regs.regs[1] = lower_32_bits(regs.regs[1]);
209 regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
210 val = regs.regs[1];
211 break;
Michal Simek50d8cef2017-08-22 14:58:53 +0200212 case IDCODE2:
213 regs.regs[1] = lower_32_bits(regs.regs[1]);
214 regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
215 val = regs.regs[1];
216 break;
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530217 default:
218 printf("%s, Invalid Req:0x%x\n", __func__, id);
219 }
220 } else {
221 switch (id) {
222 case IDCODE:
223 val = readl(ZYNQMP_CSU_IDCODE_ADDR);
224 val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
225 ZYNQMP_CSU_IDCODE_SVD_MASK;
226 val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
227 break;
228 case VERSION:
229 val = readl(ZYNQMP_CSU_VER_ADDR);
230 val &= ZYNQMP_CSU_SILICON_VER_MASK;
231 break;
232 default:
233 printf("%s, Invalid Req:0x%x\n", __func__, id);
234 }
Siva Durga Prasad Paladugu9f0a8e92017-07-25 11:51:36 +0530235 }
Soren Brinkmannd7696a52016-09-29 11:44:41 -0700236
Siva Durga Prasad Paladugu9f0a8e92017-07-25 11:51:36 +0530237 return val;
Michal Simek8111aff2016-02-01 15:05:58 +0100238}
239
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530240#define ZYNQMP_VERSION_SIZE 9
241#define ZYNQMP_PL_STATUS_BIT 9
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530242#define ZYNQMP_IPDIS_VCU_BIT 8
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530243#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
244#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530245#define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \
246 ~BIT(ZYNQMP_IPDIS_VCU_BIT)
247#define MAX_VARIANTS_EV 3
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530248
Siva Durga Prasad Paladugu8d526532017-07-25 11:51:37 +0530249#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
250 !defined(CONFIG_SPL_BUILD)
Michal Simek8111aff2016-02-01 15:05:58 +0100251static char *zynqmp_get_silicon_idcode_name(void)
252{
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530253 u32 i, id, ver, j;
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530254 char *buf;
255 static char name[ZYNQMP_VERSION_SIZE];
Michal Simek8111aff2016-02-01 15:05:58 +0100256
Siva Durga Prasad Paladugu9f0a8e92017-07-25 11:51:36 +0530257 id = chip_id(IDCODE);
Michal Simek50d8cef2017-08-22 14:58:53 +0200258 ver = chip_id(IDCODE2);
259
Michal Simek8111aff2016-02-01 15:05:58 +0100260 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530261 if (zynqmp_devices[i].id == id) {
262 if (zynqmp_devices[i].evexists &&
263 !(ver & ZYNQMP_PL_STATUS_MASK))
264 break;
265 if (zynqmp_devices[i].ver == (ver &
266 ZYNQMP_CSU_VERSION_MASK))
267 break;
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530268 }
Michal Simek8111aff2016-02-01 15:05:58 +0100269 }
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530270
271 if (i >= ARRAY_SIZE(zynqmp_devices))
272 return "unknown";
273
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530274 strncat(name, "zu", 2);
275 if (!zynqmp_devices[i].evexists ||
276 (ver & ZYNQMP_PL_STATUS_MASK)) {
277 strncat(name, zynqmp_devices[i].name,
278 ZYNQMP_VERSION_SIZE - 3);
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530279 return name;
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530280 }
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530281
Siva Durga Prasad Paladugu951c0192018-10-26 17:47:55 +0530282 /*
283 * Here we are means, PL not powered up and ev variant
284 * exists. So, we need to ignore VCU disable bit(8) in
285 * version and findout if its CG or EG/EV variant.
286 */
287 for (j = 0; j < MAX_VARIANTS_EV; j++, i++) {
288 if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) ==
289 (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) {
290 strncat(name, zynqmp_devices[i].name,
291 ZYNQMP_VERSION_SIZE - 3);
292 break;
293 }
294 }
295
296 if (j >= MAX_VARIANTS_EV)
297 return "unknown";
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530298
299 if (strstr(name, "eg") || strstr(name, "ev")) {
300 buf = strstr(name, "e");
301 *buf = '\0';
302 }
303
304 return name;
Michal Simek8111aff2016-02-01 15:05:58 +0100305}
306#endif
307
Michal Simek8b353302017-02-07 14:32:26 +0100308int board_early_init_f(void)
309{
Michal Simekc8785f22018-01-10 11:48:48 +0100310 int ret = 0;
Michal Simek8b353302017-02-07 14:32:26 +0100311#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP)
Siva Durga Prasad Paladugu8406d472018-08-21 15:44:49 +0530312 u32 pm_api_version;
313
314 pm_api_version = zynqmp_pmufw_version();
315 printf("PMUFW:\tv%d.%d\n",
316 pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT,
317 pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK);
318
319 if (pm_api_version < ZYNQMP_PM_VERSION)
320 panic("PMUFW version error. Expected: v%d.%d\n",
321 ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR);
Michal Simek8b353302017-02-07 14:32:26 +0100322#endif
Michal Simeke0f36102017-07-12 13:08:41 +0200323
Michal Simek1a1ab5a2018-01-15 12:52:59 +0100324#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
Michal Simekc8785f22018-01-10 11:48:48 +0100325 ret = psu_init();
Michal Simeke0f36102017-07-12 13:08:41 +0200326#endif
327
Michal Simekc8785f22018-01-10 11:48:48 +0100328 return ret;
Michal Simek8b353302017-02-07 14:32:26 +0100329}
330
Michal Simek04b7e622015-01-15 10:01:51 +0100331int board_init(void)
332{
Luca Ceresoli23e65002019-05-21 18:06:43 +0200333#if defined(CONFIG_SPL_BUILD)
334 /* Check *at build time* if the filename is an non-empty string */
335 if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
336 zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
337 zynqmp_pm_cfg_obj_size);
338#endif
339
Michal Simekfb7242d2015-06-22 14:31:06 +0200340 printf("EL Level:\tEL%d\n", current_el());
341
Michal Simek8111aff2016-02-01 15:05:58 +0100342#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
343 !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
344 defined(CONFIG_SPL_BUILD))
345 if (current_el() != 3) {
Siva Durga Prasad Paladuguba2622d2018-03-02 16:20:10 +0530346 zynqmppl.name = zynqmp_get_silicon_idcode_name();
Michal Simek8111aff2016-02-01 15:05:58 +0100347 printf("Chip ID:\t%s\n", zynqmppl.name);
348 fpga_init();
349 fpga_add(fpga_xilinx, &zynqmppl);
350 }
Michal Simekbf0f9ca2018-04-19 15:43:38 +0200351#endif
352
Michal Simek04b7e622015-01-15 10:01:51 +0100353 return 0;
354}
355
356int board_early_init_r(void)
357{
358 u32 val;
359
Siva Durga Prasad Paladugu64d90002017-12-07 15:05:30 +0530360 if (current_el() != 3)
361 return 0;
362
Michal Simek245d5282017-07-12 10:32:18 +0200363 val = readl(&crlapb_base->timestamp_ref_ctrl);
364 val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
365
Siva Durga Prasad Paladugu64d90002017-12-07 15:05:30 +0530366 if (!val) {
Michal Simekc23d3f82015-11-05 08:34:35 +0100367 val = readl(&crlapb_base->timestamp_ref_ctrl);
368 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
369 writel(val, &crlapb_base->timestamp_ref_ctrl);
Michal Simek04b7e622015-01-15 10:01:51 +0100370
Michal Simekc23d3f82015-11-05 08:34:35 +0100371 /* Program freq register in System counter */
372 writel(zynqmp_get_system_timer_freq(),
373 &iou_scntr_secure->base_frequency_id_register);
374 /* And enable system counter */
375 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
376 &iou_scntr_secure->counter_control_register);
377 }
Michal Simek04b7e622015-01-15 10:01:51 +0100378 return 0;
379}
380
Nitin Jainb2eb59b2018-02-16 12:56:17 +0530381unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
382 char * const argv[])
383{
384 int ret = 0;
385
386 if (current_el() > 1) {
387 smp_kick_all_cpus();
388 dcache_disable();
389 armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
390 ES_TO_AARCH64);
391 } else {
392 printf("FAIL: current EL is not above EL1\n");
393 ret = EINVAL;
394 }
395 return ret;
396}
397
Michal Simek8faa66a2016-02-08 09:34:53 +0100398#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
Simon Glass2f949c32017-03-31 08:40:32 -0600399int dram_init_banksize(void)
Michal Simek8faa66a2016-02-08 09:34:53 +0100400{
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530401 int ret;
402
403 ret = fdtdec_setup_memory_banksize();
404 if (ret)
405 return ret;
406
407 mem_map_fill();
408
409 return 0;
Tom Riniedcfdbd2016-12-09 07:56:54 -0500410}
Michal Simek8faa66a2016-02-08 09:34:53 +0100411
Tom Riniedcfdbd2016-12-09 07:56:54 -0500412int dram_init(void)
413{
Siva Durga Prasad Paladugub3d55ea2018-07-16 15:56:11 +0530414 if (fdtdec_setup_mem_size_base() != 0)
Nathan Rossiac04bfa2016-12-19 00:03:34 +1000415 return -EINVAL;
Tom Riniedcfdbd2016-12-09 07:56:54 -0500416
417 return 0;
Michal Simek8faa66a2016-02-08 09:34:53 +0100418}
419#else
Nitin Jain9bcc76f2018-04-20 12:30:40 +0530420int dram_init_banksize(void)
421{
422#if defined(CONFIG_NR_DRAM_BANKS)
423 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
424 gd->bd->bi_dram[0].size = get_effective_memsize();
425#endif
426
427 mem_map_fill();
428
429 return 0;
430}
431
Michal Simek04b7e622015-01-15 10:01:51 +0100432int dram_init(void)
433{
Michal Simek1b846212018-04-11 16:12:28 +0200434 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
435 CONFIG_SYS_SDRAM_SIZE);
Michal Simek04b7e622015-01-15 10:01:51 +0100436
437 return 0;
438}
Michal Simek8faa66a2016-02-08 09:34:53 +0100439#endif
Michal Simek04b7e622015-01-15 10:01:51 +0100440
Michal Simek04b7e622015-01-15 10:01:51 +0100441void reset_cpu(ulong addr)
442{
443}
444
Michal Simek342edfe2018-12-20 09:33:38 +0100445#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simek29b9b712018-05-17 14:06:06 +0200446static const struct {
447 u32 bit;
448 const char *name;
449} reset_reasons[] = {
450 { RESET_REASON_DEBUG_SYS, "DEBUG" },
451 { RESET_REASON_SOFT, "SOFT" },
452 { RESET_REASON_SRST, "SRST" },
453 { RESET_REASON_PSONLY, "PS-ONLY" },
454 { RESET_REASON_PMU, "PMU" },
455 { RESET_REASON_INTERNAL, "INTERNAL" },
456 { RESET_REASON_EXTERNAL, "EXTERNAL" },
457 {}
458};
459
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530460static int reset_reason(void)
Michal Simek29b9b712018-05-17 14:06:06 +0200461{
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530462 u32 reg;
463 int i, ret;
Michal Simek29b9b712018-05-17 14:06:06 +0200464 const char *reason = NULL;
465
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530466 ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, &reg);
467 if (ret)
468 return -EINVAL;
Michal Simek29b9b712018-05-17 14:06:06 +0200469
470 puts("Reset reason:\t");
471
472 for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530473 if (reg & reset_reasons[i].bit) {
Michal Simek29b9b712018-05-17 14:06:06 +0200474 reason = reset_reasons[i].name;
475 printf("%s ", reset_reasons[i].name);
476 break;
477 }
478 }
479
480 puts("\n");
481
482 env_set("reset_reason", reason);
483
T Karthik Reddy09b6def2019-03-13 20:24:18 +0530484 ret = zynqmp_mmio_write(~0, ~0, (ulong)&crlapb_base->reset_reason);
485 if (ret)
486 return -EINVAL;
Michal Simek29b9b712018-05-17 14:06:06 +0200487
488 return ret;
489}
490
Michal Simek1ca66d72019-02-14 13:14:30 +0100491static int set_fdtfile(void)
492{
493 char *compatible, *fdtfile;
494 const char *suffix = ".dtb";
495 const char *vendor = "xilinx/";
496
497 if (env_get("fdtfile"))
498 return 0;
499
500 compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
501 if (compatible) {
502 debug("Compatible: %s\n", compatible);
503
504 /* Discard vendor prefix */
505 strsep(&compatible, ",");
506
507 fdtfile = calloc(1, strlen(vendor) + strlen(compatible) +
508 strlen(suffix) + 1);
509 if (!fdtfile)
510 return -ENOMEM;
511
512 sprintf(fdtfile, "%s%s%s", vendor, compatible, suffix);
513
514 env_set("fdtfile", fdtfile);
515 free(fdtfile);
516 }
517
518 return 0;
519}
520
Michal Simek04b7e622015-01-15 10:01:51 +0100521int board_late_init(void)
522{
523 u32 reg = 0;
524 u8 bootmode;
Michal Simekf183a982018-04-25 11:20:43 +0200525 struct udevice *dev;
526 int bootseq = -1;
527 int bootseq_len = 0;
Michal Simek7410b142018-04-25 11:10:34 +0200528 int env_targets_len = 0;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200529 const char *mode;
530 char *new_targets;
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530531 char *env_targets;
Siva Durga Prasad Paladugue6fd3bb2017-02-21 17:58:28 +0530532 int ret;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200533
Michal Simek482f5492018-10-05 08:55:16 +0200534#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
535 usb_ether_init();
536#endif
537
Michal Simekecfb6dc2016-04-22 14:28:54 +0200538 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
539 debug("Saved variables - Skipping\n");
540 return 0;
541 }
Michal Simek04b7e622015-01-15 10:01:51 +0100542
Michal Simek1ca66d72019-02-14 13:14:30 +0100543 ret = set_fdtfile();
544 if (ret)
545 return ret;
546
Siva Durga Prasad Paladugue6fd3bb2017-02-21 17:58:28 +0530547 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
548 if (ret)
549 return -EINVAL;
550
Michal Simek833e0c42016-10-25 11:43:02 +0200551 if (reg >> BOOT_MODE_ALT_SHIFT)
552 reg >>= BOOT_MODE_ALT_SHIFT;
553
Michal Simek04b7e622015-01-15 10:01:51 +0100554 bootmode = reg & BOOT_MODES_MASK;
555
Michal Simekc5d95232015-09-20 17:20:42 +0200556 puts("Bootmode: ");
Michal Simek04b7e622015-01-15 10:01:51 +0100557 switch (bootmode) {
Michal Simek12398ea2016-08-19 14:14:52 +0200558 case USB_MODE:
559 puts("USB_MODE\n");
560 mode = "usb";
Michal Simek43380352017-12-01 15:18:24 +0100561 env_set("modeboot", "usb_dfu_spl");
Michal Simek12398ea2016-08-19 14:14:52 +0200562 break;
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530563 case JTAG_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200564 puts("JTAG_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200565 mode = "pxe dhcp";
Michal Simek43380352017-12-01 15:18:24 +0100566 env_set("modeboot", "jtagboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530567 break;
568 case QSPI_MODE_24BIT:
569 case QSPI_MODE_32BIT:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200570 mode = "qspi0";
Michal Simekc5d95232015-09-20 17:20:42 +0200571 puts("QSPI_MODE\n");
Michal Simek43380352017-12-01 15:18:24 +0100572 env_set("modeboot", "qspiboot");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530573 break;
Michal Simek02d66cd2015-04-15 15:02:28 +0200574 case EMMC_MODE:
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200575 puts("EMMC_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200576 mode = "mmc0";
Michal Simek43380352017-12-01 15:18:24 +0100577 env_set("modeboot", "emmcboot");
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200578 break;
579 case SD_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200580 puts("SD_MODE\n");
Michal Simekf183a982018-04-25 11:20:43 +0200581 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530582 "mmc@ff160000", &dev) &&
583 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200584 "sdhci@ff160000", &dev)) {
585 puts("Boot from SD0 but without SD0 enabled!\n");
586 return -1;
587 }
588 debug("mmc0 device found at %p, seq %d\n", dev, dev->seq);
589
590 mode = "mmc";
591 bootseq = dev->seq;
Michal Simek43380352017-12-01 15:18:24 +0100592 env_set("modeboot", "sdboot");
Michal Simek04b7e622015-01-15 10:01:51 +0100593 break;
Siva Durga Prasad Paladugu29a77d22016-09-21 11:45:05 +0530594 case SD1_LSHFT_MODE:
595 puts("LVL_SHFT_");
596 /* fall through */
Michal Simek108e1842015-10-05 10:51:12 +0200597 case SD_MODE1:
Michal Simekc5d95232015-09-20 17:20:42 +0200598 puts("SD_MODE1\n");
Michal Simekf183a982018-04-25 11:20:43 +0200599 if (uclass_get_device_by_name(UCLASS_MMC,
Siva Durga Prasad Paladugue91778d2019-01-03 15:44:24 +0530600 "mmc@ff170000", &dev) &&
601 uclass_get_device_by_name(UCLASS_MMC,
Michal Simekf183a982018-04-25 11:20:43 +0200602 "sdhci@ff170000", &dev)) {
603 puts("Boot from SD1 but without SD1 enabled!\n");
604 return -1;
605 }
606 debug("mmc1 device found at %p, seq %d\n", dev, dev->seq);
607
608 mode = "mmc";
609 bootseq = dev->seq;
Michal Simek43380352017-12-01 15:18:24 +0100610 env_set("modeboot", "sdboot");
Michal Simek108e1842015-10-05 10:51:12 +0200611 break;
612 case NAND_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200613 puts("NAND_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200614 mode = "nand0";
Michal Simek43380352017-12-01 15:18:24 +0100615 env_set("modeboot", "nandboot");
Michal Simek108e1842015-10-05 10:51:12 +0200616 break;
Michal Simek04b7e622015-01-15 10:01:51 +0100617 default:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200618 mode = "";
Michal Simek04b7e622015-01-15 10:01:51 +0100619 printf("Invalid Boot Mode:0x%x\n", bootmode);
620 break;
621 }
622
Michal Simekf183a982018-04-25 11:20:43 +0200623 if (bootseq >= 0) {
624 bootseq_len = snprintf(NULL, 0, "%i", bootseq);
625 debug("Bootseq len: %x\n", bootseq_len);
626 }
627
Michal Simekecfb6dc2016-04-22 14:28:54 +0200628 /*
629 * One terminating char + one byte for space between mode
630 * and default boot_targets
631 */
Siva Durga Prasad Paladugu245c5562017-12-20 16:35:06 +0530632 env_targets = env_get("boot_targets");
Michal Simek7410b142018-04-25 11:10:34 +0200633 if (env_targets)
634 env_targets_len = strlen(env_targets);
635
Michal Simekf183a982018-04-25 11:20:43 +0200636 new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
637 bootseq_len);
Michal Simek089b84d2018-06-13 09:42:41 +0200638 if (!new_targets)
639 return -ENOMEM;
Michal Simek7410b142018-04-25 11:10:34 +0200640
Michal Simekf183a982018-04-25 11:20:43 +0200641 if (bootseq >= 0)
642 sprintf(new_targets, "%s%x %s", mode, bootseq,
643 env_targets ? env_targets : "");
644 else
645 sprintf(new_targets, "%s %s", mode,
646 env_targets ? env_targets : "");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200647
Simon Glass6a38e412017-08-03 12:22:09 -0600648 env_set("boot_targets", new_targets);
Michal Simekecfb6dc2016-04-22 14:28:54 +0200649
Michal Simek29b9b712018-05-17 14:06:06 +0200650 reset_reason();
651
Michal Simek04b7e622015-01-15 10:01:51 +0100652 return 0;
653}
Michal Simek342edfe2018-12-20 09:33:38 +0100654#endif
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530655
656int checkboard(void)
657{
Michal Simek47ce9362016-01-25 11:04:21 +0100658 puts("Board: Xilinx ZynqMP\n");
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530659 return 0;
660}