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