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