]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
84c7204b MS |
2 | /* |
3 | * (C) Copyright 2014 - 2015 Xilinx, Inc. | |
4 | * Michal Simek <[email protected]> | |
84c7204b MS |
5 | */ |
6 | ||
7 | #include <common.h> | |
09140113 | 8 | #include <command.h> |
62270f43 | 9 | #include <cpu_func.h> |
c0adba57 | 10 | #include <debug_uart.h> |
9fb625ce | 11 | #include <env.h> |
1025bd09 | 12 | #include <env_internal.h> |
5255932f | 13 | #include <init.h> |
f7ae49fc | 14 | #include <log.h> |
90526e9f | 15 | #include <net.h> |
679b994a | 16 | #include <sata.h> |
6fe6f135 MS |
17 | #include <ahci.h> |
18 | #include <scsi.h> | |
b72894f1 | 19 | #include <malloc.h> |
4490e013 | 20 | #include <wdt.h> |
0785dfd8 | 21 | #include <asm/arch/clk.h> |
84c7204b MS |
22 | #include <asm/arch/hardware.h> |
23 | #include <asm/arch/sys_proto.h> | |
2ad341ed | 24 | #include <asm/arch/psu_init_gpl.h> |
90526e9f | 25 | #include <asm/cache.h> |
401d1c4f | 26 | #include <asm/global_data.h> |
84c7204b | 27 | #include <asm/io.h> |
25a5818f | 28 | #include <asm/ptrace.h> |
2882b39d | 29 | #include <dm/device.h> |
4490e013 | 30 | #include <dm/uclass.h> |
16fa00a7 SDPP |
31 | #include <usb.h> |
32 | #include <dwc3-uboot.h> | |
47e60cbd | 33 | #include <zynqmppl.h> |
009ab7b9 | 34 | #include <zynqmp_firmware.h> |
9feff385 | 35 | #include <g_dnl.h> |
cd93d625 | 36 | #include <linux/bitops.h> |
c05ed00a SG |
37 | #include <linux/delay.h> |
38 | #include <linux/sizes.h> | |
80fdef12 | 39 | #include "../common/board.h" |
84c7204b | 40 | |
c28a9cfa LC |
41 | #include "pm_cfg_obj.h" |
42 | ||
fa793165 | 43 | #define ZYNQMP_VERSION_SIZE 7 |
2fbdbee7 MS |
44 | #define EFUSE_VCU_DIS_MASK 0x100 |
45 | #define EFUSE_VCU_DIS_SHIFT 8 | |
46 | #define EFUSE_GPU_DIS_MASK 0x20 | |
47 | #define EFUSE_GPU_DIS_SHIFT 5 | |
48 | #define IDCODE2_PL_INIT_MASK 0x200 | |
49 | #define IDCODE2_PL_INIT_SHIFT 9 | |
fa793165 | 50 | |
84c7204b MS |
51 | DECLARE_GLOBAL_DATA_PTR; |
52 | ||
29bd8ada | 53 | #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) |
47e60cbd MS |
54 | static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; |
55 | ||
fa793165 IE |
56 | enum { |
57 | ZYNQMP_VARIANT_EG = BIT(0U), | |
58 | ZYNQMP_VARIANT_EV = BIT(1U), | |
59 | ZYNQMP_VARIANT_CG = BIT(2U), | |
60 | ZYNQMP_VARIANT_DR = BIT(3U), | |
61 | }; | |
62 | ||
47e60cbd | 63 | static const struct { |
8ebdf9ef | 64 | u32 id; |
fa793165 IE |
65 | u8 device; |
66 | u8 variants; | |
47e60cbd MS |
67 | } zynqmp_devices[] = { |
68 | { | |
fa793165 IE |
69 | .id = 0x04711093, |
70 | .device = 2, | |
71 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, | |
494fffe7 | 72 | }, |
47e60cbd | 73 | { |
fa793165 IE |
74 | .id = 0x04710093, |
75 | .device = 3, | |
76 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, | |
47e60cbd | 77 | }, |
494fffe7 | 78 | { |
fa793165 IE |
79 | .id = 0x04721093, |
80 | .device = 4, | |
81 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG | | |
82 | ZYNQMP_VARIANT_EV, | |
494fffe7 MS |
83 | }, |
84 | { | |
fa793165 IE |
85 | .id = 0x04720093, |
86 | .device = 5, | |
87 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG | | |
88 | ZYNQMP_VARIANT_EV, | |
494fffe7 | 89 | }, |
47e60cbd | 90 | { |
fa793165 IE |
91 | .id = 0x04739093, |
92 | .device = 6, | |
93 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, | |
47e60cbd | 94 | }, |
494fffe7 | 95 | { |
fa793165 IE |
96 | .id = 0x04730093, |
97 | .device = 7, | |
98 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG | | |
99 | ZYNQMP_VARIANT_EV, | |
494fffe7 MS |
100 | }, |
101 | { | |
fa793165 IE |
102 | .id = 0x04738093, |
103 | .device = 9, | |
bbe086a9 | 104 | .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, |
494fffe7 | 105 | }, |
47e60cbd | 106 | { |
fa793165 IE |
107 | .id = 0x04740093, |
108 | .device = 11, | |
109 | .variants = ZYNQMP_VARIANT_EG, | |
47e60cbd | 110 | }, |
494fffe7 | 111 | { |
fa793165 IE |
112 | .id = 0x04750093, |
113 | .device = 15, | |
114 | .variants = ZYNQMP_VARIANT_EG, | |
494fffe7 MS |
115 | }, |
116 | { | |
fa793165 IE |
117 | .id = 0x04759093, |
118 | .device = 17, | |
119 | .variants = ZYNQMP_VARIANT_EG, | |
494fffe7 | 120 | }, |
47e60cbd | 121 | { |
fa793165 IE |
122 | .id = 0x04758093, |
123 | .device = 19, | |
124 | .variants = ZYNQMP_VARIANT_EG, | |
47e60cbd | 125 | }, |
494fffe7 | 126 | { |
fa793165 IE |
127 | .id = 0x047E1093, |
128 | .device = 21, | |
129 | .variants = ZYNQMP_VARIANT_DR, | |
494fffe7 | 130 | }, |
47e60cbd | 131 | { |
fa793165 IE |
132 | .id = 0x047E3093, |
133 | .device = 23, | |
134 | .variants = ZYNQMP_VARIANT_DR, | |
47e60cbd | 135 | }, |
494fffe7 | 136 | { |
fa793165 IE |
137 | .id = 0x047E5093, |
138 | .device = 25, | |
139 | .variants = ZYNQMP_VARIANT_DR, | |
494fffe7 | 140 | }, |
47e60cbd | 141 | { |
fa793165 IE |
142 | .id = 0x047E4093, |
143 | .device = 27, | |
144 | .variants = ZYNQMP_VARIANT_DR, | |
47e60cbd MS |
145 | }, |
146 | { | |
fa793165 IE |
147 | .id = 0x047E0093, |
148 | .device = 28, | |
149 | .variants = ZYNQMP_VARIANT_DR, | |
47e60cbd MS |
150 | }, |
151 | { | |
fa793165 IE |
152 | .id = 0x047E2093, |
153 | .device = 29, | |
154 | .variants = ZYNQMP_VARIANT_DR, | |
47e60cbd | 155 | }, |
b030fedf | 156 | { |
fa793165 IE |
157 | .id = 0x047E6093, |
158 | .device = 39, | |
159 | .variants = ZYNQMP_VARIANT_DR, | |
b030fedf MS |
160 | }, |
161 | { | |
e17c5ec8 MS |
162 | .id = 0x047FD093, |
163 | .device = 43, | |
164 | .variants = ZYNQMP_VARIANT_DR, | |
b030fedf MS |
165 | }, |
166 | { | |
e17c5ec8 MS |
167 | .id = 0x047F8093, |
168 | .device = 46, | |
169 | .variants = ZYNQMP_VARIANT_DR, | |
b030fedf MS |
170 | }, |
171 | { | |
e17c5ec8 MS |
172 | .id = 0x047FF093, |
173 | .device = 47, | |
174 | .variants = ZYNQMP_VARIANT_DR, | |
b030fedf MS |
175 | }, |
176 | { | |
fa793165 IE |
177 | .id = 0x047FB093, |
178 | .device = 48, | |
179 | .variants = ZYNQMP_VARIANT_DR, | |
b030fedf MS |
180 | }, |
181 | { | |
fa793165 IE |
182 | .id = 0x047FE093, |
183 | .device = 49, | |
184 | .variants = ZYNQMP_VARIANT_DR, | |
134b0c8d | 185 | }, |
47e60cbd MS |
186 | }; |
187 | ||
47e60cbd MS |
188 | static char *zynqmp_get_silicon_idcode_name(void) |
189 | { | |
fa793165 IE |
190 | u32 i; |
191 | u32 idcode, idcode2; | |
ced4d466 | 192 | char name[ZYNQMP_VERSION_SIZE]; |
050f10f1 | 193 | u32 ret_payload[PAYLOAD_ARG_CNT]; |
0d76b71d | 194 | int ret; |
050f10f1 | 195 | |
d026aa1d MS |
196 | ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); |
197 | if (ret) { | |
198 | debug("%s: Getting chipid failed\n", __func__); | |
199 | return "unknown"; | |
200 | } | |
050f10f1 IE |
201 | |
202 | /* | |
203 | * Firmware returns: | |
204 | * payload[0][31:0] = status of the operation | |
205 | * payload[1]] = IDCODE | |
206 | * payload[2][19:0] = Version | |
207 | * payload[2][28:20] = EXTENDED_IDCODE | |
208 | * payload[2][29] = PL_INIT | |
209 | */ | |
210 | ||
fa793165 IE |
211 | idcode = ret_payload[1]; |
212 | idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT; | |
16df2f1e | 213 | debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode, |
fa793165 | 214 | idcode2); |
494fffe7 | 215 | |
47e60cbd | 216 | for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { |
fa793165 IE |
217 | if (zynqmp_devices[i].id == (idcode & 0x0FFFFFFF)) |
218 | break; | |
47e60cbd | 219 | } |
83bf2ff0 SDPP |
220 | |
221 | if (i >= ARRAY_SIZE(zynqmp_devices)) | |
222 | return "unknown"; | |
223 | ||
fa793165 | 224 | /* Add device prefix to the name */ |
0d76b71d MS |
225 | ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d", |
226 | zynqmp_devices[i].device); | |
07499daf | 227 | if (ret < 0) |
0d76b71d | 228 | return "unknown"; |
83bf2ff0 | 229 | |
fa793165 IE |
230 | if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) { |
231 | /* Devices with EV variant might be EG/CG/EV family */ | |
232 | if (idcode2 & IDCODE2_PL_INIT_MASK) { | |
233 | u32 family = ((idcode2 & EFUSE_VCU_DIS_MASK) >> | |
234 | EFUSE_VCU_DIS_SHIFT) << 1 | | |
235 | ((idcode2 & EFUSE_GPU_DIS_MASK) >> | |
236 | EFUSE_GPU_DIS_SHIFT); | |
83bf2ff0 | 237 | |
fa793165 IE |
238 | /* |
239 | * Get family name based on extended idcode values as | |
240 | * determined on UG1087, EXTENDED_IDCODE register | |
241 | * description | |
242 | */ | |
243 | switch (family) { | |
244 | case 0x00: | |
245 | strncat(name, "ev", 2); | |
246 | break; | |
247 | case 0x10: | |
248 | strncat(name, "eg", 2); | |
249 | break; | |
250 | case 0x11: | |
251 | strncat(name, "cg", 2); | |
252 | break; | |
253 | default: | |
254 | /* Do not append family name*/ | |
255 | break; | |
256 | } | |
257 | } else { | |
258 | /* | |
259 | * When PL powered down the VCU Disable efuse cannot be | |
260 | * read. So, ignore the bit and just findout if it is CG | |
261 | * or EG/EV variant. | |
262 | */ | |
263 | strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" : | |
264 | "e", 2); | |
5473f245 | 265 | } |
fa793165 IE |
266 | } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_CG) { |
267 | /* Devices with CG variant might be EG or CG family */ | |
268 | strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" : "eg", 2); | |
269 | } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EG) { | |
270 | strncat(name, "eg", 2); | |
271 | } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_DR) { | |
272 | strncat(name, "dr", 2); | |
273 | } else { | |
274 | debug("Variant not identified\n"); | |
5473f245 SDPP |
275 | } |
276 | ||
ced4d466 | 277 | return strdup(name); |
47e60cbd MS |
278 | } |
279 | #endif | |
280 | ||
fb4000e8 MS |
281 | int board_early_init_f(void) |
282 | { | |
88f05a92 | 283 | #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) |
c0adba57 MS |
284 | int ret; |
285 | ||
f32e79f1 | 286 | ret = psu_init(); |
c0adba57 MS |
287 | if (ret) |
288 | return ret; | |
f8451f14 MS |
289 | |
290 | /* Delay is required for clocks to be propagated */ | |
291 | udelay(1000000); | |
55de0929 MS |
292 | #endif |
293 | ||
c0adba57 MS |
294 | #ifdef CONFIG_DEBUG_UART |
295 | /* Uart debug for sure */ | |
296 | debug_uart_init(); | |
297 | puts("Debug uart enabled\n"); /* or printch() */ | |
298 | #endif | |
299 | ||
300 | return 0; | |
fb4000e8 MS |
301 | } |
302 | ||
c5143013 MS |
303 | static int multi_boot(void) |
304 | { | |
305 | u32 multiboot; | |
306 | ||
307 | multiboot = readl(&csu_base->multi_boot); | |
308 | ||
3ccea69f | 309 | printf("Multiboot:\t%d\n", multiboot); |
c5143013 MS |
310 | |
311 | return 0; | |
312 | } | |
313 | ||
dfbe492e ML |
314 | #define PS_SYSMON_ANALOG_BUS_VAL 0x3210 |
315 | #define PS_SYSMON_ANALOG_BUS_REG 0xFFA50914 | |
316 | ||
84c7204b MS |
317 | int board_init(void) |
318 | { | |
66ef85da | 319 | #if defined(CONFIG_ZYNQMP_FIRMWARE) |
325a22dc IE |
320 | struct udevice *dev; |
321 | ||
322 | uclass_get_device_by_name(UCLASS_FIRMWARE, "zynqmp-power", &dev); | |
323 | if (!dev) | |
324 | panic("PMU Firmware device not found - Enable it"); | |
66ef85da | 325 | #endif |
325a22dc | 326 | |
c28a9cfa LC |
327 | #if defined(CONFIG_SPL_BUILD) |
328 | /* Check *at build time* if the filename is an non-empty string */ | |
329 | if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1) | |
330 | zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj, | |
331 | zynqmp_pm_cfg_obj_size); | |
d61728c8 MS |
332 | #else |
333 | if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) | |
334 | xilinx_read_eeprom(); | |
c28a9cfa LC |
335 | #endif |
336 | ||
a0736efb MS |
337 | printf("EL Level:\tEL%d\n", current_el()); |
338 | ||
dfbe492e ML |
339 | /* Bug in ROM sets wrong value in this register */ |
340 | writel(PS_SYSMON_ANALOG_BUS_VAL, PS_SYSMON_ANALOG_BUS_REG); | |
341 | ||
29bd8ada | 342 | #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) |
4b2ad7b1 IE |
343 | zynqmppl.name = zynqmp_get_silicon_idcode_name(); |
344 | printf("Chip ID:\t%s\n", zynqmppl.name); | |
345 | fpga_init(); | |
346 | fpga_add(fpga_xilinx, &zynqmppl); | |
47e60cbd MS |
347 | #endif |
348 | ||
c5143013 MS |
349 | if (current_el() == 3) |
350 | multi_boot(); | |
351 | ||
84c7204b MS |
352 | return 0; |
353 | } | |
354 | ||
355 | int board_early_init_r(void) | |
356 | { | |
357 | u32 val; | |
358 | ||
ec60a279 SDPP |
359 | if (current_el() != 3) |
360 | return 0; | |
361 | ||
90a35db4 MS |
362 | val = readl(&crlapb_base->timestamp_ref_ctrl); |
363 | val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; | |
364 | ||
ec60a279 | 365 | if (!val) { |
0785dfd8 MS |
366 | val = readl(&crlapb_base->timestamp_ref_ctrl); |
367 | val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; | |
368 | writel(val, &crlapb_base->timestamp_ref_ctrl); | |
84c7204b | 369 | |
0785dfd8 MS |
370 | /* Program freq register in System counter */ |
371 | writel(zynqmp_get_system_timer_freq(), | |
372 | &iou_scntr_secure->base_frequency_id_register); | |
373 | /* And enable system counter */ | |
374 | writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, | |
375 | &iou_scntr_secure->counter_control_register); | |
376 | } | |
84c7204b MS |
377 | return 0; |
378 | } | |
379 | ||
51916864 | 380 | unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, |
09140113 | 381 | char *const argv[]) |
51916864 NJ |
382 | { |
383 | int ret = 0; | |
384 | ||
385 | if (current_el() > 1) { | |
386 | smp_kick_all_cpus(); | |
387 | dcache_disable(); | |
388 | armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, | |
389 | ES_TO_AARCH64); | |
390 | } else { | |
391 | printf("FAIL: current EL is not above EL1\n"); | |
392 | ret = EINVAL; | |
393 | } | |
394 | return ret; | |
395 | } | |
396 | ||
8d59d7f6 | 397 | #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) |
76b00aca | 398 | int dram_init_banksize(void) |
361a8799 | 399 | { |
0678941a NJ |
400 | int ret; |
401 | ||
402 | ret = fdtdec_setup_memory_banksize(); | |
403 | if (ret) | |
404 | return ret; | |
405 | ||
406 | mem_map_fill(); | |
407 | ||
408 | return 0; | |
8a5db0ab | 409 | } |
8d59d7f6 | 410 | |
361a8799 | 411 | int dram_init(void) |
8a5db0ab | 412 | { |
12308b12 | 413 | if (fdtdec_setup_mem_size_base() != 0) |
950f86ca | 414 | return -EINVAL; |
8a5db0ab | 415 | |
361a8799 | 416 | return 0; |
8d59d7f6 MS |
417 | } |
418 | #else | |
0678941a NJ |
419 | int dram_init_banksize(void) |
420 | { | |
0678941a NJ |
421 | gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; |
422 | gd->bd->bi_dram[0].size = get_effective_memsize(); | |
0678941a NJ |
423 | |
424 | mem_map_fill(); | |
425 | ||
426 | return 0; | |
427 | } | |
428 | ||
84c7204b MS |
429 | int dram_init(void) |
430 | { | |
61dc92a2 MS |
431 | gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, |
432 | CONFIG_SYS_SDRAM_SIZE); | |
84c7204b MS |
433 | |
434 | return 0; | |
435 | } | |
8d59d7f6 | 436 | #endif |
84c7204b | 437 | |
84c7204b MS |
438 | void reset_cpu(ulong addr) |
439 | { | |
440 | } | |
441 | ||
4d9bc795 MS |
442 | static u8 __maybe_unused zynqmp_get_bootmode(void) |
443 | { | |
444 | u8 bootmode; | |
445 | u32 reg = 0; | |
446 | int ret; | |
447 | ||
448 | ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); | |
449 | if (ret) | |
450 | return -EINVAL; | |
451 | ||
452 | if (reg >> BOOT_MODE_ALT_SHIFT) | |
453 | reg >>= BOOT_MODE_ALT_SHIFT; | |
454 | ||
455 | bootmode = reg & BOOT_MODES_MASK; | |
456 | ||
457 | return bootmode; | |
458 | } | |
459 | ||
0bf3f9cb | 460 | #if defined(CONFIG_BOARD_LATE_INIT) |
d348beaa MS |
461 | static const struct { |
462 | u32 bit; | |
463 | const char *name; | |
464 | } reset_reasons[] = { | |
465 | { RESET_REASON_DEBUG_SYS, "DEBUG" }, | |
466 | { RESET_REASON_SOFT, "SOFT" }, | |
467 | { RESET_REASON_SRST, "SRST" }, | |
468 | { RESET_REASON_PSONLY, "PS-ONLY" }, | |
469 | { RESET_REASON_PMU, "PMU" }, | |
470 | { RESET_REASON_INTERNAL, "INTERNAL" }, | |
471 | { RESET_REASON_EXTERNAL, "EXTERNAL" }, | |
472 | {} | |
473 | }; | |
474 | ||
be52372f | 475 | static int reset_reason(void) |
d348beaa | 476 | { |
be52372f KR |
477 | u32 reg; |
478 | int i, ret; | |
d348beaa MS |
479 | const char *reason = NULL; |
480 | ||
be52372f KR |
481 | ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, ®); |
482 | if (ret) | |
483 | return -EINVAL; | |
d348beaa MS |
484 | |
485 | puts("Reset reason:\t"); | |
486 | ||
487 | for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { | |
be52372f | 488 | if (reg & reset_reasons[i].bit) { |
d348beaa MS |
489 | reason = reset_reasons[i].name; |
490 | printf("%s ", reset_reasons[i].name); | |
491 | break; | |
492 | } | |
493 | } | |
494 | ||
495 | puts("\n"); | |
496 | ||
497 | env_set("reset_reason", reason); | |
498 | ||
3d037524 | 499 | ret = zynqmp_mmio_write((ulong)&crlapb_base->reset_reason, ~0, ~0); |
be52372f KR |
500 | if (ret) |
501 | return -EINVAL; | |
d348beaa MS |
502 | |
503 | return ret; | |
504 | } | |
505 | ||
91d7e0c4 MS |
506 | static int set_fdtfile(void) |
507 | { | |
508 | char *compatible, *fdtfile; | |
509 | const char *suffix = ".dtb"; | |
510 | const char *vendor = "xilinx/"; | |
1b208d59 | 511 | int fdt_compat_len; |
91d7e0c4 MS |
512 | |
513 | if (env_get("fdtfile")) | |
514 | return 0; | |
515 | ||
1b208d59 IL |
516 | compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", |
517 | &fdt_compat_len); | |
518 | if (compatible && fdt_compat_len) { | |
519 | char *name; | |
520 | ||
91d7e0c4 MS |
521 | debug("Compatible: %s\n", compatible); |
522 | ||
1b208d59 IL |
523 | name = strchr(compatible, ','); |
524 | if (!name) | |
525 | return -EINVAL; | |
526 | ||
527 | name++; | |
91d7e0c4 | 528 | |
1b208d59 | 529 | fdtfile = calloc(1, strlen(vendor) + strlen(name) + |
91d7e0c4 MS |
530 | strlen(suffix) + 1); |
531 | if (!fdtfile) | |
532 | return -ENOMEM; | |
533 | ||
1b208d59 | 534 | sprintf(fdtfile, "%s%s%s", vendor, name, suffix); |
91d7e0c4 MS |
535 | |
536 | env_set("fdtfile", fdtfile); | |
537 | free(fdtfile); | |
538 | } | |
539 | ||
540 | return 0; | |
541 | } | |
542 | ||
51f6c52e MS |
543 | int board_late_init(void) |
544 | { | |
84c7204b | 545 | u8 bootmode; |
2882b39d MS |
546 | struct udevice *dev; |
547 | int bootseq = -1; | |
548 | int bootseq_len = 0; | |
0478b0b9 | 549 | int env_targets_len = 0; |
b72894f1 MS |
550 | const char *mode; |
551 | char *new_targets; | |
01c42d3d | 552 | char *env_targets; |
d1db89f4 | 553 | int ret; |
b72894f1 | 554 | |
e615f39e MS |
555 | #if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD) |
556 | usb_ether_init(); | |
557 | #endif | |
558 | ||
b72894f1 MS |
559 | if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { |
560 | debug("Saved variables - Skipping\n"); | |
561 | return 0; | |
562 | } | |
84c7204b | 563 | |
62b96262 MS |
564 | if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG)) |
565 | return 0; | |
566 | ||
91d7e0c4 MS |
567 | ret = set_fdtfile(); |
568 | if (ret) | |
569 | return ret; | |
570 | ||
51f6c52e | 571 | bootmode = zynqmp_get_bootmode(); |
84c7204b | 572 | |
fb90917c | 573 | puts("Bootmode: "); |
84c7204b | 574 | switch (bootmode) { |
d58fc12e MS |
575 | case USB_MODE: |
576 | puts("USB_MODE\n"); | |
577 | mode = "usb"; | |
07656ba5 | 578 | env_set("modeboot", "usb_dfu_spl"); |
d58fc12e | 579 | break; |
0a5bcc8c | 580 | case JTAG_MODE: |
fb90917c | 581 | puts("JTAG_MODE\n"); |
5d2274c0 | 582 | mode = "jtag pxe dhcp"; |
07656ba5 | 583 | env_set("modeboot", "jtagboot"); |
0a5bcc8c SDPP |
584 | break; |
585 | case QSPI_MODE_24BIT: | |
586 | case QSPI_MODE_32BIT: | |
b72894f1 | 587 | mode = "qspi0"; |
fb90917c | 588 | puts("QSPI_MODE\n"); |
07656ba5 | 589 | env_set("modeboot", "qspiboot"); |
0a5bcc8c | 590 | break; |
39c56f55 | 591 | case EMMC_MODE: |
78678fee | 592 | puts("EMMC_MODE\n"); |
18be60b8 KR |
593 | if (uclass_get_device_by_name(UCLASS_MMC, |
594 | "mmc@ff160000", &dev) && | |
595 | uclass_get_device_by_name(UCLASS_MMC, | |
596 | "sdhci@ff160000", &dev)) { | |
597 | puts("Boot from EMMC but without SD0 enabled!\n"); | |
598 | return -1; | |
599 | } | |
8b85dfc6 | 600 | debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev)); |
18be60b8 KR |
601 | |
602 | mode = "mmc"; | |
8b85dfc6 | 603 | bootseq = dev_seq(dev); |
78678fee MS |
604 | break; |
605 | case SD_MODE: | |
fb90917c | 606 | puts("SD_MODE\n"); |
2882b39d | 607 | if (uclass_get_device_by_name(UCLASS_MMC, |
e7c9de66 SDPP |
608 | "mmc@ff160000", &dev) && |
609 | uclass_get_device_by_name(UCLASS_MMC, | |
2882b39d MS |
610 | "sdhci@ff160000", &dev)) { |
611 | puts("Boot from SD0 but without SD0 enabled!\n"); | |
612 | return -1; | |
613 | } | |
8b85dfc6 | 614 | debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev)); |
2882b39d MS |
615 | |
616 | mode = "mmc"; | |
8b85dfc6 | 617 | bootseq = dev_seq(dev); |
07656ba5 | 618 | env_set("modeboot", "sdboot"); |
84c7204b | 619 | break; |
e1992276 SDPP |
620 | case SD1_LSHFT_MODE: |
621 | puts("LVL_SHFT_"); | |
622 | /* fall through */ | |
af813acd | 623 | case SD_MODE1: |
fb90917c | 624 | puts("SD_MODE1\n"); |
2882b39d | 625 | if (uclass_get_device_by_name(UCLASS_MMC, |
e7c9de66 SDPP |
626 | "mmc@ff170000", &dev) && |
627 | uclass_get_device_by_name(UCLASS_MMC, | |
2882b39d MS |
628 | "sdhci@ff170000", &dev)) { |
629 | puts("Boot from SD1 but without SD1 enabled!\n"); | |
630 | return -1; | |
631 | } | |
8b85dfc6 | 632 | debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev)); |
2882b39d MS |
633 | |
634 | mode = "mmc"; | |
8b85dfc6 | 635 | bootseq = dev_seq(dev); |
07656ba5 | 636 | env_set("modeboot", "sdboot"); |
af813acd MS |
637 | break; |
638 | case NAND_MODE: | |
fb90917c | 639 | puts("NAND_MODE\n"); |
b72894f1 | 640 | mode = "nand0"; |
07656ba5 | 641 | env_set("modeboot", "nandboot"); |
af813acd | 642 | break; |
84c7204b | 643 | default: |
b72894f1 | 644 | mode = ""; |
84c7204b MS |
645 | printf("Invalid Boot Mode:0x%x\n", bootmode); |
646 | break; | |
647 | } | |
648 | ||
2882b39d MS |
649 | if (bootseq >= 0) { |
650 | bootseq_len = snprintf(NULL, 0, "%i", bootseq); | |
651 | debug("Bootseq len: %x\n", bootseq_len); | |
2784befb | 652 | env_set_hex("bootseq", bootseq); |
2882b39d MS |
653 | } |
654 | ||
b72894f1 MS |
655 | /* |
656 | * One terminating char + one byte for space between mode | |
657 | * and default boot_targets | |
658 | */ | |
01c42d3d | 659 | env_targets = env_get("boot_targets"); |
0478b0b9 MS |
660 | if (env_targets) |
661 | env_targets_len = strlen(env_targets); | |
662 | ||
2882b39d MS |
663 | new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + |
664 | bootseq_len); | |
1e3e68f1 MS |
665 | if (!new_targets) |
666 | return -ENOMEM; | |
0478b0b9 | 667 | |
2882b39d MS |
668 | if (bootseq >= 0) |
669 | sprintf(new_targets, "%s%x %s", mode, bootseq, | |
670 | env_targets ? env_targets : ""); | |
671 | else | |
672 | sprintf(new_targets, "%s %s", mode, | |
673 | env_targets ? env_targets : ""); | |
b72894f1 | 674 | |
382bee57 | 675 | env_set("boot_targets", new_targets); |
b72894f1 | 676 | |
d348beaa MS |
677 | reset_reason(); |
678 | ||
80fdef12 | 679 | return board_late_init_xilinx(); |
84c7204b | 680 | } |
0bf3f9cb | 681 | #endif |
84696ff5 SDPP |
682 | |
683 | int checkboard(void) | |
684 | { | |
5af08556 | 685 | puts("Board: Xilinx ZynqMP\n"); |
84696ff5 SDPP |
686 | return 0; |
687 | } | |
1025bd09 MS |
688 | |
689 | enum env_location env_get_location(enum env_operation op, int prio) | |
690 | { | |
691 | u32 bootmode = zynqmp_get_bootmode(); | |
692 | ||
693 | if (prio) | |
694 | return ENVL_UNKNOWN; | |
695 | ||
696 | switch (bootmode) { | |
697 | case EMMC_MODE: | |
698 | case SD_MODE: | |
699 | case SD1_LSHFT_MODE: | |
700 | case SD_MODE1: | |
701 | if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT)) | |
702 | return ENVL_FAT; | |
703 | if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)) | |
704 | return ENVL_EXT4; | |
705 | return ENVL_UNKNOWN; | |
706 | case NAND_MODE: | |
707 | if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND)) | |
708 | return ENVL_NAND; | |
709 | if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI)) | |
710 | return ENVL_UBI; | |
711 | return ENVL_UNKNOWN; | |
712 | case QSPI_MODE_24BIT: | |
713 | case QSPI_MODE_32BIT: | |
714 | if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) | |
715 | return ENVL_SPI_FLASH; | |
716 | return ENVL_UNKNOWN; | |
717 | case JTAG_MODE: | |
718 | default: | |
719 | return ENVL_NOWHERE; | |
720 | } | |
721 | } |