]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
84c7204b MS |
2 | /* |
3 | * (C) Copyright 2014 - 2015 Xilinx, Inc. | |
174d7284 | 4 | * Michal Simek <michal.simek@amd.com> |
84c7204b MS |
5 | */ |
6 | ||
d678a59d | 7 | #include <common.h> |
09140113 | 8 | #include <command.h> |
62270f43 | 9 | #include <cpu_func.h> |
c0adba57 | 10 | #include <debug_uart.h> |
b86f43de | 11 | #include <dfu.h> |
9fb625ce | 12 | #include <env.h> |
1025bd09 | 13 | #include <env_internal.h> |
5255932f | 14 | #include <init.h> |
f7ae49fc | 15 | #include <log.h> |
90526e9f | 16 | #include <net.h> |
679b994a | 17 | #include <sata.h> |
6fe6f135 MS |
18 | #include <ahci.h> |
19 | #include <scsi.h> | |
a1e618a1 | 20 | #include <soc.h> |
db23e67b | 21 | #include <spl.h> |
b72894f1 | 22 | #include <malloc.h> |
b86f43de | 23 | #include <memalign.h> |
4490e013 | 24 | #include <wdt.h> |
0785dfd8 | 25 | #include <asm/arch/clk.h> |
84c7204b MS |
26 | #include <asm/arch/hardware.h> |
27 | #include <asm/arch/sys_proto.h> | |
2ad341ed | 28 | #include <asm/arch/psu_init_gpl.h> |
90526e9f | 29 | #include <asm/cache.h> |
401d1c4f | 30 | #include <asm/global_data.h> |
84c7204b | 31 | #include <asm/io.h> |
25a5818f | 32 | #include <asm/ptrace.h> |
2882b39d | 33 | #include <dm/device.h> |
4490e013 | 34 | #include <dm/uclass.h> |
16fa00a7 SDPP |
35 | #include <usb.h> |
36 | #include <dwc3-uboot.h> | |
47e60cbd | 37 | #include <zynqmppl.h> |
009ab7b9 | 38 | #include <zynqmp_firmware.h> |
9feff385 | 39 | #include <g_dnl.h> |
cd93d625 | 40 | #include <linux/bitops.h> |
c05ed00a SG |
41 | #include <linux/delay.h> |
42 | #include <linux/sizes.h> | |
80fdef12 | 43 | #include "../common/board.h" |
84c7204b | 44 | |
c28a9cfa LC |
45 | #include "pm_cfg_obj.h" |
46 | ||
84c7204b MS |
47 | DECLARE_GLOBAL_DATA_PTR; |
48 | ||
29bd8ada | 49 | #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) |
d7fcbfc1 OS |
50 | static xilinx_desc zynqmppl = { |
51 | xilinx_zynqmp, csu_dma, 1, &zynqmp_op, 0, &zynqmp_op, NULL, | |
52 | ZYNQMP_FPGA_FLAGS | |
53 | }; | |
47e60cbd MS |
54 | #endif |
55 | ||
11381fba | 56 | int __maybe_unused psu_uboot_init(void) |
fb4000e8 | 57 | { |
c0adba57 MS |
58 | int ret; |
59 | ||
f32e79f1 | 60 | ret = psu_init(); |
c0adba57 MS |
61 | if (ret) |
62 | return ret; | |
f8451f14 | 63 | |
3414712b AF |
64 | /* |
65 | * PS_SYSMON_ANALOG_BUS register determines mapping between SysMon | |
66 | * supply sense channel to SysMon supply registers inside the IP. | |
67 | * This register must be programmed to complete SysMon IP | |
68 | * configuration. The default register configuration after | |
69 | * power-up is incorrect. Hence, fix this by writing the | |
70 | * correct value - 0x3210. | |
71 | */ | |
72 | writel(ZYNQMP_PS_SYSMON_ANALOG_BUS_VAL, | |
73 | ZYNQMP_AMS_PS_SYSMON_ANALOG_BUS); | |
74 | ||
f8451f14 MS |
75 | /* Delay is required for clocks to be propagated */ |
76 | udelay(1000000); | |
11381fba MS |
77 | |
78 | return 0; | |
79 | } | |
55de0929 | 80 | |
11381fba MS |
81 | #if !defined(CONFIG_SPL_BUILD) |
82 | # if defined(CONFIG_DEBUG_UART_BOARD_INIT) | |
83 | void board_debug_uart_init(void) | |
84 | { | |
85 | # if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) | |
86 | psu_uboot_init(); | |
87 | # endif | |
88 | } | |
89 | # endif | |
c0adba57 | 90 | |
11381fba MS |
91 | # if defined(CONFIG_BOARD_EARLY_INIT_F) |
92 | int board_early_init_f(void) | |
93 | { | |
94 | int ret = 0; | |
95 | # if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) && !defined(CONFIG_DEBUG_UART_BOARD_INIT) | |
96 | ret = psu_uboot_init(); | |
97 | # endif | |
98 | return ret; | |
fb4000e8 | 99 | } |
11381fba | 100 | # endif |
83d2941f | 101 | #endif |
fb4000e8 | 102 | |
c5143013 MS |
103 | static int multi_boot(void) |
104 | { | |
3d238435 MS |
105 | u32 multiboot = 0; |
106 | int ret; | |
c5143013 | 107 | |
3d238435 MS |
108 | ret = zynqmp_mmio_read((ulong)&csu_base->multi_boot, &multiboot); |
109 | if (ret) | |
110 | return -EINVAL; | |
c5143013 | 111 | |
e49f2a7f | 112 | return multiboot; |
c5143013 MS |
113 | } |
114 | ||
398a74ae JRO |
115 | #if defined(CONFIG_SPL_BUILD) |
116 | static void restore_jtag(void) | |
117 | { | |
118 | if (current_el() != 3) | |
119 | return; | |
120 | ||
121 | writel(CSU_JTAG_SEC_GATE_DISABLE, &csu_base->jtag_sec); | |
122 | writel(CSU_JTAG_DAP_ENABLE_DEBUG, &csu_base->jtag_dap_cfg); | |
123 | writel(CSU_JTAG_CHAIN_WR_SETUP, &csu_base->jtag_chain_status_wr); | |
124 | writel(CRLAPB_DBG_LPD_CTRL_SETUP_CLK, &crlapb_base->dbg_lpd_ctrl); | |
125 | writel(CRLAPB_RST_LPD_DBG_RESET, &crlapb_base->rst_lpd_dbg); | |
126 | writel(CSU_PCAP_PROG_RELEASE_PL, &csu_base->pcap_prog); | |
127 | } | |
128 | #endif | |
129 | ||
25a91f30 JRO |
130 | static void print_secure_boot(void) |
131 | { | |
132 | u32 status = 0; | |
133 | ||
134 | if (zynqmp_mmio_read((ulong)&csu_base->status, &status)) | |
135 | return; | |
136 | ||
137 | printf("Secure Boot:\t%sauthenticated, %sencrypted\n", | |
138 | status & ZYNQMP_CSU_STATUS_AUTHENTICATED ? "" : "not ", | |
139 | status & ZYNQMP_CSU_STATUS_ENCRYPTED ? "" : "not "); | |
140 | } | |
141 | ||
84c7204b MS |
142 | int board_init(void) |
143 | { | |
a1e618a1 SH |
144 | #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) |
145 | struct udevice *soc; | |
146 | char name[SOC_MAX_STR_SIZE]; | |
147 | int ret; | |
148 | #endif | |
0b33770b MS |
149 | |
150 | #if defined(CONFIG_SPL_BUILD) | |
151 | /* Check *at build time* if the filename is an non-empty string */ | |
152 | if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1) | |
153 | zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj, | |
154 | zynqmp_pm_cfg_obj_size); | |
155 | #endif | |
156 | ||
66ef85da | 157 | #if defined(CONFIG_ZYNQMP_FIRMWARE) |
325a22dc IE |
158 | struct udevice *dev; |
159 | ||
a93e09f0 MS |
160 | uclass_get_device_by_name(UCLASS_FIRMWARE, "power-management", &dev); |
161 | if (!dev) { | |
162 | uclass_get_device_by_name(UCLASS_FIRMWARE, "zynqmp-power", &dev); | |
163 | if (!dev) | |
164 | panic("PMU Firmware device not found - Enable it"); | |
165 | } | |
66ef85da | 166 | #endif |
325a22dc | 167 | |
c28a9cfa | 168 | #if defined(CONFIG_SPL_BUILD) |
98757d87 | 169 | printf("Silicon version:\t%d\n", zynqmp_get_silicon_version()); |
398a74ae JRO |
170 | |
171 | /* the CSU disables the JTAG interface when secure boot is enabled */ | |
11c0255c | 172 | if (CONFIG_IS_ENABLED(ZYNQMP_RESTORE_JTAG)) |
398a74ae | 173 | restore_jtag(); |
d61728c8 MS |
174 | #else |
175 | if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) | |
176 | xilinx_read_eeprom(); | |
c28a9cfa LC |
177 | #endif |
178 | ||
a0736efb MS |
179 | printf("EL Level:\tEL%d\n", current_el()); |
180 | ||
29bd8ada | 181 | #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) |
a1e618a1 SH |
182 | ret = soc_get(&soc); |
183 | if (!ret) { | |
184 | ret = soc_get_machine(soc, name, sizeof(name)); | |
185 | if (ret >= 0) { | |
186 | zynqmppl.name = strdup(name); | |
187 | fpga_init(); | |
188 | fpga_add(fpga_xilinx, &zynqmppl); | |
189 | } | |
190 | } | |
47e60cbd MS |
191 | #endif |
192 | ||
25a91f30 JRO |
193 | /* display secure boot information */ |
194 | print_secure_boot(); | |
c5143013 | 195 | if (current_el() == 3) |
e49f2a7f | 196 | printf("Multiboot:\t%d\n", multi_boot()); |
c5143013 | 197 | |
84c7204b MS |
198 | return 0; |
199 | } | |
200 | ||
201 | int board_early_init_r(void) | |
202 | { | |
203 | u32 val; | |
204 | ||
ec60a279 SDPP |
205 | if (current_el() != 3) |
206 | return 0; | |
207 | ||
90a35db4 MS |
208 | val = readl(&crlapb_base->timestamp_ref_ctrl); |
209 | val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; | |
210 | ||
ec60a279 | 211 | if (!val) { |
0785dfd8 MS |
212 | val = readl(&crlapb_base->timestamp_ref_ctrl); |
213 | val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; | |
214 | writel(val, &crlapb_base->timestamp_ref_ctrl); | |
84c7204b | 215 | |
0785dfd8 MS |
216 | /* Program freq register in System counter */ |
217 | writel(zynqmp_get_system_timer_freq(), | |
218 | &iou_scntr_secure->base_frequency_id_register); | |
219 | /* And enable system counter */ | |
220 | writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, | |
221 | &iou_scntr_secure->counter_control_register); | |
222 | } | |
84c7204b MS |
223 | return 0; |
224 | } | |
225 | ||
51916864 | 226 | unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, |
09140113 | 227 | char *const argv[]) |
51916864 NJ |
228 | { |
229 | int ret = 0; | |
230 | ||
231 | if (current_el() > 1) { | |
232 | smp_kick_all_cpus(); | |
233 | dcache_disable(); | |
234 | armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, | |
235 | ES_TO_AARCH64); | |
236 | } else { | |
237 | printf("FAIL: current EL is not above EL1\n"); | |
238 | ret = EINVAL; | |
239 | } | |
240 | return ret; | |
241 | } | |
242 | ||
aa6e94de | 243 | #if !defined(CFG_SYS_SDRAM_BASE) && !defined(CFG_SYS_SDRAM_SIZE) |
76b00aca | 244 | int dram_init_banksize(void) |
361a8799 | 245 | { |
0678941a NJ |
246 | int ret; |
247 | ||
248 | ret = fdtdec_setup_memory_banksize(); | |
249 | if (ret) | |
250 | return ret; | |
251 | ||
252 | mem_map_fill(); | |
253 | ||
254 | return 0; | |
8a5db0ab | 255 | } |
8d59d7f6 | 256 | |
361a8799 | 257 | int dram_init(void) |
8a5db0ab | 258 | { |
12308b12 | 259 | if (fdtdec_setup_mem_size_base() != 0) |
950f86ca | 260 | return -EINVAL; |
8a5db0ab | 261 | |
361a8799 | 262 | return 0; |
8d59d7f6 | 263 | } |
ce39ee28 | 264 | |
8d59d7f6 | 265 | #else |
0678941a NJ |
266 | int dram_init_banksize(void) |
267 | { | |
aa6e94de | 268 | gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE; |
0678941a | 269 | gd->bd->bi_dram[0].size = get_effective_memsize(); |
0678941a NJ |
270 | |
271 | mem_map_fill(); | |
272 | ||
273 | return 0; | |
274 | } | |
275 | ||
84c7204b MS |
276 | int dram_init(void) |
277 | { | |
aa6e94de TR |
278 | gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE, |
279 | CFG_SYS_SDRAM_SIZE); | |
84c7204b MS |
280 | |
281 | return 0; | |
282 | } | |
8d59d7f6 | 283 | #endif |
84c7204b | 284 | |
f1bc214b | 285 | #if !CONFIG_IS_ENABLED(SYSRESET) |
35b65dd8 | 286 | void reset_cpu(void) |
84c7204b MS |
287 | { |
288 | } | |
f1bc214b | 289 | #endif |
84c7204b | 290 | |
4d9bc795 MS |
291 | static u8 __maybe_unused zynqmp_get_bootmode(void) |
292 | { | |
293 | u8 bootmode; | |
294 | u32 reg = 0; | |
295 | int ret; | |
296 | ||
297 | ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); | |
298 | if (ret) | |
299 | return -EINVAL; | |
300 | ||
afb08a86 MS |
301 | debug("HW boot mode: %x\n", reg & BOOT_MODES_MASK); |
302 | debug("ALT boot mode: %x\n", reg >> BOOT_MODE_ALT_SHIFT); | |
303 | ||
4d9bc795 MS |
304 | if (reg >> BOOT_MODE_ALT_SHIFT) |
305 | reg >>= BOOT_MODE_ALT_SHIFT; | |
306 | ||
307 | bootmode = reg & BOOT_MODES_MASK; | |
308 | ||
309 | return bootmode; | |
310 | } | |
311 | ||
0bf3f9cb | 312 | #if defined(CONFIG_BOARD_LATE_INIT) |
d348beaa MS |
313 | static const struct { |
314 | u32 bit; | |
315 | const char *name; | |
316 | } reset_reasons[] = { | |
317 | { RESET_REASON_DEBUG_SYS, "DEBUG" }, | |
318 | { RESET_REASON_SOFT, "SOFT" }, | |
319 | { RESET_REASON_SRST, "SRST" }, | |
320 | { RESET_REASON_PSONLY, "PS-ONLY" }, | |
321 | { RESET_REASON_PMU, "PMU" }, | |
322 | { RESET_REASON_INTERNAL, "INTERNAL" }, | |
323 | { RESET_REASON_EXTERNAL, "EXTERNAL" }, | |
324 | {} | |
325 | }; | |
326 | ||
be52372f | 327 | static int reset_reason(void) |
d348beaa | 328 | { |
be52372f KR |
329 | u32 reg; |
330 | int i, ret; | |
d348beaa MS |
331 | const char *reason = NULL; |
332 | ||
be52372f KR |
333 | ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, ®); |
334 | if (ret) | |
335 | return -EINVAL; | |
d348beaa MS |
336 | |
337 | puts("Reset reason:\t"); | |
338 | ||
339 | for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { | |
be52372f | 340 | if (reg & reset_reasons[i].bit) { |
d348beaa MS |
341 | reason = reset_reasons[i].name; |
342 | printf("%s ", reset_reasons[i].name); | |
343 | break; | |
344 | } | |
345 | } | |
346 | ||
347 | puts("\n"); | |
348 | ||
349 | env_set("reset_reason", reason); | |
350 | ||
3aba25bc | 351 | return 0; |
d348beaa MS |
352 | } |
353 | ||
91d7e0c4 MS |
354 | static int set_fdtfile(void) |
355 | { | |
356 | char *compatible, *fdtfile; | |
357 | const char *suffix = ".dtb"; | |
358 | const char *vendor = "xilinx/"; | |
1b208d59 | 359 | int fdt_compat_len; |
91d7e0c4 MS |
360 | |
361 | if (env_get("fdtfile")) | |
362 | return 0; | |
363 | ||
1b208d59 IL |
364 | compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", |
365 | &fdt_compat_len); | |
366 | if (compatible && fdt_compat_len) { | |
367 | char *name; | |
368 | ||
91d7e0c4 MS |
369 | debug("Compatible: %s\n", compatible); |
370 | ||
1b208d59 IL |
371 | name = strchr(compatible, ','); |
372 | if (!name) | |
373 | return -EINVAL; | |
374 | ||
375 | name++; | |
91d7e0c4 | 376 | |
1b208d59 | 377 | fdtfile = calloc(1, strlen(vendor) + strlen(name) + |
91d7e0c4 MS |
378 | strlen(suffix) + 1); |
379 | if (!fdtfile) | |
380 | return -ENOMEM; | |
381 | ||
1b208d59 | 382 | sprintf(fdtfile, "%s%s%s", vendor, name, suffix); |
91d7e0c4 MS |
383 | |
384 | env_set("fdtfile", fdtfile); | |
385 | free(fdtfile); | |
386 | } | |
387 | ||
388 | return 0; | |
389 | } | |
390 | ||
6ec17a2c | 391 | static int boot_targets_setup(void) |
51f6c52e | 392 | { |
84c7204b | 393 | u8 bootmode; |
2882b39d MS |
394 | struct udevice *dev; |
395 | int bootseq = -1; | |
396 | int bootseq_len = 0; | |
0478b0b9 | 397 | int env_targets_len = 0; |
d75c65a5 | 398 | const char *mode = NULL; |
b72894f1 | 399 | char *new_targets; |
01c42d3d | 400 | char *env_targets; |
e8b43c64 | 401 | |
51f6c52e | 402 | bootmode = zynqmp_get_bootmode(); |
84c7204b | 403 | |
fb90917c | 404 | puts("Bootmode: "); |
84c7204b | 405 | switch (bootmode) { |
d58fc12e MS |
406 | case USB_MODE: |
407 | puts("USB_MODE\n"); | |
ef1be3e3 | 408 | mode = "usb_dfu0 usb_dfu1"; |
07656ba5 | 409 | env_set("modeboot", "usb_dfu_spl"); |
d58fc12e | 410 | break; |
0a5bcc8c | 411 | case JTAG_MODE: |
fb90917c | 412 | puts("JTAG_MODE\n"); |
5d2274c0 | 413 | mode = "jtag pxe dhcp"; |
07656ba5 | 414 | env_set("modeboot", "jtagboot"); |
0a5bcc8c SDPP |
415 | break; |
416 | case QSPI_MODE_24BIT: | |
417 | case QSPI_MODE_32BIT: | |
b72894f1 | 418 | mode = "qspi0"; |
fb90917c | 419 | puts("QSPI_MODE\n"); |
07656ba5 | 420 | env_set("modeboot", "qspiboot"); |
0a5bcc8c | 421 | break; |
39c56f55 | 422 | case EMMC_MODE: |
78678fee | 423 | puts("EMMC_MODE\n"); |
18be60b8 KR |
424 | if (uclass_get_device_by_name(UCLASS_MMC, |
425 | "mmc@ff160000", &dev) && | |
426 | uclass_get_device_by_name(UCLASS_MMC, | |
427 | "sdhci@ff160000", &dev)) { | |
d75c65a5 VYA |
428 | debug("SD0 driver for SD0 device is not present\n"); |
429 | break; | |
18be60b8 | 430 | } |
8b85dfc6 | 431 | debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev)); |
18be60b8 KR |
432 | |
433 | mode = "mmc"; | |
8b85dfc6 | 434 | bootseq = dev_seq(dev); |
5d498a12 | 435 | env_set("modeboot", "emmcboot"); |
78678fee MS |
436 | break; |
437 | case SD_MODE: | |
fb90917c | 438 | puts("SD_MODE\n"); |
2882b39d | 439 | if (uclass_get_device_by_name(UCLASS_MMC, |
e7c9de66 SDPP |
440 | "mmc@ff160000", &dev) && |
441 | uclass_get_device_by_name(UCLASS_MMC, | |
2882b39d | 442 | "sdhci@ff160000", &dev)) { |
d75c65a5 VYA |
443 | debug("SD0 driver for SD0 device is not present\n"); |
444 | break; | |
2882b39d | 445 | } |
8b85dfc6 | 446 | debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev)); |
2882b39d MS |
447 | |
448 | mode = "mmc"; | |
8b85dfc6 | 449 | bootseq = dev_seq(dev); |
07656ba5 | 450 | env_set("modeboot", "sdboot"); |
84c7204b | 451 | break; |
e1992276 SDPP |
452 | case SD1_LSHFT_MODE: |
453 | puts("LVL_SHFT_"); | |
f510927d | 454 | fallthrough; |
af813acd | 455 | case SD_MODE1: |
fb90917c | 456 | puts("SD_MODE1\n"); |
2882b39d | 457 | if (uclass_get_device_by_name(UCLASS_MMC, |
e7c9de66 SDPP |
458 | "mmc@ff170000", &dev) && |
459 | uclass_get_device_by_name(UCLASS_MMC, | |
2882b39d | 460 | "sdhci@ff170000", &dev)) { |
d75c65a5 VYA |
461 | debug("SD1 driver for SD1 device is not present\n"); |
462 | break; | |
2882b39d | 463 | } |
8b85dfc6 | 464 | debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev)); |
2882b39d MS |
465 | |
466 | mode = "mmc"; | |
8b85dfc6 | 467 | bootseq = dev_seq(dev); |
07656ba5 | 468 | env_set("modeboot", "sdboot"); |
af813acd MS |
469 | break; |
470 | case NAND_MODE: | |
fb90917c | 471 | puts("NAND_MODE\n"); |
b72894f1 | 472 | mode = "nand0"; |
07656ba5 | 473 | env_set("modeboot", "nandboot"); |
af813acd | 474 | break; |
84c7204b MS |
475 | default: |
476 | printf("Invalid Boot Mode:0x%x\n", bootmode); | |
477 | break; | |
478 | } | |
479 | ||
d75c65a5 VYA |
480 | if (mode) { |
481 | if (bootseq >= 0) { | |
482 | bootseq_len = snprintf(NULL, 0, "%i", bootseq); | |
483 | debug("Bootseq len: %x\n", bootseq_len); | |
484 | env_set_hex("bootseq", bootseq); | |
485 | } | |
2882b39d | 486 | |
d75c65a5 VYA |
487 | /* |
488 | * One terminating char + one byte for space between mode | |
489 | * and default boot_targets | |
490 | */ | |
491 | env_targets = env_get("boot_targets"); | |
492 | if (env_targets) | |
493 | env_targets_len = strlen(env_targets); | |
494 | ||
495 | new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + | |
496 | bootseq_len); | |
497 | if (!new_targets) | |
498 | return -ENOMEM; | |
499 | ||
500 | if (bootseq >= 0) | |
501 | sprintf(new_targets, "%s%x %s", mode, bootseq, | |
502 | env_targets ? env_targets : ""); | |
503 | else | |
504 | sprintf(new_targets, "%s %s", mode, | |
505 | env_targets ? env_targets : ""); | |
506 | ||
507 | env_set("boot_targets", new_targets); | |
508 | free(new_targets); | |
509 | } | |
b72894f1 | 510 | |
6ec17a2c MS |
511 | return 0; |
512 | } | |
513 | ||
514 | int board_late_init(void) | |
515 | { | |
516 | int ret, multiboot; | |
517 | ||
518 | #if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD) | |
519 | usb_ether_init(); | |
520 | #endif | |
521 | ||
522 | if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { | |
523 | debug("Saved variables - Skipping\n"); | |
524 | return 0; | |
525 | } | |
526 | ||
527 | if (!IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) | |
528 | return 0; | |
529 | ||
530 | ret = set_fdtfile(); | |
531 | if (ret) | |
532 | return ret; | |
533 | ||
534 | multiboot = multi_boot(); | |
535 | if (multiboot >= 0) | |
536 | env_set_hex("multiboot", multiboot); | |
537 | ||
538 | if (IS_ENABLED(CONFIG_DISTRO_DEFAULTS)) { | |
539 | ret = boot_targets_setup(); | |
540 | if (ret) | |
541 | return ret; | |
542 | } | |
543 | ||
d348beaa MS |
544 | reset_reason(); |
545 | ||
80fdef12 | 546 | return board_late_init_xilinx(); |
84c7204b | 547 | } |
0bf3f9cb | 548 | #endif |
84696ff5 SDPP |
549 | |
550 | int checkboard(void) | |
551 | { | |
5af08556 | 552 | puts("Board: Xilinx ZynqMP\n"); |
84696ff5 SDPP |
553 | return 0; |
554 | } | |
1025bd09 | 555 | |
476588c9 MS |
556 | int mmc_get_env_dev(void) |
557 | { | |
558 | struct udevice *dev; | |
559 | int bootseq = 0; | |
560 | ||
561 | switch (zynqmp_get_bootmode()) { | |
562 | case EMMC_MODE: | |
563 | case SD_MODE: | |
564 | if (uclass_get_device_by_name(UCLASS_MMC, | |
565 | "mmc@ff160000", &dev) && | |
566 | uclass_get_device_by_name(UCLASS_MMC, | |
567 | "sdhci@ff160000", &dev)) { | |
568 | return -1; | |
569 | } | |
570 | bootseq = dev_seq(dev); | |
571 | break; | |
572 | case SD1_LSHFT_MODE: | |
573 | case SD_MODE1: | |
574 | if (uclass_get_device_by_name(UCLASS_MMC, | |
575 | "mmc@ff170000", &dev) && | |
576 | uclass_get_device_by_name(UCLASS_MMC, | |
577 | "sdhci@ff170000", &dev)) { | |
578 | return -1; | |
579 | } | |
580 | bootseq = dev_seq(dev); | |
581 | break; | |
582 | default: | |
583 | break; | |
584 | } | |
585 | ||
586 | debug("bootseq %d\n", bootseq); | |
587 | ||
588 | return bootseq; | |
589 | } | |
590 | ||
097ccdf9 | 591 | #if defined(CONFIG_ENV_IS_NOWHERE) |
1025bd09 MS |
592 | enum env_location env_get_location(enum env_operation op, int prio) |
593 | { | |
594 | u32 bootmode = zynqmp_get_bootmode(); | |
595 | ||
596 | if (prio) | |
597 | return ENVL_UNKNOWN; | |
598 | ||
599 | switch (bootmode) { | |
600 | case EMMC_MODE: | |
601 | case SD_MODE: | |
602 | case SD1_LSHFT_MODE: | |
603 | case SD_MODE1: | |
604 | if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT)) | |
605 | return ENVL_FAT; | |
606 | if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)) | |
607 | return ENVL_EXT4; | |
50918d0d | 608 | return ENVL_NOWHERE; |
1025bd09 MS |
609 | case NAND_MODE: |
610 | if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND)) | |
611 | return ENVL_NAND; | |
612 | if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI)) | |
613 | return ENVL_UBI; | |
50918d0d | 614 | return ENVL_NOWHERE; |
1025bd09 MS |
615 | case QSPI_MODE_24BIT: |
616 | case QSPI_MODE_32BIT: | |
617 | if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) | |
618 | return ENVL_SPI_FLASH; | |
50918d0d | 619 | return ENVL_NOWHERE; |
1025bd09 MS |
620 | case JTAG_MODE: |
621 | default: | |
622 | return ENVL_NOWHERE; | |
623 | } | |
624 | } | |
097ccdf9 | 625 | #endif |
b86f43de MS |
626 | |
627 | #if defined(CONFIG_SET_DFU_ALT_INFO) | |
628 | ||
629 | #define DFU_ALT_BUF_LEN SZ_1K | |
630 | ||
c01f5949 MS |
631 | static void mtd_found_part(u32 *base, u32 *size) |
632 | { | |
633 | struct mtd_info *part, *mtd; | |
634 | ||
635 | mtd_probe_devices(); | |
636 | ||
637 | mtd = get_mtd_device_nm("nor0"); | |
638 | if (!IS_ERR_OR_NULL(mtd)) { | |
639 | list_for_each_entry(part, &mtd->partitions, node) { | |
640 | debug("0x%012llx-0x%012llx : \"%s\"\n", | |
641 | part->offset, part->offset + part->size, | |
642 | part->name); | |
643 | ||
644 | if (*base >= part->offset && | |
645 | *base < part->offset + part->size) { | |
646 | debug("Found my partition: %d/%s\n", | |
647 | part->index, part->name); | |
648 | *base = part->offset; | |
649 | *size = part->size; | |
650 | break; | |
651 | } | |
652 | } | |
653 | } | |
654 | } | |
655 | ||
b86f43de MS |
656 | void set_dfu_alt_info(char *interface, char *devstr) |
657 | { | |
b40d154c | 658 | int multiboot, bootseq = 0, len = 0; |
b86f43de MS |
659 | |
660 | ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); | |
661 | ||
ce183fd7 | 662 | if (env_get("dfu_alt_info")) |
b86f43de MS |
663 | return; |
664 | ||
665 | memset(buf, 0, sizeof(buf)); | |
666 | ||
667 | multiboot = multi_boot(); | |
e8b43c64 MS |
668 | if (multiboot < 0) |
669 | multiboot = 0; | |
670 | ||
671 | multiboot = env_get_hex("multiboot", multiboot); | |
b86f43de MS |
672 | debug("Multiboot: %d\n", multiboot); |
673 | ||
674 | switch (zynqmp_get_bootmode()) { | |
675 | case EMMC_MODE: | |
676 | case SD_MODE: | |
677 | case SD1_LSHFT_MODE: | |
678 | case SD_MODE1: | |
679 | bootseq = mmc_get_env_dev(); | |
b40d154c MS |
680 | |
681 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, "mmc %d=boot", | |
682 | bootseq); | |
683 | ||
684 | if (multiboot) | |
685 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, | |
686 | "%04d", multiboot); | |
687 | ||
688 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, ".bin fat %d 1", | |
689 | bootseq); | |
690 | #if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) | |
65d958d4 MS |
691 | if (strlen(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME)) |
692 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, | |
693 | ";%s fat %d 1", | |
694 | CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, | |
695 | bootseq); | |
b40d154c | 696 | #endif |
b86f43de MS |
697 | break; |
698 | case QSPI_MODE_24BIT: | |
699 | case QSPI_MODE_32BIT: | |
c01f5949 MS |
700 | { |
701 | u32 base = multiboot * SZ_32K; | |
702 | u32 size = 0x1500000; | |
703 | u32 limit = size; | |
704 | ||
705 | mtd_found_part(&base, &limit); | |
706 | ||
707 | #if defined(CONFIG_SYS_SPI_U_BOOT_OFFS) | |
708 | size = limit; | |
709 | limit = CONFIG_SYS_SPI_U_BOOT_OFFS; | |
710 | #endif | |
711 | ||
65d958d4 | 712 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, |
c01f5949 MS |
713 | "sf 0:0=boot.bin raw 0x%x 0x%x", |
714 | base, limit); | |
715 | #if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) && defined(CONFIG_SYS_SPI_U_BOOT_OFFS) | |
716 | if (strlen(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME)) | |
717 | len += snprintf(buf + len, DFU_ALT_BUF_LEN, | |
718 | ";%s raw 0x%x 0x%x", | |
719 | CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, | |
720 | base + limit, size - limit); | |
f93c1c8f | 721 | #endif |
c01f5949 | 722 | } |
b40d154c | 723 | break; |
b86f43de MS |
724 | default: |
725 | return; | |
726 | } | |
727 | ||
728 | env_set("dfu_alt_info", buf); | |
729 | puts("DFU alt info setting: done\n"); | |
730 | } | |
731 | #endif | |
2c8a0921 MS |
732 | |
733 | #if defined(CONFIG_SPL_SPI_LOAD) | |
734 | unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash) | |
735 | { | |
736 | u32 offset; | |
737 | int multiboot = multi_boot(); | |
738 | ||
739 | offset = multiboot * SZ_32K; | |
740 | offset += CONFIG_SYS_SPI_U_BOOT_OFFS; | |
741 | ||
742 | log_info("SPI offset:\t0x%x\n", offset); | |
743 | ||
744 | return offset; | |
745 | } | |
746 | #endif |