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