1
2
3
4
5
6
7#include <common.h>
8#include <uboot_aes.h>
9#include <sata.h>
10#include <ahci.h>
11#include <scsi.h>
12#include <malloc.h>
13#include <wdt.h>
14#include <asm/arch/clk.h>
15#include <asm/arch/hardware.h>
16#include <asm/arch/sys_proto.h>
17#include <asm/arch/psu_init_gpl.h>
18#include <asm/io.h>
19#include <dm/device.h>
20#include <dm/uclass.h>
21#include <usb.h>
22#include <dwc3-uboot.h>
23#include <zynqmppl.h>
24#include <g_dnl.h>
25#include <linux/sizes.h>
26
27#include "pm_cfg_obj.h"
28
29DECLARE_GLOBAL_DATA_PTR;
30
31#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
32static struct udevice *watchdog_dev;
33#endif
34
35#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
36 !defined(CONFIG_SPL_BUILD)
37static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
38
39static const struct {
40 u32 id;
41 u32 ver;
42 char *name;
43 bool evexists;
44} zynqmp_devices[] = {
45 {
46 .id = 0x10,
47 .name = "3eg",
48 },
49 {
50 .id = 0x10,
51 .ver = 0x2c,
52 .name = "3cg",
53 },
54 {
55 .id = 0x11,
56 .name = "2eg",
57 },
58 {
59 .id = 0x11,
60 .ver = 0x2c,
61 .name = "2cg",
62 },
63 {
64 .id = 0x20,
65 .name = "5ev",
66 .evexists = 1,
67 },
68 {
69 .id = 0x20,
70 .ver = 0x100,
71 .name = "5eg",
72 .evexists = 1,
73 },
74 {
75 .id = 0x20,
76 .ver = 0x12c,
77 .name = "5cg",
78 .evexists = 1,
79 },
80 {
81 .id = 0x21,
82 .name = "4ev",
83 .evexists = 1,
84 },
85 {
86 .id = 0x21,
87 .ver = 0x100,
88 .name = "4eg",
89 .evexists = 1,
90 },
91 {
92 .id = 0x21,
93 .ver = 0x12c,
94 .name = "4cg",
95 .evexists = 1,
96 },
97 {
98 .id = 0x30,
99 .name = "7ev",
100 .evexists = 1,
101 },
102 {
103 .id = 0x30,
104 .ver = 0x100,
105 .name = "7eg",
106 .evexists = 1,
107 },
108 {
109 .id = 0x30,
110 .ver = 0x12c,
111 .name = "7cg",
112 .evexists = 1,
113 },
114 {
115 .id = 0x38,
116 .name = "9eg",
117 },
118 {
119 .id = 0x38,
120 .ver = 0x2c,
121 .name = "9cg",
122 },
123 {
124 .id = 0x39,
125 .name = "6eg",
126 },
127 {
128 .id = 0x39,
129 .ver = 0x2c,
130 .name = "6cg",
131 },
132 {
133 .id = 0x40,
134 .name = "11eg",
135 },
136 {
137 .id = 0x50,
138 .ver = 0x2c,
139 .name = "15cg",
140 },
141 {
142 .id = 0x50,
143 .name = "15eg",
144 },
145 {
146 .id = 0x58,
147 .name = "19eg",
148 },
149 {
150 .id = 0x59,
151 .name = "17eg",
152 },
153 {
154 .id = 0x61,
155 .name = "21dr",
156 },
157 {
158 .id = 0x63,
159 .name = "23dr",
160 },
161 {
162 .id = 0x65,
163 .name = "25dr",
164 },
165 {
166 .id = 0x64,
167 .name = "27dr",
168 },
169 {
170 .id = 0x60,
171 .name = "28dr",
172 },
173 {
174 .id = 0x62,
175 .name = "29dr",
176 },
177 {
178 .id = 0x66,
179 .name = "39dr",
180 },
181 {
182 .id = 0x7b,
183 .name = "48dr",
184 },
185 {
186 .id = 0x7e,
187 .name = "49dr",
188 },
189};
190#endif
191
192int chip_id(unsigned char id)
193{
194 struct pt_regs regs;
195 int val = -EINVAL;
196
197 if (current_el() != 3) {
198 regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
199 regs.regs[1] = 0;
200 regs.regs[2] = 0;
201 regs.regs[3] = 0;
202
203 smc_call(®s);
204
205
206
207
208
209
210
211
212 switch (id) {
213 case IDCODE:
214 regs.regs[0] = upper_32_bits(regs.regs[0]);
215 regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
216 ZYNQMP_CSU_IDCODE_SVD_MASK;
217 regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
218 val = regs.regs[0];
219 break;
220 case VERSION:
221 regs.regs[1] = lower_32_bits(regs.regs[1]);
222 regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
223 val = regs.regs[1];
224 break;
225 case IDCODE2:
226 regs.regs[1] = lower_32_bits(regs.regs[1]);
227 regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
228 val = regs.regs[1];
229 break;
230 default:
231 printf("%s, Invalid Req:0x%x\n", __func__, id);
232 }
233 } else {
234 switch (id) {
235 case IDCODE:
236 val = readl(ZYNQMP_CSU_IDCODE_ADDR);
237 val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
238 ZYNQMP_CSU_IDCODE_SVD_MASK;
239 val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
240 break;
241 case VERSION:
242 val = readl(ZYNQMP_CSU_VER_ADDR);
243 val &= ZYNQMP_CSU_SILICON_VER_MASK;
244 break;
245 default:
246 printf("%s, Invalid Req:0x%x\n", __func__, id);
247 }
248 }
249
250 return val;
251}
252
253#define ZYNQMP_VERSION_SIZE 9
254#define ZYNQMP_PL_STATUS_BIT 9
255#define ZYNQMP_IPDIS_VCU_BIT 8
256#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
257#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
258#define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \
259 ~BIT(ZYNQMP_IPDIS_VCU_BIT)
260#define MAX_VARIANTS_EV 3
261
262#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
263 !defined(CONFIG_SPL_BUILD)
264static char *zynqmp_get_silicon_idcode_name(void)
265{
266 u32 i, id, ver, j;
267 char *buf;
268 static char name[ZYNQMP_VERSION_SIZE];
269
270 id = chip_id(IDCODE);
271 ver = chip_id(IDCODE2);
272
273 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
274 if (zynqmp_devices[i].id == id) {
275 if (zynqmp_devices[i].evexists &&
276 !(ver & ZYNQMP_PL_STATUS_MASK))
277 break;
278 if (zynqmp_devices[i].ver == (ver &
279 ZYNQMP_CSU_VERSION_MASK))
280 break;
281 }
282 }
283
284 if (i >= ARRAY_SIZE(zynqmp_devices))
285 return "unknown";
286
287 strncat(name, "zu", 2);
288 if (!zynqmp_devices[i].evexists ||
289 (ver & ZYNQMP_PL_STATUS_MASK)) {
290 strncat(name, zynqmp_devices[i].name,
291 ZYNQMP_VERSION_SIZE - 3);
292 return name;
293 }
294
295
296
297
298
299
300 for (j = 0; j < MAX_VARIANTS_EV; j++, i++) {
301 if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) ==
302 (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) {
303 strncat(name, zynqmp_devices[i].name,
304 ZYNQMP_VERSION_SIZE - 3);
305 break;
306 }
307 }
308
309 if (j >= MAX_VARIANTS_EV)
310 return "unknown";
311
312 if (strstr(name, "eg") || strstr(name, "ev")) {
313 buf = strstr(name, "e");
314 *buf = '\0';
315 }
316
317 return name;
318}
319#endif
320
321int board_early_init_f(void)
322{
323 int ret = 0;
324#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP)
325 u32 pm_api_version;
326
327 pm_api_version = zynqmp_pmufw_version();
328 printf("PMUFW:\tv%d.%d\n",
329 pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT,
330 pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK);
331
332 if (pm_api_version < ZYNQMP_PM_VERSION)
333 panic("PMUFW version error. Expected: v%d.%d\n",
334 ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR);
335#endif
336
337#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
338 ret = psu_init();
339#endif
340
341#if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD)
342
343 watchdog_dev = NULL;
344#endif
345
346 return ret;
347}
348
349int board_init(void)
350{
351#if defined(CONFIG_SPL_BUILD)
352
353 if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
354 zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
355 zynqmp_pm_cfg_obj_size);
356#endif
357
358 printf("EL Level:\tEL%d\n", current_el());
359
360#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
361 !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
362 defined(CONFIG_SPL_BUILD))
363 if (current_el() != 3) {
364 zynqmppl.name = zynqmp_get_silicon_idcode_name();
365 printf("Chip ID:\t%s\n", zynqmppl.name);
366 fpga_init();
367 fpga_add(fpga_xilinx, &zynqmppl);
368 }
369#endif
370
371#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
372 if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) {
373 debug("Watchdog: Not found by seq!\n");
374 if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
375 puts("Watchdog: Not found!\n");
376 return 0;
377 }
378 }
379
380 wdt_start(watchdog_dev, 0, 0);
381 puts("Watchdog: Started\n");
382#endif
383
384 return 0;
385}
386
387#ifdef CONFIG_WATCHDOG
388
389void watchdog_reset(void)
390{
391# if !defined(CONFIG_SPL_BUILD)
392 static ulong next_reset;
393 ulong now;
394
395 if (!watchdog_dev)
396 return;
397
398 now = timer_get_us();
399
400
401 if (now > next_reset) {
402 wdt_reset(watchdog_dev);
403 next_reset = now + 1000;
404 }
405# endif
406}
407#endif
408
409int board_early_init_r(void)
410{
411 u32 val;
412
413 if (current_el() != 3)
414 return 0;
415
416 val = readl(&crlapb_base->timestamp_ref_ctrl);
417 val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
418
419 if (!val) {
420 val = readl(&crlapb_base->timestamp_ref_ctrl);
421 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
422 writel(val, &crlapb_base->timestamp_ref_ctrl);
423
424
425 writel(zynqmp_get_system_timer_freq(),
426 &iou_scntr_secure->base_frequency_id_register);
427
428 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
429 &iou_scntr_secure->counter_control_register);
430 }
431 return 0;
432}
433
434unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
435 char * const argv[])
436{
437 int ret = 0;
438
439 if (current_el() > 1) {
440 smp_kick_all_cpus();
441 dcache_disable();
442 armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
443 ES_TO_AARCH64);
444 } else {
445 printf("FAIL: current EL is not above EL1\n");
446 ret = EINVAL;
447 }
448 return ret;
449}
450
451#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
452int dram_init_banksize(void)
453{
454 int ret;
455
456 ret = fdtdec_setup_memory_banksize();
457 if (ret)
458 return ret;
459
460 mem_map_fill();
461
462 return 0;
463}
464
465int dram_init(void)
466{
467 if (fdtdec_setup_mem_size_base() != 0)
468 return -EINVAL;
469
470 return 0;
471}
472#else
473int dram_init_banksize(void)
474{
475#if defined(CONFIG_NR_DRAM_BANKS)
476 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
477 gd->bd->bi_dram[0].size = get_effective_memsize();
478#endif
479
480 mem_map_fill();
481
482 return 0;
483}
484
485int dram_init(void)
486{
487 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
488 CONFIG_SYS_SDRAM_SIZE);
489
490 return 0;
491}
492#endif
493
494void reset_cpu(ulong addr)
495{
496}
497
498#if defined(CONFIG_BOARD_LATE_INIT)
499static const struct {
500 u32 bit;
501 const char *name;
502} reset_reasons[] = {
503 { RESET_REASON_DEBUG_SYS, "DEBUG" },
504 { RESET_REASON_SOFT, "SOFT" },
505 { RESET_REASON_SRST, "SRST" },
506 { RESET_REASON_PSONLY, "PS-ONLY" },
507 { RESET_REASON_PMU, "PMU" },
508 { RESET_REASON_INTERNAL, "INTERNAL" },
509 { RESET_REASON_EXTERNAL, "EXTERNAL" },
510 {}
511};
512
513static int reset_reason(void)
514{
515 u32 reg;
516 int i, ret;
517 const char *reason = NULL;
518
519 ret = zynqmp_mmio_read((ulong)&crlapb_base->reset_reason, ®);
520 if (ret)
521 return -EINVAL;
522
523 puts("Reset reason:\t");
524
525 for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
526 if (reg & reset_reasons[i].bit) {
527 reason = reset_reasons[i].name;
528 printf("%s ", reset_reasons[i].name);
529 break;
530 }
531 }
532
533 puts("\n");
534
535 env_set("reset_reason", reason);
536
537 ret = zynqmp_mmio_write(~0, ~0, (ulong)&crlapb_base->reset_reason);
538 if (ret)
539 return -EINVAL;
540
541 return ret;
542}
543
544static int set_fdtfile(void)
545{
546 char *compatible, *fdtfile;
547 const char *suffix = ".dtb";
548 const char *vendor = "xilinx/";
549
550 if (env_get("fdtfile"))
551 return 0;
552
553 compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
554 if (compatible) {
555 debug("Compatible: %s\n", compatible);
556
557
558 strsep(&compatible, ",");
559
560 fdtfile = calloc(1, strlen(vendor) + strlen(compatible) +
561 strlen(suffix) + 1);
562 if (!fdtfile)
563 return -ENOMEM;
564
565 sprintf(fdtfile, "%s%s%s", vendor, compatible, suffix);
566
567 env_set("fdtfile", fdtfile);
568 free(fdtfile);
569 }
570
571 return 0;
572}
573
574int board_late_init(void)
575{
576 u32 reg = 0;
577 u8 bootmode;
578 struct udevice *dev;
579 int bootseq = -1;
580 int bootseq_len = 0;
581 int env_targets_len = 0;
582 const char *mode;
583 char *new_targets;
584 char *env_targets;
585 int ret;
586 ulong initrd_hi;
587
588#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
589 usb_ether_init();
590#endif
591
592 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
593 debug("Saved variables - Skipping\n");
594 return 0;
595 }
596
597 ret = set_fdtfile();
598 if (ret)
599 return ret;
600
601 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®);
602 if (ret)
603 return -EINVAL;
604
605 if (reg >> BOOT_MODE_ALT_SHIFT)
606 reg >>= BOOT_MODE_ALT_SHIFT;
607
608 bootmode = reg & BOOT_MODES_MASK;
609
610 puts("Bootmode: ");
611 switch (bootmode) {
612 case USB_MODE:
613 puts("USB_MODE\n");
614 mode = "usb";
615 env_set("modeboot", "usb_dfu_spl");
616 break;
617 case JTAG_MODE:
618 puts("JTAG_MODE\n");
619 mode = "jtag pxe dhcp";
620 env_set("modeboot", "jtagboot");
621 break;
622 case QSPI_MODE_24BIT:
623 case QSPI_MODE_32BIT:
624 mode = "qspi0";
625 puts("QSPI_MODE\n");
626 env_set("modeboot", "qspiboot");
627 break;
628 case EMMC_MODE:
629 puts("EMMC_MODE\n");
630 mode = "mmc0";
631 env_set("modeboot", "emmcboot");
632 break;
633 case SD_MODE:
634 puts("SD_MODE\n");
635 if (uclass_get_device_by_name(UCLASS_MMC,
636 "mmc@ff160000", &dev) &&
637 uclass_get_device_by_name(UCLASS_MMC,
638 "sdhci@ff160000", &dev)) {
639 puts("Boot from SD0 but without SD0 enabled!\n");
640 return -1;
641 }
642 debug("mmc0 device found at %p, seq %d\n", dev, dev->seq);
643
644 mode = "mmc";
645 bootseq = dev->seq;
646 env_set_ulong("sdbootdev", bootseq);
647 env_set("modeboot", "sdboot");
648 break;
649 case SD1_LSHFT_MODE:
650 puts("LVL_SHFT_");
651
652 case SD_MODE1:
653 puts("SD_MODE1\n");
654 if (uclass_get_device_by_name(UCLASS_MMC,
655 "mmc@ff170000", &dev) &&
656 uclass_get_device_by_name(UCLASS_MMC,
657 "sdhci@ff170000", &dev)) {
658 puts("Boot from SD1 but without SD1 enabled!\n");
659 return -1;
660 }
661 debug("mmc1 device found at %p, seq %d\n", dev, dev->seq);
662
663 mode = "mmc";
664 bootseq = dev->seq;
665 env_set_ulong("sdbootdev", bootseq);
666 env_set("modeboot", "sdboot");
667 break;
668 case NAND_MODE:
669 puts("NAND_MODE\n");
670 mode = "nand0";
671 env_set("modeboot", "nandboot");
672 break;
673 default:
674 mode = "";
675 printf("Invalid Boot Mode:0x%x\n", bootmode);
676 break;
677 }
678
679 if (bootseq >= 0) {
680 bootseq_len = snprintf(NULL, 0, "%i", bootseq);
681 debug("Bootseq len: %x\n", bootseq_len);
682 }
683
684
685
686
687
688 env_targets = env_get("boot_targets");
689 if (env_targets)
690 env_targets_len = strlen(env_targets);
691
692 new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
693 bootseq_len);
694 if (!new_targets)
695 return -ENOMEM;
696
697 if (bootseq >= 0)
698 sprintf(new_targets, "%s%x %s", mode, bootseq,
699 env_targets ? env_targets : "");
700 else
701 sprintf(new_targets, "%s %s", mode,
702 env_targets ? env_targets : "");
703
704 env_set("boot_targets", new_targets);
705
706 initrd_hi = gd->start_addr_sp - CONFIG_STACK_SIZE;
707 initrd_hi = round_down(initrd_hi, SZ_16M);
708 env_set_addr("initrd_high", (void *)initrd_hi);
709
710 reset_reason();
711
712 return 0;
713}
714#endif
715
716int checkboard(void)
717{
718 puts("Board: Xilinx ZynqMP\n");
719 return 0;
720}
721
722#if defined(CONFIG_AES)
723
724#define KEY_LEN 64
725#define IV_LEN 24
726#define ZYNQMP_SIP_SVC_PM_SECURE_LOAD 0xC2000019
727#define ZYNQMP_PM_SECURE_AES 0x1
728
729int aes_decrypt_hw(u8 *key_ptr, u8 *src_ptr, u8 *dst_ptr, u32 len)
730{
731 int ret;
732 u32 src_lo, src_hi, wlen;
733 u32 ret_payload[PAYLOAD_ARG_CNT];
734
735 if ((ulong)src_ptr != ALIGN((ulong)src_ptr,
736 CONFIG_SYS_CACHELINE_SIZE)) {
737 debug("FAIL: Source address not aligned:%p\n", src_ptr);
738 return -EINVAL;
739 }
740
741 src_lo = (u32)(ulong)src_ptr;
742 src_hi = upper_32_bits((ulong)src_ptr);
743 wlen = DIV_ROUND_UP(len, 4);
744
745 memcpy(src_ptr + len, key_ptr, KEY_LEN + IV_LEN);
746 len = ROUND(len + KEY_LEN + IV_LEN, CONFIG_SYS_CACHELINE_SIZE);
747 flush_dcache_range((ulong)src_ptr, (ulong)(src_ptr + len));
748
749 ret = invoke_smc(ZYNQMP_SIP_SVC_PM_SECURE_LOAD, src_lo, src_hi, wlen,
750 ZYNQMP_PM_SECURE_AES, ret_payload);
751 if (ret)
752 printf("Fail: %s: %d\n", __func__, ret);
753
754 return ret;
755}
756#endif
757