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