Browse Source

Merge tag 'xilinx-for-v2018.07' of git://www.denx.de/git/u-boot-microblaze

Xilinx changes for v2018.07

microblaze:
- Align defconfig

zynq:
- Rework fpga initialization and cpuinfo handling

zynqmp:
- Add ZynqMP R5 support
- Wire and enable watchdog on zcu100-revC
- Setup MMU map for DDR at run time
- Show board info based on DT and cleanup IDENT_STRING

zynqmp tools:
- Add read partition support
- Add initial support for Xilinx bif format for boot.bin generation

mmc:
- Fix get_timer usage on 64bit cpus
- Add support for SD3.0 UHS mode

nand-zynq:
- Add support for 16bit buswidth
- Use address cycles from onfi params

scsi:
- convert ceva sata to UCLASS_AHCI

timer:
- Add Cadence TTC for ZynqMP r5

watchdog:
- Minor cadence driver cleanup
Tom Rini 6 years ago
parent
commit
3b52847a45
85 changed files with 3176 additions and 314 deletions
  1. 9 2
      MAINTAINERS
  2. 11 0
      arch/arm/Kconfig
  3. 1 0
      arch/arm/Makefile
  4. 52 32
      arch/arm/cpu/armv8/zynqmp/cpu.c
  5. 3 0
      arch/arm/dts/Makefile
  6. 1 1
      arch/arm/dts/zynqmp-clk.dtsi
  7. 73 0
      arch/arm/dts/zynqmp-r5.dts
  8. 79 0
      arch/arm/dts/zynqmp-zc1275-revB.dts
  9. 1 0
      arch/arm/dts/zynqmp-zcu100-revC.dts
  10. 1 1
      arch/arm/include/asm/arch-zynqmp/sys_proto.h
  11. 84 1
      arch/arm/mach-zynq/cpu.c
  12. 6 5
      arch/arm/mach-zynq/spl.c
  13. 27 0
      arch/arm/mach-zynqmp-r5/Kconfig
  14. 3 0
      arch/arm/mach-zynqmp-r5/Makefile
  15. 37 0
      arch/arm/mach-zynqmp-r5/cpu.c
  16. 0 80
      board/xilinx/zynq/board.c
  17. 2 0
      board/xilinx/zynqmp/Makefile
  18. 229 0
      board/xilinx/zynqmp/tap_delays.c
  19. 523 0
      board/xilinx/zynqmp/zynqmp-zc1275-revB/psu_init_gpl.c
  20. 1 1
      board/xilinx/zynqmp/zynqmp-zcu100-revC/psu_init_gpl.c
  21. 71 9
      board/xilinx/zynqmp/zynqmp.c
  22. 7 0
      board/xilinx/zynqmp_r5/MAINTAINERS
  23. 6 0
      board/xilinx/zynqmp_r5/Makefile
  24. 25 0
      board/xilinx/zynqmp_r5/board.c
  25. 1 0
      common/image.c
  26. 0 4
      configs/microblaze-generic_defconfig
  27. 0 1
      configs/syzygy_hub_defconfig
  28. 0 1
      configs/topic_miami_defconfig
  29. 0 1
      configs/topic_miamilite_defconfig
  30. 0 1
      configs/topic_miamiplus_defconfig
  31. 16 0
      configs/xilinx_zynqmp_r5_defconfig
  32. 0 2
      configs/xilinx_zynqmp_zc1232_revA_defconfig
  33. 0 2
      configs/xilinx_zynqmp_zc1254_revA_defconfig
  34. 0 2
      configs/xilinx_zynqmp_zc1275_revA_defconfig
  35. 53 0
      configs/xilinx_zynqmp_zc1275_revB_defconfig
  36. 0 2
      configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
  37. 0 2
      configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
  38. 0 2
      configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig
  39. 0 2
      configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
  40. 0 2
      configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
  41. 2 2
      configs/xilinx_zynqmp_zcu100_revC_defconfig
  42. 2 2
      configs/xilinx_zynqmp_zcu102_rev1_0_defconfig
  43. 0 2
      configs/xilinx_zynqmp_zcu102_revA_defconfig
  44. 0 2
      configs/xilinx_zynqmp_zcu102_revB_defconfig
  45. 0 2
      configs/xilinx_zynqmp_zcu104_revA_defconfig
  46. 0 2
      configs/xilinx_zynqmp_zcu104_revC_defconfig
  47. 0 2
      configs/xilinx_zynqmp_zcu106_revA_defconfig
  48. 0 2
      configs/xilinx_zynqmp_zcu111_revA_defconfig
  49. 0 1
      configs/zynq_cc108_defconfig
  50. 1 0
      configs/zynq_cse_qspi_defconfig
  51. 0 1
      configs/zynq_microzed_defconfig
  52. 0 1
      configs/zynq_picozed_defconfig
  53. 0 1
      configs/zynq_z_turn_defconfig
  54. 0 1
      configs/zynq_zc702_defconfig
  55. 0 1
      configs/zynq_zc706_defconfig
  56. 0 1
      configs/zynq_zc770_xm010_defconfig
  57. 0 1
      configs/zynq_zc770_xm011_defconfig
  58. 0 1
      configs/zynq_zc770_xm011_x16_defconfig
  59. 0 1
      configs/zynq_zc770_xm012_defconfig
  60. 0 1
      configs/zynq_zc770_xm013_defconfig
  61. 0 1
      configs/zynq_zed_defconfig
  62. 0 1
      configs/zynq_zybo_defconfig
  63. 20 16
      drivers/ata/sata_ceva.c
  64. 2 2
      drivers/mmc/mmc.c
  65. 61 4
      drivers/mmc/sdhci.c
  66. 226 5
      drivers/mmc/zynq_sdhci.c
  67. 53 1
      drivers/mtd/nand/zynq_nand.c
  68. 1 1
      drivers/serial/Kconfig
  69. 0 1
      drivers/serial/serial_zynq.c
  70. 7 0
      drivers/timer/Kconfig
  71. 1 0
      drivers/timer/Makefile
  72. 91 0
      drivers/timer/cadence-ttc.c
  73. 2 2
      drivers/watchdog/cdns_wdt.c
  74. 51 0
      include/configs/xilinx_zynqmp_r5.h
  75. 16 0
      include/configs/xilinx_zynqmp_zc1275_revB.h
  76. 1 0
      include/image.h
  77. 8 0
      include/sdhci.h
  78. 19 0
      include/zynqmp_tap_delay.h
  79. 34 55
      include/zynqpl.h
  80. 1 0
      tools/Makefile
  81. 1 0
      tools/imagetool.h
  82. 7 0
      tools/mkimage.c
  83. 1008 0
      tools/zynqmpbif.c
  84. 100 42
      tools/zynqmpimage.c
  85. 139 0
      tools/zynqmpimage.h

+ 9 - 2
MAINTAINERS

@@ -274,7 +274,7 @@ ARM ZYNQMP
 M:	Michal Simek <michal.simek@xilinx.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-microblaze.git
-F:	arch/arm/mach-zynq/
+F:	arch/arm/cpu/armv8/zynqmp/
 F:	drivers/clk/clk_zynqmp.c
 F:	drivers/fpga/zynqpl.c
 F:	drivers/gpio/zynq_gpio.c
@@ -288,12 +288,19 @@ F:	drivers/net/zynq_gem.c
 F:	drivers/serial/serial_zynq.c
 F:	drivers/spi/zynq_qspi.c
 F:	drivers/spi/zynq_spi.c
+F:	drivers/timer/cadence-ttc.c
 F:	drivers/usb/host/ehci-zynq.c
 F:	drivers/watchdog/cdns_wdt.c
 F:	include/zynqmppl.h
-F:	tools/zynqimage.c
+F:	tools/zynqmp*
 N:	zynqmp
 
+ARM ZYNQMP R5
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/arm/mach-zynqmp-r5/
+
 BUILDMAN
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained

+ 11 - 0
arch/arm/Kconfig

@@ -821,6 +821,15 @@ config ARCH_ZYNQ
 	imply CMD_CLK
 	imply FAT_WRITE
 	imply CMD_SPL
+	imply ARCH_EARLY_INIT_R
+
+config ARCH_ZYNQMP_R5
+	bool "Xilinx ZynqMP R5 based platform"
+	select CPU_V7R
+	select OF_CONTROL
+	select DM
+	select DM_SERIAL
+	select CLK
 
 config ARCH_ZYNQMP
 	bool "Xilinx ZynqMP based platform"
@@ -1344,6 +1353,8 @@ source "arch/arm/cpu/armv7/vf610/Kconfig"
 
 source "arch/arm/mach-zynq/Kconfig"
 
+source "arch/arm/mach-zynqmp-r5/Kconfig"
+
 source "arch/arm/cpu/armv7/Kconfig"
 
 source "arch/arm/cpu/armv8/zynqmp/Kconfig"

+ 1 - 0
arch/arm/Makefile

@@ -76,6 +76,7 @@ machine-$(CONFIG_ARCH_STM32MP)		+= stm32mp
 machine-$(CONFIG_TEGRA)			+= tegra
 machine-$(CONFIG_ARCH_UNIPHIER)		+= uniphier
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
+machine-$(CONFIG_ARCH_ZYNQMP_R5)	+= zynqmp-r5
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 

+ 52 - 32
arch/arm/cpu/armv8/zynqmp/cpu.c

@@ -15,16 +15,28 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct mm_region zynqmp_mem_map[] = {
+/*
+ * Number of filled static entries and also the first empty
+ * slot in zynqmp_mem_map.
+ */
+#define ZYNQMP_MEM_MAP_USED	4
+
 #if !defined(CONFIG_ZYNQMP_NO_DDR)
-	{
-		.virt = 0x0UL,
-		.phys = 0x0UL,
-		.size = 0x80000000UL,
-		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
-			 PTE_BLOCK_INNER_SHARE
-	},
+#define DRAM_BANKS CONFIG_NR_DRAM_BANKS
+#else
+#define DRAM_BANKS 0
 #endif
+
+#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
+#define TCM_MAP 1
+#else
+#define TCM_MAP 0
+#endif
+
+/* +1 is end of list which needs to be empty */
+#define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1)
+
+static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = {
 	{
 		.virt = 0x80000000UL,
 		.phys = 0x80000000UL,
@@ -32,8 +44,7 @@ static struct mm_region zynqmp_mem_map[] = {
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
-	},
-	{
+	}, {
 		.virt = 0xf8000000UL,
 		.phys = 0xf8000000UL,
 		.size = 0x07e00000UL,
@@ -41,42 +52,51 @@ static struct mm_region zynqmp_mem_map[] = {
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
-		.virt = 0xffe00000UL,
-		.phys = 0xffe00000UL,
-		.size = 0x00200000UL,
-		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
-			 PTE_BLOCK_INNER_SHARE
-	}, {
-#endif
 		.virt = 0x400000000UL,
 		.phys = 0x400000000UL,
 		.size = 0x400000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
-	},
-#if !defined(CONFIG_ZYNQMP_NO_DDR)
-	{
-		.virt = 0x800000000UL,
-		.phys = 0x800000000UL,
-		.size = 0x800000000UL,
-		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
-			 PTE_BLOCK_INNER_SHARE
-	},
-#endif
-	{
+	}, {
 		.virt = 0x1000000000UL,
 		.phys = 0x1000000000UL,
 		.size = 0xf000000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
-	}, {
-		/* List terminator */
-		0,
 	}
 };
+
+void mem_map_fill(void)
+{
+	int banks = ZYNQMP_MEM_MAP_USED;
+
+#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
+	zynqmp_mem_map[banks].virt = 0xffe00000UL;
+	zynqmp_mem_map[banks].phys = 0xffe00000UL;
+	zynqmp_mem_map[banks].size = 0x00200000UL;
+	zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				      PTE_BLOCK_INNER_SHARE;
+	banks = banks + 1;
+#endif
+
+#if !defined(CONFIG_ZYNQMP_NO_DDR)
+	for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/* Zero size means no more DDR that's this is end */
+		if (!gd->bd->bi_dram[i].size)
+			break;
+
+		zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start;
+		zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start;
+		zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size;
+		zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+					      PTE_BLOCK_INNER_SHARE;
+		banks = banks + 1;
+	}
+#endif
+}
+
 struct mm_region *mem_map = zynqmp_mem_map;
 
 u64 get_page_table_size(void)

+ 3 - 0
arch/arm/dts/Makefile

@@ -157,11 +157,14 @@ dtb-$(CONFIG_ARCH_ZYNQMP) += \
 	zynqmp-zc1232-revA.dtb			\
 	zynqmp-zc1254-revA.dtb			\
 	zynqmp-zc1275-revA.dtb			\
+	zynqmp-zc1275-revB.dtb			\
 	zynqmp-zc1751-xm015-dc1.dtb		\
 	zynqmp-zc1751-xm016-dc2.dtb		\
 	zynqmp-zc1751-xm017-dc3.dtb		\
 	zynqmp-zc1751-xm018-dc4.dtb		\
 	zynqmp-zc1751-xm019-dc5.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP_R5) += \
+	zynqmp-r5.dtb
 dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \
 	am335x-draco.dtb \
 	am335x-evm.dtb \

+ 1 - 1
arch/arm/dts/zynqmp-clk.dtsi

@@ -219,7 +219,7 @@
 };
 
 &watchdog0 {
-	clocks = <&clk250>;
+	clocks = <&clk100>;
 };
 
 &xilinx_drm {

+ 73 - 0
arch/arm/dts/zynqmp-r5.dts

@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Xilinx ZynqMP R5
+ *
+ * (C) Copyright 2018, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "xlnx,zynqmp-r5";
+	model = "Xilinx ZynqMP R5";
+
+	cpus {
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-r5";
+			device_type = "cpu";
+			reg = <0>;
+		};
+	};
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "";
+		stdout-path = "serial0:115200n8";
+	};
+
+	clk100: clk100 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		u-boot,dm-pre-reloc;
+	};
+
+	amba {
+		u-boot,dm-pre-reloc;
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ttc0: timer@ff110000 {
+			compatible = "cdns,ttc";
+			status = "okay";
+			reg = <0xff110000 0x1000>;
+			timer-width = <32>;
+			clocks = <&clk100>;
+		};
+
+		uart1: serial@ff010000 {
+			u-boot,dm-pre-reloc;
+			compatible = "cdns,uart-r1p12", "xlnx,xuartps";
+			reg = <0xff010000 0x1000>;
+			clock-names = "uart_clk", "pclk";
+			clocks = <&clk100 &clk100>;
+		};
+	};
+};

+ 79 - 0
arch/arm/dts/zynqmp-zc1275-revB.dts

@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Xilinx ZynqMP ZC1275 RevB
+ *
+ * (C) Copyright 2018, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad Paladugu <sivadur@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+
+/ {
+	model = "ZynqMP ZC1275 RevB";
+	compatible = "xlnx,zynqmp-zc1275-revB", "xlnx,zynqmp-zc1275", "xlnx,zynqmp";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+		mmc0 = &sdhci1;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@qspi-fsbl-uboot { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@qspi-linux { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@qspi-device-tree { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@qspi-rootfs { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&sdhci1 {
+	status = "okay";
+	no-1-8-v;
+	xlnx,mio_bank = <1>;
+};

+ 1 - 0
arch/arm/dts/zynqmp-zcu100-revC.dts

@@ -332,6 +332,7 @@
 
 &watchdog0 {
 	status = "okay";
+	reset-on-timeout;
 };
 
 &xilinx_ams {

+ 1 - 1
arch/arm/include/asm/arch-zynqmp/sys_proto.h

@@ -45,7 +45,7 @@ int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3,
 	       u32 *ret_payload);
 
 void initialize_tcm(bool mode);
-
+void mem_map_fill(void);
 int chip_id(unsigned char id);
 
 #endif /* _ASM_ARCH_SYS_PROTO_H */

+ 84 - 1
arch/arm/mach-zynq/cpu.c

@@ -4,14 +4,45 @@
  * Copyright (C) 2012 Xilinx, Inc. All rights reserved.
  */
 #include <common.h>
+#include <zynqpl.h>
 #include <asm/io.h>
 #include <asm/arch/clk.h>
-#include <asm/arch/sys_proto.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/ps7_init_gpl.h>
+#include <asm/arch/sys_proto.h>
 
 #define ZYNQ_SILICON_VER_MASK	0xF0000000
 #define ZYNQ_SILICON_VER_SHIFT	28
 
+#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
+    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
+xilinx_desc fpga = {
+	.family = xilinx_zynq,
+	.iface = devcfg,
+	.operations = &zynq_op,
+};
+#endif
+
+static const struct {
+	u8 idcode;
+#if defined(CONFIG_FPGA)
+	u32 fpga_size;
+#endif
+	char *devicename;
+} zynq_fpga_descs[] = {
+	ZYNQ_DESC(7Z007S),
+	ZYNQ_DESC(7Z010),
+	ZYNQ_DESC(7Z012S),
+	ZYNQ_DESC(7Z014S),
+	ZYNQ_DESC(7Z015),
+	ZYNQ_DESC(7Z020),
+	ZYNQ_DESC(7Z030),
+	ZYNQ_DESC(7Z035),
+	ZYNQ_DESC(7Z045),
+	ZYNQ_DESC(7Z100),
+	{ /* Sentinel */ },
+};
+
 int arch_cpu_init(void)
 {
 	zynq_slcr_unlock();
@@ -59,3 +90,55 @@ void enable_caches(void)
 	dcache_enable();
 }
 #endif
+
+static int __maybe_unused cpu_desc_id(void)
+{
+	u32 idcode;
+	u8 i;
+
+	idcode = zynq_slcr_get_idcode();
+	for (i = 0; zynq_fpga_descs[i].idcode; i++) {
+		if (zynq_fpga_descs[i].idcode == idcode)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+#if defined(CONFIG_ARCH_EARLY_INIT_R)
+int arch_early_init_r(void)
+{
+#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
+    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
+	int cpu_id = cpu_desc_id();
+
+	if (cpu_id < 0)
+		return 0;
+
+	fpga.size = zynq_fpga_descs[cpu_id].fpga_size;
+	fpga.name = zynq_fpga_descs[cpu_id].devicename;
+	fpga_init();
+	fpga_add(fpga_xilinx, &fpga);
+#endif
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+	u32 version;
+	int cpu_id = cpu_desc_id();
+
+	if (cpu_id < 0)
+		return 0;
+
+	version = zynq_get_silicon_version() << 1;
+	if (version > (PCW_SILICON_VERSION_3 << 1))
+		version += 1;
+
+	printf("CPU:   Zynq %s\n", zynq_fpga_descs[cpu_id].devicename);
+	printf("Silicon: v%d.%d\n", version >> 1, version & 1);
+	return 0;
+}
+#endif

+ 6 - 5
arch/arm/mach-zynq/spl.c

@@ -17,11 +17,12 @@ void board_init_f(ulong dummy)
 	ps7_init();
 
 	arch_cpu_init();
-	/*
-	 * The debug UART can be used from this point:
-	 * debug_uart_init();
-	 * printch('x');
-	 */
+
+#ifdef CONFIG_DEBUG_UART
+	/* Uart debug for sure */
+	debug_uart_init();
+	puts("Debug uart enabled\n"); /* or printch() */
+#endif
 }
 
 #ifdef CONFIG_SPL_BOARD_INIT

+ 27 - 0
arch/arm/mach-zynqmp-r5/Kconfig

@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if ARCH_ZYNQMP_R5
+
+config SYS_BOARD
+	string "Board name"
+	default "zynqmp_r5"
+
+config SYS_VENDOR
+	string "Vendor name"
+	default "xilinx"
+
+config SYS_SOC
+	default "zynqmp-r5"
+
+config SYS_CONFIG_NAME
+	string "Board configuration name"
+	default "xilinx_zynqmp_r5"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
+
+config SYS_MALLOC_F_LEN
+	default 0x600
+
+endif

+ 3 - 0
arch/arm/mach-zynqmp-r5/Makefile

@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y	+= cpu.o

+ 37 - 0
arch/arm/mach-zynqmp-r5/cpu.c

@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Xilinx, Inc. (Michal Simek)
+ */
+
+#include <common.h>
+#include <asm/armv7_mpu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mpu_region_config region_config[] = {
+	{ 0x00000000, REGION_0, XN_DIS, PRIV_RW_USR_RW,
+	  O_I_WB_RD_WR_ALLOC, REGION_1GB },
+	{ 0x20000000, REGION_1, XN_EN, PRIV_RO_USR_RO,
+	  O_I_WB_RD_WR_ALLOC, REGION_512MB },
+	{ 0x40000000, REGION_2, XN_EN, PRIV_RO_USR_RO,
+	  O_I_WB_RD_WR_ALLOC, REGION_1GB },
+};
+
+int arch_cpu_init(void)
+{
+	gd->cpu_clk = CONFIG_CPU_FREQ_HZ;
+
+	setup_mpu_regions(region_config, sizeof(region_config) /
+			  sizeof(struct mpu_region_config));
+
+	return 0;
+}
+
+/*
+ * Perform the low-level reset.
+ */
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

+ 0 - 80
board/xilinx/zynq/board.c

@@ -13,27 +13,9 @@
 #include <zynqpl.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/ps7_init_gpl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
-    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
-static xilinx_desc fpga;
-
-/* It can be done differently */
-static xilinx_desc fpga007s = XILINX_XC7Z007S_DESC(0x7);
-static xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
-static xilinx_desc fpga012s = XILINX_XC7Z012S_DESC(0x12);
-static xilinx_desc fpga014s = XILINX_XC7Z014S_DESC(0x14);
-static xilinx_desc fpga015 = XILINX_XC7Z015_DESC(0x15);
-static xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
-static xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
-static xilinx_desc fpga035 = XILINX_XC7Z035_DESC(0x35);
-static xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
-static xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100);
-#endif
-
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
 static struct udevice *watchdog_dev;
 #endif
@@ -52,46 +34,6 @@ int board_early_init_f(void)
 
 int board_init(void)
 {
-#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
-    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
-	u32 idcode;
-
-	idcode = zynq_slcr_get_idcode();
-
-	switch (idcode) {
-	case XILINX_ZYNQ_7007S:
-		fpga = fpga007s;
-		break;
-	case XILINX_ZYNQ_7010:
-		fpga = fpga010;
-		break;
-	case XILINX_ZYNQ_7012S:
-		fpga = fpga012s;
-		break;
-	case XILINX_ZYNQ_7014S:
-		fpga = fpga014s;
-		break;
-	case XILINX_ZYNQ_7015:
-		fpga = fpga015;
-		break;
-	case XILINX_ZYNQ_7020:
-		fpga = fpga020;
-		break;
-	case XILINX_ZYNQ_7030:
-		fpga = fpga030;
-		break;
-	case XILINX_ZYNQ_7035:
-		fpga = fpga035;
-		break;
-	case XILINX_ZYNQ_7045:
-		fpga = fpga045;
-		break;
-	case XILINX_ZYNQ_7100:
-		fpga = fpga100;
-		break;
-	}
-#endif
-
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
 	if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
 		puts("Watchdog: Not found!\n");
@@ -101,12 +43,6 @@ int board_init(void)
 	}
 # endif
 
-#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
-    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
-	fpga_init();
-	fpga_add(fpga_xilinx, &fpga);
-#endif
-
 	return 0;
 }
 
@@ -136,22 +72,6 @@ int board_late_init(void)
 	return 0;
 }
 
-#ifdef CONFIG_DISPLAY_BOARDINFO
-int checkboard(void)
-{
-	u32 version = zynq_get_silicon_version();
-
-	version <<= 1;
-	if (version > (PCW_SILICON_VERSION_3 << 1))
-		version += 1;
-
-	puts("Board: Xilinx Zynq\n");
-	printf("Silicon: v%d.%d\n", version >> 1, version & 1);
-
-	return 0;
-}
-#endif
-
 int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
 {
 #if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \

+ 2 - 0
board/xilinx/zynqmp/Makefile

@@ -24,6 +24,8 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),)
 obj-y += $(init-objs)
 endif
 
+obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
+
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZYNQMP) += cmds.o
 endif

+ 229 - 0
board/xilinx/zynqmp/tap_delays.c

@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+
+#define SD_DLL_CTRL			0xFF180358
+#define SD_ITAP_DLY			0xFF180314
+#define SD_OTAP_DLY			0xFF180318
+#define SD0_DLL_RST_MASK		0x00000004
+#define SD0_DLL_RST			0x00000004
+#define SD1_DLL_RST_MASK		0x00040000
+#define SD1_DLL_RST			0x00040000
+#define SD0_ITAPCHGWIN_MASK		0x00000200
+#define SD0_ITAPCHGWIN			0x00000200
+#define SD1_ITAPCHGWIN_MASK		0x02000000
+#define SD1_ITAPCHGWIN			0x02000000
+#define SD0_ITAPDLYENA_MASK		0x00000100
+#define SD0_ITAPDLYENA			0x00000100
+#define SD1_ITAPDLYENA_MASK		0x01000000
+#define SD1_ITAPDLYENA			0x01000000
+#define SD0_ITAPDLYSEL_MASK		0x000000FF
+#define SD0_ITAPDLYSEL_HSD		0x00000015
+#define SD0_ITAPDLYSEL_SD_DDR50		0x0000003D
+#define SD0_ITAPDLYSEL_MMC_DDR50	0x00000012
+
+#define SD1_ITAPDLYSEL_MASK		0x00FF0000
+#define SD1_ITAPDLYSEL_HSD		0x00150000
+#define SD1_ITAPDLYSEL_SD_DDR50		0x003D0000
+#define SD1_ITAPDLYSEL_MMC_DDR50	0x00120000
+
+#define SD0_OTAPDLYSEL_MASK		0x0000003F
+#define SD0_OTAPDLYSEL_MMC_HSD		0x00000006
+#define SD0_OTAPDLYSEL_SD_HSD		0x00000005
+#define SD0_OTAPDLYSEL_SDR50		0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B0	0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B2	0x00000002
+#define SD0_OTAPDLYSEL_SD_DDR50		0x00000004
+#define SD0_OTAPDLYSEL_MMC_DDR50	0x00000006
+
+#define SD1_OTAPDLYSEL_MASK		0x003F0000
+#define SD1_OTAPDLYSEL_MMC_HSD		0x00060000
+#define SD1_OTAPDLYSEL_SD_HSD		0x00050000
+#define SD1_OTAPDLYSEL_SDR50		0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B0	0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B2	0x00020000
+#define SD1_OTAPDLYSEL_SD_DDR50		0x00040000
+#define SD1_OTAPDLYSEL_MMC_DDR50	0x00060000
+
+#define MMC_BANK2		0x2
+
+#define MMC_TIMING_UHS_SDR25		1
+#define MMC_TIMING_UHS_SDR50		2
+#define MMC_TIMING_UHS_SDR104		3
+#define MMC_TIMING_UHS_DDR50		4
+#define MMC_TIMING_MMC_HS200		5
+#define MMC_TIMING_SD_HS		6
+#define MMC_TIMING_MMC_DDR52		7
+#define MMC_TIMING_MMC_HS		8
+
+void zynqmp_dll_reset(u8 deviceid)
+{
+	/* Issue DLL Reset */
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+				  SD1_DLL_RST);
+
+	mdelay(1);
+
+	/* Release DLL Reset */
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}
+
+static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program OTAP */
+		if (bank == MMC_BANK2)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SDR104_B2);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SDR104_B0);
+	} else {
+		/* Program OTAP */
+		if (bank == MMC_BANK2)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SDR104_B2);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SDR104_B0);
+	}
+}
+
+static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+				  SD0_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+				  SD0_ITAPDLYENA);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+				  SD0_ITAPDLYSEL_HSD);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		if (timing == MMC_TIMING_MMC_HS)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_MMC_HSD);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SD_HSD);
+	} else {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+				  SD1_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+				  SD1_ITAPDLYENA);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+				  SD1_ITAPDLYSEL_HSD);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		if (timing == MMC_TIMING_MMC_HS)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_MMC_HSD);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SD_HSD);
+	}
+}
+
+static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+				  SD0_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+				  SD0_ITAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+					  SD0_ITAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+					  SD0_ITAPDLYSEL_MMC_DDR50);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_MMC_DDR50);
+	} else {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+				  SD1_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+				  SD1_ITAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  SD1_ITAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  SD1_ITAPDLYSEL_MMC_DDR50);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_MMC_DDR50);
+	}
+}
+
+static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+				  SD0_OTAPDLYSEL_SDR50);
+	} else {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+				  SD1_OTAPDLYSEL_SDR50);
+	}
+}
+
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+				  SD1_DLL_RST);
+
+	switch (timing) {
+	case MMC_TIMING_UHS_SDR25:
+		arasan_zynqmp_tap_hs(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_DDR50:
+		arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
+		break;
+	}
+
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}

+ 523 - 0
board/xilinx/zynqmp/zynqmp-zc1275-revB/psu_init_gpl.c

@@ -0,0 +1,523 @@
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+static unsigned long psu_pll_init_data(void)
+{
+	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4E2C62U);
+	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00013C00U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000002U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000200U);
+	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014200U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014800U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000002U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014000U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000004U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000200U);
+
+	return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+	psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
+	psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010502U);
+	psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+	psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000400U);
+	psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000900U);
+	psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
+	psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010A02U);
+	psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010402U);
+	psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010802U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011D02U);
+	psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000104U);
+	psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+	psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000600U);
+	psu_mask_write(0xFD1A0084, 0x07003F07U, 0x07000203U);
+	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000202U);
+	psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
+	psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_init_data(void)
+{
+	psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040001U);
+	psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+	psu_mask_write(0xFD070020, 0x000003F3U, 0x00000100U);
+	psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+	psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00403210U);
+	psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+	psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+	psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x00308034U);
+	psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+	psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+	psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0030051FU);
+	psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020063U);
+	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00290000U);
+	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00000E05U);
+	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x05200004U);
+	psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00110004U);
+	psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x00000000U);
+	psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+	psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+	psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x07080D07U);
+	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x0005020BU);
+	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x03030607U);
+	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00502006U);
+	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x13020206U);
+	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x03030202U);
+	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010003U);
+	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000303U);
+	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x02020909U);
+	psu_mask_write(0xFD070124, 0x40070F3FU, 0x0004040DU);
+	psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x440C011CU);
+	psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x80800020U);
+	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x02009896U);
+	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x04828202U);
+	psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00020304U);
+	psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+	psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+	psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+	psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+	psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000000U);
+	psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
+	psu_mask_write(0xFD070204, 0x001F1F1FU, 0x00080808U);
+	psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x00000000U);
+	psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x00000000U);
+	psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x070F0707U);
+	psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x0F070707U);
+	psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070220, 0x00001F1FU, 0x00000000U);
+	psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
+	psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000604U);
+	psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+	psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
+	psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U);
+	psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U);
+	psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U);
+	psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U);
+	psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU);
+	psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U);
+	psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U);
+	psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU);
+	psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
+	psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
+	psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+	psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F05D90U);
+	psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+	psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x1900C810U);
+	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0x4E200708U);
+	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04061U);
+	psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000DAU);
+	psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040BU);
+	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x040E0A04U);
+	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28100004U);
+	psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0200U);
+	psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x82000800U);
+	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x00682B0AU);
+	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00152504U);
+	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000506U);
+	psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+	psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+	psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000520U);
+	psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000004U);
+	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+	psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800081C7U);
+	psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U);
+	psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U);
+	psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U);
+	psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12340800U);
+	psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+	psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+	psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+	psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0B0U);
+	psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF1032019U);
+	psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U);
+	psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x0088E858U);
+	psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000077BBU);
+	psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+	psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+	psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x000076BBU);
+	psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x40803660U);
+	psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
+	psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
+	psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
+	psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00B000U);
+	psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09093030U);
+	psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70000000U);
+	psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70000000U);
+	psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70000000U);
+	psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70000000U);
+	psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+	psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70000000U);
+	psu_mask_write(0xFD0817C4, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+	return 1;
+}
+
+static unsigned long psu_mio_init_data(void)
+{
+	psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180088, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF18008C, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF180204, 0x0000007FU, 0x00000002U);
+	psu_mask_write(0xFF180208, 0x000FFF8CU, 0x00003004U);
+	psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_pre_init_data(void)
+{
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x00012302U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+	psu_mask_write(0xFD1A0100, 0x0000807CU, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF180320, 0x33800000U, 0x02800000U);
+	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
+	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000200U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000800U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFF000034, 0x000000FFU, 0x00000005U);
+	psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000008FU);
+	psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U);
+	psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U);
+	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
+	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
+	psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
+	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
+	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x01FC9F08U);
+	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+	psu_mask_write(0xFD615000, 0x00000300U, 0x00000200U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+	unsigned int regval = 0;
+	unsigned int pll_retry = 10;
+	unsigned int pll_locked = 0;
+
+	while ((pll_retry > 0) && (!pll_locked)) {
+		Xil_Out32(0xFD080004, 0x00040010);
+		Xil_Out32(0xFD080004, 0x00040011);
+
+		while ((Xil_In32(0xFD080030) & 0x1) != 1)
+			;
+
+		pll_locked = (Xil_In32(0xFD080030) & 0x80000000) >> 31;
+		pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000) >> 16;
+		pll_retry--;
+	}
+	Xil_Out32(0xFD0800C0, Xil_In32(0xFD0800C0) | (pll_retry << 16));
+	Xil_Out32(0xFD080004U, 0x00040063U);
+
+	while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+		;
+	prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+	while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+		;
+	Xil_Out32(0xFD0701B0U, 0x00000001U);
+	Xil_Out32(0xFD070320U, 0x00000001U);
+	while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+		;
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+	Xil_Out32(0xFD080004, 0x0004FE01);
+	regval = Xil_In32(0xFD080030);
+	while (regval != 0x80000FFF)
+		regval = Xil_In32(0xFD080030);
+	Xil_Out32(0xFD070180U, 0x00800020U);
+	Xil_Out32(0xFD070060U, 0x00000000U);
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+	return 1;
+}
+
+static void init_peripheral(void)
+{
+	psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
+}
+
+int psu_init(void)
+{
+	int status = 1;
+
+	status &= psu_mio_init_data();
+	status &= psu_peripherals_pre_init_data();
+	status &= psu_pll_init_data();
+	status &= psu_clock_init_data();
+	status &= psu_ddr_init_data();
+	status &= psu_ddr_phybringup_data();
+	status &= psu_peripherals_init_data();
+	init_peripheral();
+
+	status &= psu_afi_config();
+
+	if (status == 0)
+		return 1;
+	return 0;
+}

+ 1 - 1
board/xilinx/zynqmp/zynqmp-zcu100-revC/psu_init_gpl.c

@@ -481,7 +481,7 @@ static unsigned long psu_mio_init_data(void)
 
 static unsigned long psu_peripherals_init_data(void)
 {
-	psu_mask_write(0xFD1A0100, 0x0001007CU, 0x00000000U);
+	psu_mask_write(0xFD1A0100, 0x0001807CU, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
 	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
 	psu_mask_write(0xFF5E023C, 0x00000FC0U, 0x00000000U);

+ 71 - 9
board/xilinx/zynqmp/zynqmp.c

@@ -9,11 +9,13 @@
 #include <ahci.h>
 #include <scsi.h>
 #include <malloc.h>
+#include <wdt.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/psu_init_gpl.h>
 #include <asm/io.h>
+#include <dm/uclass.h>
 #include <usb.h>
 #include <dwc3-uboot.h>
 #include <zynqmppl.h>
@@ -22,6 +24,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
+static struct udevice *watchdog_dev;
+#endif
+
 #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
     !defined(CONFIG_SPL_BUILD)
 static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
@@ -281,6 +287,11 @@ int board_early_init_f(void)
 	ret = psu_init();
 #endif
 
+#if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD)
+	/* bss is not cleared at time when watchdog_reset() is called */
+	watchdog_dev = NULL;
+#endif
+
 	return ret;
 }
 
@@ -299,9 +310,40 @@ int board_init(void)
 	}
 #endif
 
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
+	if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
+		puts("Watchdog: Not found!\n");
+	} else {
+		wdt_start(watchdog_dev, 0, 0);
+		puts("Watchdog: Started\n");
+	}
+#endif
+
 	return 0;
 }
 
+#ifdef CONFIG_WATCHDOG
+/* Called by macro WATCHDOG_RESET */
+void watchdog_reset(void)
+{
+# if !defined(CONFIG_SPL_BUILD)
+	static ulong next_reset;
+	ulong now;
+
+	if (!watchdog_dev)
+		return;
+
+	now = timer_get_us();
+
+	/* Do not reset the watchdog too often */
+	if (now > next_reset) {
+		wdt_reset(watchdog_dev);
+		next_reset = now + 1000;
+	}
+# endif
+}
+#endif
+
 int board_early_init_r(void)
 {
 	u32 val;
@@ -363,7 +405,15 @@ unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
 #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
 int dram_init_banksize(void)
 {
-	return fdtdec_setup_memory_banksize();
+	int ret;
+
+	ret = fdtdec_setup_memory_banksize();
+	if (ret)
+		return ret;
+
+	mem_map_fill();
+
+	return 0;
 }
 
 int dram_init(void)
@@ -374,6 +424,18 @@ int dram_init(void)
 	return 0;
 }
 #else
+int dram_init_banksize(void)
+{
+#if defined(CONFIG_NR_DRAM_BANKS)
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size = get_effective_memsize();
+#endif
+
+	mem_map_fill();
+
+	return 0;
+}
+
 int dram_init(void)
 {
 	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
@@ -391,6 +453,7 @@ int board_late_init(void)
 {
 	u32 reg = 0;
 	u8 bootmode;
+	int env_targets_len = 0;
 	const char *mode;
 	char *new_targets;
 	char *env_targets;
@@ -467,14 +530,13 @@ int board_late_init(void)
 	 * and default boot_targets
 	 */
 	env_targets = env_get("boot_targets");
-	if (env_targets) {
-		new_targets = calloc(1, strlen(mode) +
-				     strlen(env_targets) + 2);
-		sprintf(new_targets, "%s %s", mode, env_targets);
-	} else {
-		new_targets = calloc(1, strlen(mode) + 2);
-		sprintf(new_targets, "%s", mode);
-	}
+	if (env_targets)
+		env_targets_len = strlen(env_targets);
+
+	new_targets = calloc(1, strlen(mode) + env_targets_len + 2);
+
+	sprintf(new_targets, "%s %s", mode,
+		env_targets ? env_targets : "");
 
 	env_set("boot_targets", new_targets);
 

+ 7 - 0
board/xilinx/zynqmp_r5/MAINTAINERS

@@ -0,0 +1,7 @@
+XILINX_ZYNQMP_R5 BOARDS
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+F:	arch/arm/dts/zynqmp-r5*
+F:	board/xilinx/zynqmp_r5/
+F:	include/configs/xilinx_zynqmp_r5_*
+F:	configs/xilinx_zynqmp_r5_*

+ 6 - 0
board/xilinx/zynqmp_r5/Makefile

@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# (C) Copyright 2018 Xilinx, Inc. (Michal Simek)
+#
+
+obj-y	:= board.o

+ 25 - 0
board/xilinx/zynqmp_r5/board.c

@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Xilinx, Inc. (Michal Simek)
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	return fdtdec_setup_memory_banksize();
+}
+
+int dram_init(void)
+{
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
+
+	return 0;
+}

+ 1 - 0
common/image.c

@@ -159,6 +159,7 @@ static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_VYBRIDIMAGE, "vybridimage",  "Vybrid Boot Image", },
 	{	IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
 	{	IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" },
+	{	IH_TYPE_ZYNQMPBIF,  "zynqmpbif",  "Xilinx ZynqMP Boot Image (bif)" },
 	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
 	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },

+ 0 - 4
configs/microblaze-generic_defconfig

@@ -35,10 +35,6 @@ CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_JFFS2=y
-CONFIG_MTDIDS_DEFAULT="nor0=flash-0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=flash-0:256k(u-boot),256k(env),3m(kernel),1m(romfs),1m(cramfs),-(jffs2)"
-CONFIG_CMD_UBI=y
-# CONFIG_CMD_UBIFS is not set
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NETCONSOLE=y

+ 0 - 1
configs/syzygy_hub_defconfig

@@ -13,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/topic_miami_defconfig

@@ -11,7 +11,6 @@ CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=0
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_PROMPT="zynq-uboot> "

+ 0 - 1
configs/topic_miamilite_defconfig

@@ -11,7 +11,6 @@ CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=0
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_PROMPT="zynq-uboot> "

+ 0 - 1
configs/topic_miamiplus_defconfig

@@ -11,7 +11,6 @@ CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=0
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_PROMPT="zynq-uboot> "

+ 16 - 0
configs/xilinx_zynqmp_r5_defconfig

@@ -0,0 +1,16 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQMP_R5=y
+CONFIG_SYS_TEXT_BASE=0x10000000
+CONFIG_DEFAULT_DEVICE_TREE="zynqmp-r5"
+CONFIG_DEBUG_UART=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SYS_PROMPT="ZynqMP r5> "
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_OF_EMBED=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff010000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_ZYNQ_SERIAL=y
+CONFIG_TIMER=y
+CONFIG_CADENCE_TTC_TIMER=y

+ 0 - 2
configs/xilinx_zynqmp_zc1232_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 # CONFIG_SPL_LIBDISK_SUPPORT is not set
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1232 revA"
 # CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1232-revA"
 CONFIG_DEBUG_UART=y
@@ -13,7 +12,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zc1254_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 # CONFIG_SPL_LIBDISK_SUPPORT is not set
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1254 revA"
 # CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1254-revA"
 CONFIG_DEBUG_UART=y
@@ -13,7 +12,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zc1275_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 # CONFIG_SPL_LIBDISK_SUPPORT is not set
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1275 revA"
 # CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1275-revA"
 CONFIG_DEBUG_UART=y
@@ -13,7 +12,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 53 - 0
configs/xilinx_zynqmp_zc1275_revB_defconfig

@@ -0,0 +1,53 @@
+CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1275_revB"
+CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_TEXT_BASE=0x8000000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
+# CONFIG_SPL_LIBDISK_SUPPORT is not set
+CONFIG_SPL=y
+# CONFIG_SPL_FAT_SUPPORT is not set
+CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1275-revB"
+CONFIG_DEBUG_UART=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_OS_BOOT=y
+CONFIG_SPL_RAM_SUPPORT=y
+CONFIG_SPL_RAM_DEVICE=y
+CONFIG_SPL_ATF=y
+CONFIG_SYS_PROMPT="ZynqMP> "
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_CLK=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_FPGA_LOADBP=y
+CONFIG_CMD_FPGA_LOADP=y
+CONFIG_CMD_MMC=y
+# CONFIG_CMD_NET is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_EMBED=y
+CONFIG_SPL_DM=y
+CONFIG_CLK_ZYNQMP=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ZYNQ=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SF_DUAL_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ZYNQ_SERIAL=y
+CONFIG_EFI_LOADER_BOUNCE_BUFFER=y

+ 0 - 2
configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm015 dc1"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm015-dc1"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 0 - 2
configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig

@@ -5,7 +5,6 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 # CONFIG_SPL_LIBDISK_SUPPORT is not set
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm016 dc2"
 # CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm016-dc2"
@@ -15,7 +14,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 0 - 2
configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm017 dc3"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm017-dc3"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig

@@ -3,7 +3,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm018 dc4"
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm018-dc4"
 CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -11,7 +10,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 0 - 2
configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm019 dc5"
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm019-dc5"
 CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -12,7 +11,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 2 - 2
configs/xilinx_zynqmp_zcu100_revC_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU100 RevC"
 CONFIG_ZYNQ_SDHCI_MAX_FREQ=15000000
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu100-revC"
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
@@ -80,5 +78,7 @@ CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_WDT=y
+CONFIG_WDT_CDNS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y

+ 2 - 2
configs/xilinx_zynqmp_zcu102_rev1_0_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 rev1.0"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-rev1.0"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
@@ -62,6 +60,8 @@ CONFIG_ZYNQ_I2C1=y
 CONFIG_MISC=y
 CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20
 CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ZYNQ=y
 CONFIG_SPI_FLASH=y

+ 0 - 2
configs/xilinx_zynqmp_zcu102_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 revA"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revA"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 0 - 2
configs/xilinx_zynqmp_zcu102_revB_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 revB"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y

+ 0 - 2
configs/xilinx_zynqmp_zcu104_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU104 revA"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu104-revA"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zcu104_revC_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU104 revC"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu104-revC"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zcu106_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU106 revA"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu106-revA"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 2
configs/xilinx_zynqmp_zcu111_revA_defconfig

@@ -4,7 +4,6 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
-CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU111"
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu111-revA"
 CONFIG_DEBUG_UART=y
@@ -14,7 +13,6 @@ CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y

+ 0 - 1
configs/zynq_cc108_defconfig

@@ -11,7 +11,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 1 - 0
configs/zynq_cse_qspi_defconfig

@@ -12,6 +12,7 @@ CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=-1
 # CONFIG_USE_BOOTCOMMAND is not set
 # CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_ARCH_EARLY_INIT_R is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/zynq_microzed_defconfig

@@ -10,7 +10,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_picozed_defconfig

@@ -6,7 +6,6 @@ CONFIG_SPL_STACK_R_ADDR=0x200000
 CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/zynq_z_turn_defconfig

@@ -11,7 +11,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zc702_defconfig

@@ -13,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zc706_defconfig

@@ -13,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zc770_xm010_defconfig

@@ -12,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zc770_xm011_defconfig

@@ -13,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/zynq_zc770_xm011_x16_defconfig

@@ -13,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/zynq_zc770_xm012_defconfig

@@ -12,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_PROMPT="Zynq> "

+ 0 - 1
configs/zynq_zc770_xm013_defconfig

@@ -12,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zed_defconfig

@@ -11,7 +11,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 0 - 1
configs/zynq_zybo_defconfig

@@ -12,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y

+ 20 - 16
drivers/ata/sata_ceva.c

@@ -72,6 +72,10 @@
 #define DRV_NAME	"ahci-ceva"
 #define CEVA_FLAG_BROKEN_GEN2	1
 
+struct ceva_sata_priv {
+	ulong base;
+};
+
 static int ceva_init_sata(ulong mmio)
 {
 	ulong tmp;
@@ -110,18 +114,20 @@ static int ceva_init_sata(ulong mmio)
 	return 0;
 }
 
-static int sata_ceva_probe(struct udevice *dev)
+static int sata_ceva_bind(struct udevice *dev)
 {
-	int ret;
-	struct scsi_platdata *plat = dev_get_uclass_platdata(dev);
+	struct udevice *scsi_dev;
+
+	return ahci_bind_scsi(dev, &scsi_dev);
+}
 
-	ceva_init_sata(plat->base);
+static int sata_ceva_probe(struct udevice *dev)
+{
+	struct ceva_sata_priv *priv = dev_get_priv(dev);
 
-	ret = ahci_init_one_dm(dev);
-	if (ret)
-		return ret;
+	ceva_init_sata(priv->base);
 
-	return ahci_start_ports_dm(dev);
+	return ahci_probe_scsi(dev, priv->base);
 }
 
 static const struct udevice_id sata_ceva_ids[] = {
@@ -131,24 +137,22 @@ static const struct udevice_id sata_ceva_ids[] = {
 
 static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
 {
-	struct scsi_platdata *plat = dev_get_uclass_platdata(dev);
+	struct ceva_sata_priv *priv = dev_get_priv(dev);
 
-	plat->base = devfdt_get_addr(dev);
-	if (plat->base == FDT_ADDR_T_NONE)
+	priv->base = devfdt_get_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	/* Hardcode number for ceva sata controller */
-	plat->max_lun = 1; /* Actually two but untested */
-	plat->max_id = 2;
-
 	return 0;
 }
 
 U_BOOT_DRIVER(ceva_host_blk) = {
 	.name = "ceva_sata",
-	.id = UCLASS_SCSI,
+	.id = UCLASS_AHCI,
 	.of_match = sata_ceva_ids,
+	.bind = sata_ceva_bind,
 	.ops = &scsi_ops,
+	.priv_auto_alloc_size = sizeof(struct ceva_sata_priv),
 	.probe = sata_ceva_probe,
 	.ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
 };

+ 2 - 2
drivers/mmc/mmc.c

@@ -679,7 +679,7 @@ static int mmc_complete_op_cond(struct mmc *mmc)
 {
 	struct mmc_cmd cmd;
 	int timeout = 1000;
-	uint start;
+	ulong start;
 	int err;
 
 	mmc->op_cond_pending = 0;
@@ -2611,7 +2611,7 @@ static int mmc_complete_init(struct mmc *mmc)
 int mmc_init(struct mmc *mmc)
 {
 	int err = 0;
-	__maybe_unused unsigned start;
+	__maybe_unused ulong start;
 #if CONFIG_IS_ENABLED(DM_MMC)
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
 

+ 61 - 4
drivers/mmc/sdhci.c

@@ -151,7 +151,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	u32 mask, flags, mode;
 	unsigned int time = 0, start_addr = 0;
 	int mmc_dev = mmc_get_blk_desc(mmc)->devnum;
-	unsigned start = get_timer(0);
+	ulong start = get_timer(0);
 
 	/* Timeout unit - ms */
 	static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
@@ -160,7 +160,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 
 	/* We shouldn't wait for data inihibit for stop commands, even
 	   though they might use busy signaling */
-	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION ||
+	    cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK)
 		mask &= ~SDHCI_DATA_INHIBIT;
 
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
@@ -182,6 +183,9 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
 
 	mask = SDHCI_INT_RESPONSE;
+	if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+		mask = SDHCI_INT_DATA_AVAIL;
+
 	if (!(cmd->resp_type & MMC_RSP_PRESENT))
 		flags = SDHCI_CMD_RESP_NONE;
 	else if (cmd->resp_type & MMC_RSP_136)
@@ -197,7 +201,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		flags |= SDHCI_CMD_CRC;
 	if (cmd->resp_type & MMC_RSP_OPCODE)
 		flags |= SDHCI_CMD_INDEX;
-	if (data)
+	if (data || cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK)
 		flags |= SDHCI_CMD_DATA;
 
 	/* Set Transfer mode regarding to data flag */
@@ -301,6 +305,24 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		return -ECOMM;
 }
 
+#if defined(CONFIG_DM_MMC) && defined(MMC_SUPPORTS_TUNING)
+static int sdhci_execute_tuning(struct udevice *dev, uint opcode)
+{
+	int err;
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct sdhci_host *host = mmc->priv;
+
+	debug("%s\n", __func__);
+
+	if (host->ops->platform_execute_tuning) {
+		err = host->ops->platform_execute_tuning(mmc, opcode);
+		if (err)
+			return err;
+		return 0;
+	}
+	return 0;
+}
+#endif
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
 	struct sdhci_host *host = mmc->priv;
@@ -325,6 +347,9 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 	if (clock == 0)
 		return 0;
 
+	if (host->ops->set_delay)
+		host->ops->set_delay(host);
+
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/*
 		 * Check if the Host Controller supports Programmable Clock
@@ -439,6 +464,9 @@ static int sdhci_set_ios(struct mmc *mmc)
 	if (mmc->clock != host->clock)
 		sdhci_set_clock(mmc, mmc->clock);
 
+	if (mmc->clk_disable)
+		sdhci_set_clock(mmc, 0);
+
 	/* Set bus width */
 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 	if (mmc->bus_width == 8) {
@@ -514,6 +542,9 @@ int sdhci_probe(struct udevice *dev)
 const struct dm_mmc_ops sdhci_ops = {
 	.send_cmd	= sdhci_send_command,
 	.set_ios	= sdhci_set_ios,
+#ifdef MMC_SUPPORTS_TUNING
+	.execute_tuning	= sdhci_execute_tuning,
+#endif
 };
 #else
 static const struct mmc_ops sdhci_ops = {
@@ -526,7 +557,7 @@ static const struct mmc_ops sdhci_ops = {
 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		u32 f_max, u32 f_min)
 {
-	u32 caps, caps_1;
+	u32 caps, caps_1 = 0;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 
@@ -607,6 +638,32 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		cfg->host_caps &= ~MMC_MODE_HS_52MHz;
 	}
 
+	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
+		caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+
+	if (!(cfg->voltages & MMC_VDD_165_195) ||
+	    (host->quirks & SDHCI_QUIRK_NO_1_8_V))
+		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+			    SDHCI_SUPPORT_DDR50);
+
+	if (caps_1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+		      SDHCI_SUPPORT_DDR50))
+		cfg->host_caps |= MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25);
+
+	if (caps_1 & SDHCI_SUPPORT_SDR104) {
+		cfg->host_caps |= MMC_CAP(UHS_SDR104) | MMC_CAP(UHS_SDR50);
+		/*
+		 * SD3.0: SDR104 is supported so (for eMMC) the caps2
+		 * field can be promoted to support HS200.
+		 */
+		cfg->host_caps |= MMC_CAP(MMC_HS_200);
+	} else if (caps_1 & SDHCI_SUPPORT_SDR50) {
+		cfg->host_caps |= MMC_CAP(UHS_SDR50);
+	}
+
+	if (caps_1 & SDHCI_SUPPORT_DDR50)
+		cfg->host_caps |= MMC_CAP(UHS_DDR50);
+
 	if (host->host_caps)
 		cfg->host_caps |= host->host_caps;
 

+ 226 - 5
drivers/mmc/zynq_sdhci.c

@@ -9,9 +9,11 @@
 #include <common.h>
 #include <dm.h>
 #include <fdtdec.h>
+#include "mmc_private.h"
 #include <linux/libfdt.h>
 #include <malloc.h>
 #include <sdhci.h>
+#include <zynqmp_tap_delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -21,15 +23,212 @@ struct arasan_sdhci_plat {
 	unsigned int f_max;
 };
 
+struct arasan_sdhci_priv {
+	struct sdhci_host *host;
+	u8 deviceid;
+	u8 bank;
+	u8 no_1p8;
+	bool pwrseq;
+};
+
+#if defined(CONFIG_ARCH_ZYNQMP)
+static const u8 mode2timing[] = {
+	     [UHS_SDR12] = UHS_SDR12_BUS_SPEED,
+	     [UHS_SDR25] = UHS_SDR25_BUS_SPEED,
+	     [UHS_SDR50] = UHS_SDR50_BUS_SPEED,
+	     [UHS_SDR104] = UHS_SDR104_BUS_SPEED,
+	     [UHS_DDR50] = UHS_DDR50_BUS_SPEED,
+};
+
+#define SDHCI_HOST_CTRL2	0x3E
+#define SDHCI_CTRL2_MODE_MASK	0x7
+#define SDHCI_18V_SIGNAL	0x8
+#define SDHCI_CTRL_EXEC_TUNING	0x0040
+#define SDHCI_CTRL_TUNED_CLK	0x80
+#define SDHCI_TUNING_LOOP_COUNT	40
+
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+{
+	u16 clk;
+	unsigned long timeout;
+
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	clk &= ~(SDHCI_CLOCK_CARD_EN);
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Issue DLL Reset */
+	zynqmp_dll_reset(deviceid);
+
+	/* Wait max 20 ms */
+	timeout = 100;
+	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+				& SDHCI_CLOCK_INT_STABLE)) {
+		if (timeout == 0) {
+			dev_err(mmc_dev(host->mmc),
+				": Internal clock never stabilised.\n");
+			return;
+		}
+		timeout--;
+		udelay(1000);
+	}
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
+{
+	struct mmc_cmd cmd;
+	struct mmc_data data;
+	u32 ctrl;
+	struct sdhci_host *host;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
+	u8 deviceid;
+
+	debug("%s\n", __func__);
+
+	host = priv->host;
+	deviceid = priv->deviceid;
+
+	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+
+	mdelay(1);
+
+	arasan_zynqmp_dll_reset(host, deviceid);
+
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+
+	do {
+		cmd.cmdidx = opcode;
+		cmd.resp_type = MMC_RSP_R1;
+		cmd.cmdarg = 0;
+
+		data.blocksize = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+
+		if (tuning_loop_counter-- == 0)
+			break;
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
+		    mmc->bus_width == 8)
+			data.blocksize = 128;
+
+		sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
+						    data.blocksize),
+			     SDHCI_BLOCK_SIZE);
+		sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
+		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+		mmc_send_cmd(mmc, &cmd, NULL);
+		ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+			udelay(1);
+
+	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
+
+	if (tuning_loop_counter < 0) {
+		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+		sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+	}
+
+	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+		printf("%s:Tuning failed\n", __func__);
+		return -1;
+	}
+
+	udelay(1);
+	arasan_zynqmp_dll_reset(host, deviceid);
+
+	/* Enable only interrupts served by the SD controller */
+	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
+		     SDHCI_INT_ENABLE);
+	/* Mask all sdhci interrupt sources */
+	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
+
+	return 0;
+}
+
+static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 uhsmode;
+
+	if (!IS_SD(mmc))
+		return;
+
+	uhsmode = mode2timing[mmc->selected_mode];
+
+	if (uhsmode >= UHS_SDR25_BUS_SPEED)
+		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
+					   priv->bank);
+}
+
+static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u32 reg;
+
+	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+		reg |= SDHCI_18V_SIGNAL;
+		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+	}
+
+	if (mmc->selected_mode > SD_HS &&
+	    mmc->selected_mode <= UHS_DDR50) {
+		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+		reg &= ~SDHCI_CTRL2_MODE_MASK;
+		switch (mmc->selected_mode) {
+		case UHS_SDR12:
+			reg |= UHS_SDR12_BUS_SPEED;
+			break;
+		case UHS_SDR25:
+			reg |= UHS_SDR25_BUS_SPEED;
+			break;
+		case UHS_SDR50:
+			reg |= UHS_SDR50_BUS_SPEED;
+			break;
+		case UHS_SDR104:
+			reg |= UHS_SDR104_BUS_SPEED;
+			break;
+		case UHS_DDR50:
+			reg |= UHS_DDR50_BUS_SPEED;
+			break;
+		default:
+			break;
+		}
+		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+	}
+}
+#endif
+
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+const struct sdhci_ops arasan_ops = {
+	.platform_execute_tuning	= &arasan_sdhci_execute_tuning,
+	.set_delay = &arasan_sdhci_set_tapdelay,
+	.set_control_reg = &arasan_sdhci_set_control_reg,
+};
+#endif
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
 	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct sdhci_host *host;
 	struct clk clk;
 	unsigned long clock;
 	int ret;
 
+	host = priv->host;
+
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get clock\n");
@@ -41,6 +240,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
 		dev_err(dev, "failed to get rate\n");
 		return clock;
 	}
+
 	debug("%s: CLK %ld\n", __func__, clock);
 
 	ret = clk_enable(&clk);
@@ -56,6 +256,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
 	host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
 #endif
 
+	if (priv->no_1p8)
+		host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+
 	host->max_clk = clock;
 
 	ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
@@ -73,10 +276,28 @@ static int arasan_sdhci_probe(struct udevice *dev)
 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 {
 	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+
+	priv->host = calloc(1, sizeof(struct sdhci_host));
+	if (!priv->host)
+		return -1;
 
-	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	priv->host->name = dev->name;
+	priv->host->ioaddr = (void *)devfdt_get_addr(dev);
+
+	priv->deviceid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					"xlnx,device_id", -1);
+	priv->bank = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+				    "xlnx,mio_bank", -1);
+	if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev),
+			     "no-1-8-v", NULL))
+		priv->no_1p8 = 1;
+	else
+		priv->no_1p8 = 0;
+
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+	priv->host->ops = &arasan_ops;
+#endif
 
 	plat->f_max = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				"max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ);
@@ -104,6 +325,6 @@ U_BOOT_DRIVER(arasan_sdhci_drv) = {
 	.ops		= &sdhci_ops,
 	.bind		= arasan_sdhci_bind,
 	.probe		= arasan_sdhci_probe,
-	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.priv_auto_alloc_size = sizeof(struct arasan_sdhci_priv),
 	.platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat),
 };

+ 53 - 1
drivers/mtd/nand/zynq_nand.c

@@ -16,6 +16,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand_ecc.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 /* The NAND flash driver defines */
 #define ZYNQ_NAND_CMD_PHASE		1
@@ -83,6 +84,18 @@
 #define ZYNQ_NAND_ECC_BUSY	(1 << 6)	/* ECC block is busy */
 #define ZYNQ_NAND_ECC_MASK	0x00FFFFFF	/* ECC value mask */
 
+#define ZYNQ_NAND_ROW_ADDR_CYCL_MASK	0x0F
+#define ZYNQ_NAND_COL_ADDR_CYCL_MASK	0xF0
+
+#define ZYNQ_NAND_MIO_NUM_NAND_8BIT	13
+#define ZYNQ_NAND_MIO_NUM_NAND_16BIT	8
+
+enum zynq_nand_bus_width {
+	NAND_BW_UNKNOWN = -1,
+	NAND_BW_8BIT,
+	NAND_BW_16BIT,
+};
+
 #ifndef NAND_CMD_LOCK_TIGHT
 #define NAND_CMD_LOCK_TIGHT 0x2c
 #endif
@@ -768,6 +781,7 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
 {
 	struct nand_chip *chip = mtd->priv;
 	const struct zynq_nand_command_format *curr_cmd = NULL;
+	u8 addr_cycles = 0;
 	struct zynq_nand_info *xnand = (struct zynq_nand_info *)chip->priv;
 	void *cmd_addr;
 	unsigned long cmd_data = 0;
@@ -818,8 +832,18 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
 	else
 		end_cmd = curr_cmd->end_cmd;
 
+	if (command == NAND_CMD_READ0 ||
+	    command == NAND_CMD_SEQIN) {
+		addr_cycles = chip->onfi_params.addr_cycles &
+				ZYNQ_NAND_ROW_ADDR_CYCL_MASK;
+		addr_cycles += ((chip->onfi_params.addr_cycles &
+				ZYNQ_NAND_COL_ADDR_CYCL_MASK) >> 4);
+	} else {
+		addr_cycles = curr_cmd->addr_cycles;
+	}
+
 	cmd_phase_addr = (unsigned long)xnand->nand_base	|
-			(curr_cmd->addr_cycles << ADDR_CYCLES_SHIFT)	|
+			(addr_cycles << ADDR_CYCLES_SHIFT)	|
 			(end_cmd_valid << END_CMD_VALID_SHIFT)		|
 			(COMMAND_PHASE)					|
 			(end_cmd << END_CMD_SHIFT)			|
@@ -1005,6 +1029,23 @@ static int zynq_nand_device_ready(struct mtd_info *mtd)
 	return 0;
 }
 
+static int zynq_nand_check_is_16bit_bw_flash(void)
+{
+	int is_16bit_bw = NAND_BW_UNKNOWN;
+	int mio_num_8bit = 0, mio_num_16bit = 0;
+
+	mio_num_8bit = zynq_slcr_get_mio_pin_status("nand8");
+	if (mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT)
+		is_16bit_bw = NAND_BW_8BIT;
+
+	mio_num_16bit = zynq_slcr_get_mio_pin_status("nand16");
+	if (mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT &&
+	    mio_num_16bit == ZYNQ_NAND_MIO_NUM_NAND_16BIT)
+		is_16bit_bw = NAND_BW_16BIT;
+
+	return is_16bit_bw;
+}
+
 static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
 {
 	struct zynq_nand_info *xnand;
@@ -1016,6 +1057,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
 	unsigned long ecc_cfg;
 	int ondie_ecc_enabled = 0;
 	int err = -1;
+	int is_16bit_bw;
 
 	xnand = calloc(1, sizeof(struct zynq_nand_info));
 	if (!xnand) {
@@ -1045,6 +1087,16 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
 	nand_chip->read_buf = zynq_nand_read_buf;
 	nand_chip->write_buf = zynq_nand_write_buf;
 
+	is_16bit_bw = zynq_nand_check_is_16bit_bw_flash();
+	if (is_16bit_bw == NAND_BW_UNKNOWN) {
+		printf("%s: Unable detect NAND based on MIO settings\n",
+		       __func__);
+		goto fail;
+	}
+
+	if (is_16bit_bw == NAND_BW_16BIT)
+		nand_chip->options = NAND_BUSWIDTH_16;
+
 	nand_chip->bbt_options = NAND_BBT_USE_FLASH;
 
 	/* Initialize the NAND flash interface on NAND controller */

+ 1 - 1
drivers/serial/Kconfig

@@ -624,7 +624,7 @@ config STM32_SERIAL
 
 config ZYNQ_SERIAL
 	bool "Cadence (Xilinx Zynq) UART support"
-	depends on DM_SERIAL && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
+	depends on DM_SERIAL && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_ZYNQMP_R5)
 	help
 	  This driver supports the Cadence UART. It is found e.g. in Xilinx
 	  Zynq/ZynqMP.

+ 0 - 1
drivers/serial/serial_zynq.c

@@ -14,7 +14,6 @@
 #include <asm/io.h>
 #include <linux/compiler.h>
 #include <serial.h>
-#include <asm/arch/hardware.h>
 
 #define ZYNQ_UART_SR_TXEMPTY	(1 << 3) /* TX FIFO empty */
 #define ZYNQ_UART_SR_TXACTIVE	(1 << 11)  /* TX active */

+ 7 - 0
drivers/timer/Kconfig

@@ -52,6 +52,13 @@ config ATMEL_PIT_TIMER
 	  it is designed to offer maximum accuracy and efficient management,
 	  even for systems with long response time.
 
+config CADENCE_TTC_TIMER
+	bool "Cadence TTC (Triple Timer Counter)"
+	depends on TIMER
+	help
+	  Enables support for the cadence ttc driver. This driver is present
+	  on Xilinx Zynq and ZynqMP SoCs.
+
 config SANDBOX_TIMER
 	bool "Sandbox timer support"
 	depends on SANDBOX && TIMER

+ 1 - 0
drivers/timer/Makefile

@@ -4,6 +4,7 @@
 
 obj-y += timer-uclass.o
 obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
+obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence-ttc.o
 obj-$(CONFIG_SANDBOX_TIMER)	+= sandbox_timer.o
 obj-$(CONFIG_X86_TSC_TIMER)	+= tsc_timer.o
 obj-$(CONFIG_OMAP_TIMER)	+= omap-timer.o

+ 91 - 0
drivers/timer/cadence-ttc.c

@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Xilinx, Inc. (Michal Simek)
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+#define CNT_CNTRL_RESET		BIT(4)
+
+struct cadence_ttc_regs {
+	u32 clk_cntrl1; /* 0x0 - Clock Control 1 */
+	u32 clk_cntrl2; /* 0x4 - Clock Control 2 */
+	u32 clk_cntrl3; /* 0x8 - Clock Control 3 */
+	u32 counter_cntrl1; /* 0xC - Counter Control 1 */
+	u32 counter_cntrl2; /* 0x10 - Counter Control 2 */
+	u32 counter_cntrl3; /* 0x14 - Counter Control 3 */
+	u32 counter_val1; /* 0x18 - Counter Control 1 */
+	u32 counter_val2; /* 0x1C - Counter Control 2 */
+	u32 counter_val3; /* 0x20 - Counter Control 3 */
+	u32 reserved[15];
+	u32 interrupt_enable1; /* 0x60 - Interrupt Enable 1 */
+	u32 interrupt_enable2; /* 0x64 - Interrupt Enable 2 */
+	u32 interrupt_enable3; /* 0x68 - Interrupt Enable 3 */
+};
+
+struct cadence_ttc_priv {
+	struct cadence_ttc_regs *regs;
+};
+
+static int cadence_ttc_get_count(struct udevice *dev, u64 *count)
+{
+	struct cadence_ttc_priv *priv = dev_get_priv(dev);
+
+	*count = readl(&priv->regs->counter_val1);
+
+	return 0;
+}
+
+static int cadence_ttc_probe(struct udevice *dev)
+{
+	struct cadence_ttc_priv *priv = dev_get_priv(dev);
+
+	/* Disable interrupts for sure */
+	writel(0, &priv->regs->interrupt_enable1);
+	writel(0, &priv->regs->interrupt_enable2);
+	writel(0, &priv->regs->interrupt_enable3);
+
+	/* Make sure that clocks are configured properly without prescaller */
+	writel(0, &priv->regs->clk_cntrl1);
+	writel(0, &priv->regs->clk_cntrl2);
+	writel(0, &priv->regs->clk_cntrl3);
+
+	/* Reset and enable this counter */
+	writel(CNT_CNTRL_RESET, &priv->regs->counter_cntrl1);
+
+	return 0;
+}
+
+static int cadence_ttc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct cadence_ttc_priv *priv = dev_get_priv(dev);
+
+	priv->regs = map_physmem(devfdt_get_addr(dev),
+				 sizeof(struct cadence_ttc_regs), MAP_NOCACHE);
+
+	return 0;
+}
+
+static const struct timer_ops cadence_ttc_ops = {
+	.get_count = cadence_ttc_get_count,
+};
+
+static const struct udevice_id cadence_ttc_ids[] = {
+	{ .compatible = "cdns,ttc" },
+	{}
+};
+
+U_BOOT_DRIVER(cadence_ttc) = {
+	.name = "cadence_ttc",
+	.id = UCLASS_TIMER,
+	.of_match = cadence_ttc_ids,
+	.ofdata_to_platdata = cadence_ttc_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct cadence_ttc_priv),
+	.probe = cadence_ttc_probe,
+	.ops = &cadence_ttc_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};

+ 2 - 2
drivers/watchdog/cdns_wdt.c

@@ -142,13 +142,13 @@ static int cdns_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
 		return -1;
 	}
 
-	debug("%s: CLK_FREQ %ld, timeout %lld\n", __func__, clk_f, timeout);
-
 	if ((timeout < CDNS_WDT_MIN_TIMEOUT) ||
 	    (timeout > CDNS_WDT_MAX_TIMEOUT)) {
 		timeout = priv->timeout;
 	}
 
+	debug("%s: CLK_FREQ %ld, timeout %lld\n", __func__, clk_f, timeout);
+
 	if (clk_f <= CDNS_WDT_CLK_75MHZ) {
 		prescaler = CDNS_WDT_PRESCALE_512;
 		ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512;

+ 51 - 0
include/configs/xilinx_zynqmp_r5.h

@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2018 Xilinx, Inc. (Michal Simek)
+ */
+
+#ifndef __CONFIG_ZYNQMP_R5_H
+#define __CONFIG_ZYNQMP_R5_H
+
+#define CONFIG_EXTRA_ENV_SETTINGS
+
+/* CPU clock */
+#define CONFIG_CPU_FREQ_HZ	500000000
+
+/* Serial drivers */
+/* The following table includes the supported baudrates */
+#define CONFIG_SYS_BAUDRATE_TABLE  \
+	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
+
+# define CONFIG_ENV_SIZE	(128 << 10)
+
+/* Allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/* Boot configuration */
+#define CONFIG_SYS_LOAD_ADDR		0 /* default? */
+
+#define CONFIG_SYS_MAXARGS		32 /* max number of command args */
+
+#define CONFIG_NR_DRAM_BANKS		1
+
+#define CONFIG_SYS_MALLOC_LEN		0x1400000
+
+#define CONFIG_SYS_INIT_RAM_ADDR	0xFFFF0000
+#define CONFIG_SYS_INIT_RAM_SIZE	0x1000
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INIT_RAM_ADDR + \
+					CONFIG_SYS_INIT_RAM_SIZE - \
+					GENERATED_GBL_DATA_SIZE)
+
+/* Extend size of kernel image for uncompression */
+#define CONFIG_SYS_BOOTM_LEN	(60 * 1024 * 1024)
+
+#define CONFIG_SYS_UBOOT_START	CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/* 0x0 - 0x40 is used for placing exception vectors */
+#define CONFIG_SYS_MEMTEST_START	0x40
+#define CONFIG_SYS_MEMTEST_END		0x100
+#define CONFIG_SYS_MEMTEST_SCRATCH	0
+
+#endif /* __CONFIG_ZYNQ_ZYNQMP_R5_H */

+ 16 - 0
include/configs/xilinx_zynqmp_zc1275_revB.h

@@ -0,0 +1,16 @@
+/*
+ * Configuration for Xilinx ZynqMP zc1275 RevB
+ *
+ * (C) Copyright 2018 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZC1275_REVB_H
+#define __CONFIG_ZYNQMP_ZC1275_REVB_H
+
+#define CONFIG_ZYNQ_SDHCI1
+
+#include <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZC1275_REVB_H */

+ 1 - 0
include/image.h

@@ -268,6 +268,7 @@ enum {
 	IH_TYPE_RKSPI,			/* Rockchip SPI image		*/
 	IH_TYPE_ZYNQIMAGE,		/* Xilinx Zynq Boot Image */
 	IH_TYPE_ZYNQMPIMAGE,		/* Xilinx ZynqMP Boot Image */
+	IH_TYPE_ZYNQMPBIF,		/* Xilinx ZynqMP Boot Image (bif) */
 	IH_TYPE_FPGA,			/* FPGA Image */
 	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
 	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */

+ 8 - 0
include/sdhci.h

@@ -166,6 +166,11 @@
 #define  SDHCI_CAN_64BIT	BIT(28)
 
 #define SDHCI_CAPABILITIES_1	0x44
+#define  SDHCI_SUPPORT_SDR50	0x00000001
+#define  SDHCI_SUPPORT_SDR104	0x00000002
+#define  SDHCI_SUPPORT_DDR50	0x00000004
+#define  SDHCI_USE_SDR50_TUNING	0x00002000
+
 #define  SDHCI_CLOCK_MUL_MASK	0x00FF0000
 #define  SDHCI_CLOCK_MUL_SHIFT	16
 
@@ -220,6 +225,7 @@
 #define SDHCI_QUIRK_BROKEN_HISPD_MODE	BIT(5)
 #define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 6)
 #define SDHCI_QUIRK_USE_WIDE8		(1 << 8)
+#define SDHCI_QUIRK_NO_1_8_V		(1 << 9)
 
 /* to make gcc happy */
 struct sdhci_host;
@@ -242,6 +248,8 @@ struct sdhci_ops {
 	void	(*set_control_reg)(struct sdhci_host *host);
 	void	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
+	int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
+	void (*set_delay)(struct sdhci_host *host);
 };
 
 struct sdhci_host {

+ 19 - 0
include/zynqmp_tap_delay.h

@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ */
+
+#ifndef __ZYNQMP_TAP_DELAY_H__
+#define __ZYNQMP_TAP_DELAY_H__
+
+#ifdef CONFIG_ARCH_ZYNQMP
+void zynqmp_dll_reset(u8 deviceid);
+void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank);
+#else
+inline void zynqmp_dll_reset(u8 deviceid) {}
+inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {}
+#endif
+
+#endif

+ 34 - 55
include/zynqpl.h

@@ -11,23 +11,18 @@
 
 #include <xilinx.h>
 
-#if defined(CONFIG_FPGA_ZYNQPL)
 extern struct xilinx_fpga_op zynq_op;
-# define FPGA_ZYNQPL_OPS	&zynq_op
-#else
-# define FPGA_ZYNQPL_OPS	NULL
-#endif
 
-#define XILINX_ZYNQ_7007S	0x3
-#define XILINX_ZYNQ_7010	0x2
-#define XILINX_ZYNQ_7012S	0x1c
-#define XILINX_ZYNQ_7014S	0x8
-#define XILINX_ZYNQ_7015	0x1b
-#define XILINX_ZYNQ_7020	0x7
-#define XILINX_ZYNQ_7030	0xc
-#define XILINX_ZYNQ_7035	0x12
-#define XILINX_ZYNQ_7045	0x11
-#define XILINX_ZYNQ_7100	0x16
+#define XILINX_ZYNQ_XC7Z007S	0x3
+#define XILINX_ZYNQ_XC7Z010	0x2
+#define XILINX_ZYNQ_XC7Z012S	0x1c
+#define XILINX_ZYNQ_XC7Z014S	0x8
+#define XILINX_ZYNQ_XC7Z015	0x1b
+#define XILINX_ZYNQ_XC7Z020	0x7
+#define XILINX_ZYNQ_XC7Z030	0xc
+#define XILINX_ZYNQ_XC7Z035	0x12
+#define XILINX_ZYNQ_XC7Z045	0x11
+#define XILINX_ZYNQ_XC7Z100	0x16
 
 /* Device Image Sizes */
 #define XILINX_XC7Z007S_SIZE	16669920/8
@@ -41,45 +36,29 @@ extern struct xilinx_fpga_op zynq_op;
 #define XILINX_XC7Z045_SIZE	106571232/8
 #define XILINX_XC7Z100_SIZE	139330784/8
 
-/* Descriptor Macros */
-#define XILINX_XC7Z007S_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z007S_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z007s" }
-
-#define XILINX_XC7Z010_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z010_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z010" }
-
-#define XILINX_XC7Z012S_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z012S_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z012s" }
-
-#define XILINX_XC7Z014S_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z014S_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z014s" }
-
-#define XILINX_XC7Z015_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z015_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z015" }
-
-#define XILINX_XC7Z020_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z020_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z020" }
-
-#define XILINX_XC7Z030_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z030_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z030" }
-
-#define XILINX_XC7Z035_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z035_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z035" }
-
-#define XILINX_XC7Z045_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z045_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z045" }
-
-#define XILINX_XC7Z100_DESC(cookie) \
-{ xilinx_zynq, devcfg, XILINX_XC7Z100_SIZE, NULL, cookie, FPGA_ZYNQPL_OPS, \
-	"7z100" }
+/* Device Names */
+#define XILINX_XC7Z007S_NAME	"7z007s"
+#define XILINX_XC7Z010_NAME	"7z010"
+#define XILINX_XC7Z012S_NAME	"7z012s"
+#define XILINX_XC7Z014S_NAME	"7z014s"
+#define XILINX_XC7Z015_NAME	"7z015"
+#define XILINX_XC7Z020_NAME	"7z020"
+#define XILINX_XC7Z030_NAME	"7z030"
+#define XILINX_XC7Z035_NAME	"7z035"
+#define XILINX_XC7Z045_NAME	"7z045"
+#define XILINX_XC7Z100_NAME	"7z100"
+
+#if defined(CONFIG_FPGA)
+#define ZYNQ_DESC(name) { \
+	.idcode = XILINX_ZYNQ_XC##name, \
+	.fpga_size = XILINX_XC##name##_SIZE, \
+	.devicename = XILINX_XC##name##_NAME \
+	}
+#else
+#define ZYNQ_DESC(name) { \
+	.idcode = XILINX_ZYNQ_XC##name, \
+	.devicename = XILINX_XC##name##_NAME \
+	}
+#endif
 
 #endif /* _ZYNQPL_H_ */

+ 1 - 0
tools/Makefile

@@ -111,6 +111,7 @@ dumpimage-mkimage-objs := aisimage.o \
 			ublimage.o \
 			zynqimage.o \
 			zynqmpimage.o \
+			zynqmpbif.o \
 			$(LIBFDT_OBJS) \
 			gpimage.o \
 			gpimage-common.o \

+ 1 - 0
tools/imagetool.h

@@ -231,6 +231,7 @@ time_t imagetool_get_source_date(
 
 
 void pbl_load_uboot(int fd, struct image_tool_params *mparams);
+int zynqmpbif_copy_image(int fd, struct image_tool_params *mparams);
 
 #define ___cat(a, b) a ## b
 #define __cat(a, b) ___cat(a, b)

+ 7 - 0
tools/mkimage.c

@@ -515,6 +515,13 @@ int main(int argc, char **argv)
 		} else if (params.type == IH_TYPE_PBLIMAGE) {
 			/* PBL has special Image format, implements its' own */
 			pbl_load_uboot(ifd, &params);
+		} else if (params.type == IH_TYPE_ZYNQMPBIF) {
+			/* Image file is meta, walk through actual targets */
+			int ret;
+
+			ret = zynqmpbif_copy_image(ifd, &params);
+			if (ret)
+				return ret;
 		} else {
 			copy_file(ifd, params.datafile, pad_len);
 		}

+ 1008 - 0
tools/zynqmpbif.c

@@ -0,0 +1,1008 @@
+/*
+ * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "imagetool.h"
+#include "mkimage.h"
+#include "zynqmpimage.h"
+#include <elf.h>
+#include <image.h>
+
+struct bif_entry {
+	const char *filename;
+	uint64_t flags;
+	uint64_t dest_cpu;
+	uint64_t exp_lvl;
+	uint64_t dest_dev;
+	uint64_t load;
+	uint64_t entry;
+	size_t offset;
+};
+
+enum bif_flag {
+	BIF_FLAG_AESKEYFILE,
+	BIF_FLAG_INIT,
+	BIF_FLAG_UDF_BH,
+	BIF_FLAG_HEADERSIGNATURE,
+	BIF_FLAG_PPKFILE,
+	BIF_FLAG_PSKFILE,
+	BIF_FLAG_SPKFILE,
+	BIF_FLAG_SSKFILE,
+	BIF_FLAG_SPKSIGNATURE,
+	BIF_FLAG_FSBL_CONFIG,
+	BIF_FLAG_AUTH_PARAMS,
+	BIF_FLAG_KEYSRC_ENCRYPTION,
+	BIF_FLAG_PMUFW_IMAGE,
+	BIF_FLAG_BOOTLOADER,
+	BIF_FLAG_TZ,
+	BIF_FLAG_BH_KEY_IV,
+	BIF_FLAG_BH_KEYFILE,
+	BIF_FLAG_PUF_FILE,
+	BIF_FLAG_AARCH32,
+	BIF_FLAG_PART_OWNER_UBOOT,
+
+	/* Internal flags */
+	BIF_FLAG_BIT_FILE,
+	BIF_FLAG_ELF_FILE,
+	BIF_FLAG_BIN_FILE,
+};
+
+struct bif_flags {
+	const char name[32];
+	uint64_t flag;
+	char *(*parse)(char *line, struct bif_entry *bf);
+};
+
+struct bif_file_type {
+	const char name[32];
+	uint32_t header;
+	int (*add)(struct bif_entry *bf);
+};
+
+struct bif_output {
+	size_t data_len;
+	char *data;
+	struct image_header_table *imgheader;
+	struct zynqmp_header *header;
+	struct partition_header *last_part;
+};
+
+struct bif_output bif_output;
+
+static uint32_t zynqmp_csum(void *start, void *end)
+{
+	uint32_t checksum = 0;
+	uint32_t *ptr32 = start;
+
+	while (ptr32 != end) {
+		checksum += le32_to_cpu(*ptr32);
+		ptr32++;
+	}
+
+	return ~checksum;
+}
+
+static int zynqmpbif_check_params(struct image_tool_params *params)
+{
+	if (!params)
+		return 0;
+
+	if (params->addr != 0x0) {
+		fprintf(stderr, "Error: Load Address can not be specified.\n");
+		return -1;
+	}
+
+	if (params->eflag) {
+		fprintf(stderr, "Error: Entry Point can not be specified.\n");
+		return -1;
+	}
+
+	return !(params->lflag || params->dflag);
+}
+
+static int zynqmpbif_check_image_types(uint8_t type)
+{
+	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static char *parse_dest_cpu(char *line, struct bif_entry *bf)
+{
+	uint64_t i;
+
+	for (i = 0; i < ARRAY_SIZE(dest_cpus); i++) {
+		if (!strncmp(line, dest_cpus[i], strlen(dest_cpus[i]))) {
+			bf->dest_cpu = i << PART_ATTR_DEST_CPU_SHIFT;
+			return line + strlen(dest_cpus[i]);
+		}
+
+		/* a5x can also be written as a53 */
+		if (!strncmp(dest_cpus[i], "a5x", 3)) {
+			char a53[] = "a53-X";
+
+			a53[4] = dest_cpus[i][4];
+			if (!strncmp(line, a53, strlen(a53))) {
+				bf->dest_cpu = i << PART_ATTR_DEST_CPU_SHIFT;
+				return line + strlen(a53);
+			}
+		}
+	}
+
+	return line;
+}
+
+static char *parse_el(char *line, struct bif_entry *bf)
+{
+	const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" };
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dest_els); i++) {
+		if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) {
+			bf->exp_lvl = i;
+			return line + strlen(dest_els[i]);
+		}
+	}
+
+	return line;
+}
+
+static char *parse_load(char *line, struct bif_entry *bf)
+{
+	char *endptr;
+
+	bf->load = strtoll(line, &endptr, 0);
+
+	return endptr;
+}
+
+static char *parse_entry(char *line, struct bif_entry *bf)
+{
+	char *endptr;
+
+	bf->entry = strtoll(line, &endptr, 0);
+
+	return endptr;
+}
+
+static char *parse_offset(char *line, struct bif_entry *bf)
+{
+	char *endptr;
+
+	bf->offset = strtoll(line, &endptr, 0);
+
+	return endptr;
+}
+
+static char *parse_partition_owner(char *line, struct bif_entry *bf)
+{
+	char *endptr = NULL;
+
+	if (!strncmp(line, "fsbl", 4)) {
+		endptr = line + 4;
+	} else if (!strncmp(line, "uboot", 5)) {
+		bf->flags |= 1ULL << BIF_FLAG_PART_OWNER_UBOOT;
+		endptr = line + 5;
+	} else {
+		printf("ERROR: Unknown partition type '%s'\n", line);
+	}
+
+	return endptr;
+}
+
+static const struct bif_flags bif_flags[] = {
+	{ "fsbl_config", BIF_FLAG_FSBL_CONFIG },
+	{ "trustzone", BIF_FLAG_TZ },
+	{ "pmufw_image", BIF_FLAG_PMUFW_IMAGE },
+	{ "bootloader", BIF_FLAG_BOOTLOADER },
+	{ "destination_cpu=", 0, parse_dest_cpu },
+	{ "exception_level=", 0, parse_el },
+	{ "load=", 0, parse_load },
+	{ "startup=", 0, parse_entry },
+	{ "offset=", 0, parse_offset },
+	{ "partition_owner=", 0, parse_partition_owner },
+};
+
+static char *read_full_file(const char *filename, size_t *size)
+{
+	char *buf, *bufp;
+	struct stat sbuf;
+	int len = 0, r, fd;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+
+	if (fstat(fd, &sbuf) < 0)
+		return NULL;
+
+	if (size)
+		*size = sbuf.st_size;
+
+	buf = malloc(sbuf.st_size);
+	if (!buf)
+		return NULL;
+
+	bufp = buf;
+	while (len < sbuf.st_size) {
+		r = read(fd, bufp, sbuf.st_size - len);
+		if (r < 0)
+			return NULL;
+		len += r;
+		bufp += r;
+	}
+
+	close(fd);
+
+	return buf;
+}
+
+static int bif_add_blob(const void *data, size_t len, size_t *offset)
+{
+	size_t new_size;
+	uintptr_t header_off;
+	uintptr_t last_part_off;
+	uintptr_t imgheader_off;
+	uintptr_t old_data = (uintptr_t)bif_output.data;
+	void *new_data;
+
+	header_off = (uintptr_t)bif_output.header - old_data;
+	last_part_off = (uintptr_t)bif_output.last_part - old_data;
+	imgheader_off = (uintptr_t)bif_output.imgheader - old_data;
+
+	if (offset && *offset) {
+		/* Pad to a given offset */
+		if (bif_output.data_len > *offset) {
+			printf("Can not pad to offset %zx\n", *offset);
+			return -1;
+		}
+
+		bif_output.data_len = *offset;
+	}
+
+	new_size = ROUND(bif_output.data_len + len, 64);
+	new_data = realloc(bif_output.data, new_size);
+	memcpy(new_data + bif_output.data_len, data, len);
+	if (offset)
+		*offset = bif_output.data_len;
+	bif_output.data = new_data;
+	bif_output.data_len = new_size;
+
+	/* Readjust internal pointers */
+	if (bif_output.header)
+		bif_output.header = new_data + header_off;
+	if (bif_output.last_part)
+		bif_output.last_part = new_data + last_part_off;
+	if (bif_output.imgheader)
+		bif_output.imgheader = new_data + imgheader_off;
+
+	return 0;
+}
+
+static int bif_init(void)
+{
+	struct zynqmp_header header = { { 0 } };
+	int r;
+
+	zynqmpimage_default_header(&header);
+
+	r = bif_add_blob(&header, sizeof(header), NULL);
+	if (r)
+		return r;
+
+	bif_output.header = (void *)bif_output.data;
+
+	return 0;
+}
+
+static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len)
+{
+	int r;
+
+	if (bif_output.header->image_offset) {
+		printf("PMUFW expected before bootloader in your .bif file!\n");
+		return -1;
+	}
+
+	r = bif_add_blob(data, len, &bf->offset);
+	if (r)
+		return r;
+
+	len = ROUND(len, 64);
+	bif_output.header->pfw_image_length = cpu_to_le32(len);
+	bif_output.header->total_pfw_image_length = cpu_to_le32(len);
+	bif_output.header->image_offset = cpu_to_le32(bf->offset);
+
+	return 0;
+}
+
+static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
+{
+	size_t parthdr_offset = 0;
+	struct partition_header parthdr = {
+		.len_enc = cpu_to_le32(len / 4),
+		.len_unenc = cpu_to_le32(len / 4),
+		.len = cpu_to_le32(len / 4),
+		.entry_point = cpu_to_le64(bf->entry),
+		.load_address = cpu_to_le64(bf->load),
+	};
+	int r;
+	uint32_t csum;
+
+	if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
+		return bif_add_pmufw(bf, data, len);
+
+	r = bif_add_blob(data, len, &bf->offset);
+	if (r)
+		return r;
+
+	parthdr.offset = cpu_to_le32(bf->offset / 4);
+
+	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
+		if (bif_output.last_part) {
+			printf("ERROR: Bootloader expected before others\n");
+			return -1;
+		}
+
+		parthdr.offset = cpu_to_le32(bif_output.header->image_offset);
+		parthdr.len = cpu_to_le32((bf->offset + len -
+			bif_output.header->image_offset) / 4);
+		parthdr.len_enc = parthdr.len;
+		parthdr.len_unenc = parthdr.len;
+	}
+
+	/* Normalize EL */
+	bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3;
+	parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT;
+	parthdr.attributes |= bf->dest_dev;
+	parthdr.attributes |= bf->dest_cpu;
+	if (bf->flags & (1ULL << BIF_FLAG_TZ))
+		parthdr.attributes |= PART_ATTR_TZ_SECURE;
+	if (bf->flags & (1ULL << BIF_FLAG_PART_OWNER_UBOOT))
+		parthdr.attributes |= PART_ATTR_PART_OWNER_UBOOT;
+	switch (bf->dest_cpu) {
+	case PART_ATTR_DEST_CPU_NONE:
+	case PART_ATTR_DEST_CPU_A53_0:
+	case PART_ATTR_DEST_CPU_A53_1:
+	case PART_ATTR_DEST_CPU_A53_2:
+	case PART_ATTR_DEST_CPU_A53_3:
+		if (bf->flags & (1ULL << BIF_FLAG_AARCH32))
+			parthdr.attributes |= PART_ATTR_A53_EXEC_AARCH32;
+	}
+
+	csum = zynqmp_csum(&parthdr, &parthdr.checksum);
+	parthdr.checksum = cpu_to_le32(csum);
+
+	r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
+	if (r)
+		return r;
+
+	/* Add image header table if not there yet */
+	if (!bif_output.imgheader) {
+		size_t imghdr_off = 0;
+		struct image_header_table imghdr = {
+			.version = cpu_to_le32(0x01020000),
+			.nr_parts = 0,
+		};
+
+		r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
+		if (r)
+			return r;
+
+		bif_output.header->image_header_table_offset = imghdr_off;
+		bif_output.imgheader = (void *)(bif_output.data + imghdr_off);
+	}
+
+	bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
+		bif_output.imgheader->nr_parts) + 1);
+
+	/* Link to this partition header */
+	if (bif_output.last_part) {
+		bif_output.last_part->next_partition_offset =
+			cpu_to_le32(parthdr_offset / 4);
+
+		/* Recalc checksum of last_part */
+		csum = zynqmp_csum(bif_output.last_part,
+				   &bif_output.last_part->checksum);
+		bif_output.last_part->checksum = cpu_to_le32(csum);
+	} else {
+		bif_output.imgheader->partition_header_offset =
+			cpu_to_le32(parthdr_offset / 4);
+	}
+	bif_output.last_part = (void *)(bif_output.data + parthdr_offset);
+
+	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
+		bif_output.header->image_load = cpu_to_le32(bf->load);
+		if (!bif_output.header->image_offset)
+			bif_output.header->image_offset =
+				cpu_to_le32(bf->offset);
+		bif_output.header->image_size = cpu_to_le32(len);
+		bif_output.header->image_stored_size = cpu_to_le32(len);
+
+		bif_output.header->image_attributes &= ~HEADER_CPU_SELECT_MASK;
+		switch (bf->dest_cpu) {
+		default:
+		case PART_ATTR_DEST_CPU_A53_0:
+			if (bf->flags & BIF_FLAG_AARCH32)
+				bif_output.header->image_attributes |=
+					HEADER_CPU_SELECT_A53_32BIT;
+			else
+				bif_output.header->image_attributes |=
+					HEADER_CPU_SELECT_A53_64BIT;
+			break;
+		case PART_ATTR_DEST_CPU_R5_0:
+			bif_output.header->image_attributes |=
+				HEADER_CPU_SELECT_R5_SINGLE;
+			break;
+		case PART_ATTR_DEST_CPU_R5_L:
+			bif_output.header->image_attributes |=
+				HEADER_CPU_SELECT_R5_DUAL;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/* Add .bit bitstream */
+static int bif_add_bit(struct bif_entry *bf)
+{
+	char *bit = read_full_file(bf->filename, NULL);
+	char *bitbin;
+	uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
+				     0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
+	uint16_t len;
+	uint32_t bitlen;
+	int i;
+
+	if (!bit)
+		return -1;
+
+	/* Skip initial header */
+	if (memcmp(bit, initial_header, sizeof(initial_header)))
+		return -1;
+
+	bit += sizeof(initial_header);
+
+	/* Design name */
+	len = be16_to_cpu(*(uint16_t *)bit);
+	bit += sizeof(uint16_t);
+	debug("Design: %s\n", bit);
+	bit += len;
+
+	/* Device identifier */
+	if (*bit != 'b')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t *)bit);
+	bit += sizeof(uint16_t);
+	debug("Device: %s\n", bit);
+	bit += len;
+
+	/* Date */
+	if (*bit != 'c')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t *)bit);
+	bit += sizeof(uint16_t);
+	debug("Date: %s\n", bit);
+	bit += len;
+
+	/* Time */
+	if (*bit != 'd')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t *)bit);
+	bit += sizeof(uint16_t);
+	debug("Time: %s\n", bit);
+	bit += len;
+
+	/* Bitstream length */
+	if (*bit != 'e')
+		return -1;
+	bit++;
+	bitlen = be32_to_cpu(*(uint32_t *)bit);
+	bit += sizeof(uint32_t);
+	bitbin = bit;
+
+	debug("Bitstream Length: 0x%x\n", bitlen);
+	for (i = 0; i < bitlen; i += sizeof(uint32_t)) {
+		uint32_t *bitbin32 = (uint32_t *)&bitbin[i];
+		*bitbin32 = __swab32(*bitbin32);
+	}
+
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
+
+	bf->load = 0xffffffff;
+	bf->entry = 0;
+
+	bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
+	return bif_add_part(bf, bit, bitlen);
+}
+
+/* Add .bin bitstream */
+static int bif_add_bin(struct bif_entry *bf)
+{
+	size_t size;
+	char *bin = read_full_file(bf->filename, &size);
+
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
+
+	bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
+	return bif_add_part(bf, bin, size);
+}
+
+/* Add elf file */
+static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
+{
+	Elf64_Ehdr *ehdr;
+	Elf64_Shdr *shdr;
+	size_t min_addr = -1, max_addr = 0;
+	char *flat;
+	int i;
+
+	ehdr = (void *)elf;
+	shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff));
+
+	/* Look for smallest / biggest address */
+	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) {
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC) ||
+		    (shdr->sh_type == SHT_NOBITS))
+			continue;
+
+		if (le64_to_cpu(shdr->sh_addr) < min_addr)
+			min_addr = le64_to_cpu(shdr->sh_addr);
+		if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) >
+			max_addr)
+			max_addr = le64_to_cpu(shdr->sh_addr) +
+				   le64_to_cpu(shdr->sh_size);
+	}
+
+	*load_addr = min_addr;
+	*flat_size = max_addr - min_addr;
+	flat = calloc(1, *flat_size);
+	if (!flat)
+		return NULL;
+
+	shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff));
+	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) {
+		char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr;
+		char *src = elf + le64_to_cpu(shdr->sh_offset);
+
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC))
+			continue;
+
+		if (shdr->sh_type != SHT_NOBITS)
+			memcpy(dst, src, le64_to_cpu(shdr->sh_size));
+	}
+
+	return flat;
+}
+
+static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
+{
+	Elf32_Ehdr *ehdr;
+	Elf32_Shdr *shdr;
+	size_t min_addr = -1, max_addr = 0;
+	char *flat;
+	int i;
+
+	ehdr = (void *)elf;
+	shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff));
+
+	/* Look for smallest / biggest address */
+	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) {
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC) ||
+		    (shdr->sh_type == SHT_NOBITS))
+			continue;
+
+		if (le32_to_cpu(shdr->sh_addr) < min_addr)
+			min_addr = le32_to_cpu(shdr->sh_addr);
+		if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) >
+			max_addr)
+			max_addr = le32_to_cpu(shdr->sh_addr) +
+				   le32_to_cpu(shdr->sh_size);
+	}
+
+	*load_addr = min_addr;
+	*flat_size = max_addr - min_addr;
+	flat = calloc(1, *flat_size);
+	if (!flat)
+		return NULL;
+
+	shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff));
+	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) {
+		char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr;
+		char *src = elf + le32_to_cpu(shdr->sh_offset);
+
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC))
+			continue;
+
+		if (shdr->sh_type != SHT_NOBITS)
+			memcpy(dst, src, le32_to_cpu(shdr->sh_size));
+	}
+
+	return flat;
+}
+
+static int bif_add_elf(struct bif_entry *bf)
+{
+	size_t size;
+	size_t elf_size;
+	char *elf;
+	char *flat;
+	size_t load_addr;
+	Elf32_Ehdr *ehdr32;
+	Elf64_Ehdr *ehdr64;
+
+	elf = read_full_file(bf->filename, &elf_size);
+	if (!elf)
+		return -1;
+
+	ehdr32 = (void *)elf;
+	ehdr64 = (void *)elf;
+
+	switch (ehdr32->e_ident[EI_CLASS]) {
+	case ELFCLASS32:
+		flat = elf2flat32(elf, &size, &load_addr);
+		bf->entry = le32_to_cpu(ehdr32->e_entry);
+		bf->flags |= 1ULL << BIF_FLAG_AARCH32;
+		break;
+	case ELFCLASS64:
+		flat = elf2flat64(elf, &size, &load_addr);
+		bf->entry = le64_to_cpu(ehdr64->e_entry);
+		break;
+	default:
+		printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
+		return -1;
+	}
+
+	if (!flat)
+		return -1;
+
+	bf->load = load_addr;
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
+
+	bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
+	return bif_add_part(bf, flat, size);
+}
+
+static const struct bif_file_type bif_file_types[] = {
+	{
+		.name = "bitstream (.bit)",
+		.header = 0x00090ff0,
+		.add = bif_add_bit,
+	},
+
+	{
+		.name = "ELF",
+		.header = 0x7f454c46,
+		.add = bif_add_elf,
+	},
+
+	/* Anything else is a .bin file */
+	{
+		.name = ".bin",
+		.add = bif_add_bin,
+	},
+};
+
+static int bif_fsbl_config(struct bif_entry *fsbl_config,
+			   struct bif_entry *entries, int nr_entries)
+{
+	int i;
+	int config_set = 0;
+	struct {
+		const char *name;
+		uint64_t flags;
+		uint64_t dest_cpu;
+	} configs[] = {
+		{ .name = "a5x_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 },
+		{ .name = "a53_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 },
+		{ .name = "a5x_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0,
+				     .flags = 1ULL << BIF_FLAG_AARCH32 },
+		{ .name = "a53_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0,
+				     .flags = 1ULL << BIF_FLAG_AARCH32 },
+		{ .name = "r5_single", .dest_cpu = PART_ATTR_DEST_CPU_R5_0 },
+		{ .name = "r5_dual", .dest_cpu = PART_ATTR_DEST_CPU_R5_L },
+	};
+
+	/* Set target CPU of bootloader entry */
+	for (i = 0; i < nr_entries; i++) {
+		struct bif_entry *b = &entries[i];
+		const char *config_attr = fsbl_config->filename;
+		int j;
+
+		if (!(b->flags & (1ULL << BIF_FLAG_BOOTLOADER)))
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(configs); j++) {
+			if (!strncmp(config_attr, configs[j].name,
+				     strlen(configs[j].name))) {
+				b->dest_cpu = configs[j].dest_cpu;
+				b->flags |= configs[j].flags;
+				config_set = 1;
+			}
+		}
+
+		if (!config_set) {
+			printf("ERROR: Unsupported fsbl_config: %s\n",
+			       config_attr);
+			return -1;
+		}
+	}
+
+	if (!config_set) {
+		printf("ERROR: fsbl_config w/o bootloader\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static const struct bif_flags *find_flag(char *str)
+{
+	const struct bif_flags *bf;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
+		bf = &bif_flags[i];
+		if (!strncmp(bf->name, str, strlen(bf->name)))
+			return bf;
+	}
+
+	printf("ERROR: Flag '%s' not found\n", str);
+
+	return NULL;
+}
+
+static int bif_open_file(struct bif_entry *entry)
+{
+	int fd = open(entry->filename, O_RDONLY);
+
+	if (fd < 0)
+		printf("Error opening file %s\n", entry->filename);
+
+	return fd;
+}
+
+static const struct bif_file_type *get_file_type(struct bif_entry *entry)
+{
+	int fd = bif_open_file(entry);
+	uint32_t header;
+	int i;
+
+	if (fd < 0)
+		return NULL;
+
+	if (read(fd, &header, sizeof(header)) != sizeof(header)) {
+		printf("Error reading file %s", entry->filename);
+		return NULL;
+	}
+
+	close(fd);
+
+	for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
+		const struct bif_file_type *type = &bif_file_types[i];
+
+		if (!type->header)
+			return type;
+		if (type->header == be32_to_cpu(header))
+			return type;
+	}
+
+	return NULL;
+}
+
+#define NEXT_CHAR(str, chr) ({		\
+	char *_n = strchr(str, chr);	\
+	if (!_n)			\
+		goto err;		\
+	_n;				\
+})
+
+static char *skip_whitespace(char *str)
+{
+	while (*str == ' ' || *str == '\t')
+		str++;
+
+	return str;
+}
+
+int zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
+{
+	char *bif, *bifp, *bifpn;
+	char *line;
+	struct bif_entry entries[32] = { { 0 } };
+	int nr_entries = 0;
+	struct bif_entry *entry = entries;
+	size_t len;
+	int i;
+	uint32_t csum;
+	int bldr = -1;
+
+	bif_init();
+
+	/* Read .bif input file */
+	bif = read_full_file(mparams->datafile, NULL);
+	if (!bif)
+		goto err;
+
+	/* Interpret .bif file */
+	bifp = bif;
+
+	/* A bif description starts with a { section */
+	bifp = NEXT_CHAR(bifp, '{') + 1;
+
+	/* Read every line */
+	while (1) {
+		bifpn = NEXT_CHAR(bifp, '\n');
+
+		if (bifpn[-1] == '\r')
+			bifpn[-1] = '\0';
+
+		*bifpn = '\0';
+		bifpn++;
+		line = bifp;
+
+		line = skip_whitespace(line);
+
+		/* Attributes? */
+		if (*line == '[') {
+			line++;
+			while (1) {
+				const struct bif_flags *bf;
+
+				line = skip_whitespace(line);
+				bf = find_flag(line);
+				if (!bf)
+					goto err;
+
+				line += strlen(bf->name);
+				if (bf->parse)
+					line = bf->parse(line, entry);
+				else
+					entry->flags |= 1ULL << bf->flag;
+
+				if (!line)
+					goto err;
+
+				/* Go to next attribute or quit */
+				if (*line == ']') {
+					line++;
+					break;
+				}
+				if (*line == ',')
+					line++;
+			}
+		}
+
+		/* End of image description */
+		if (*line == '}')
+			break;
+
+		if (*line) {
+			line = skip_whitespace(line);
+			entry->filename = line;
+			nr_entries++;
+			entry++;
+		}
+
+		/* Use next line */
+		bifp = bifpn;
+	}
+
+	for (i = 0; i < nr_entries; i++) {
+		debug("Entry flags=%#lx name=%s\n", entries[i].flags,
+		      entries[i].filename);
+	}
+
+	/*
+	 * Some entries are actually configuration option for other ones,
+	 * let's apply them in an intermediate step.
+	 */
+	for (i = 0; i < nr_entries; i++) {
+		struct bif_entry *entry = &entries[i];
+
+		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
+			if (bif_fsbl_config(entry, entries, nr_entries))
+				goto err;
+	}
+
+	/* Make sure PMUFW comes before bootloader */
+	for (i = 0; i < nr_entries; i++) {
+		struct bif_entry *entry = &entries[i];
+
+		if (entry->flags & (1ULL << BIF_FLAG_BOOTLOADER))
+			bldr = i;
+		if (entry->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) {
+			if (bldr >= 0) {
+				struct bif_entry tmp = *entry;
+
+				*entry = entries[bldr];
+				entries[bldr] = tmp;
+			}
+		}
+	}
+
+	for (i = 0; i < nr_entries; i++) {
+		struct bif_entry *entry = &entries[i];
+		const struct bif_file_type *type;
+		int r;
+
+		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
+			continue;
+
+		type = get_file_type(entry);
+		if (!type)
+			goto err;
+
+		debug("type=%s file=%s\n", type->name, entry->filename);
+		r = type->add(entry);
+		if (r)
+			goto err;
+	}
+
+	/* Calculate checksums */
+	csum = zynqmp_csum(&bif_output.header->width_detection,
+			   &bif_output.header->checksum);
+	bif_output.header->checksum = cpu_to_le32(csum);
+
+	if (bif_output.imgheader) {
+		csum = zynqmp_csum(bif_output.imgheader,
+				   &bif_output.imgheader->checksum);
+		bif_output.imgheader->checksum = cpu_to_le32(csum);
+	}
+
+	/* Write headers and components */
+	if (lseek(outfd, 0, SEEK_SET) != 0)
+		goto err;
+
+	len = bif_output.data_len;
+	bifp = bif_output.data;
+	while (len) {
+		int r;
+
+		r = write(outfd, bifp, len);
+		if (r < 0)
+			goto err;
+		len -= r;
+		bifp += r;
+	}
+
+	return 0;
+
+err:
+	fprintf(stderr, "Error: Failed to create image.\n");
+	return -1;
+}
+
+/* Needs to be stubbed out so we can print after creation */
+static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
+				 struct image_tool_params *params)
+{
+}
+
+static struct zynqmp_header zynqmpimage_header;
+
+U_BOOT_IMAGE_TYPE(
+	zynqmpbif,
+	"Xilinx ZynqMP Boot Image support (bif)",
+	sizeof(struct zynqmp_header),
+	(void *)&zynqmpimage_header,
+	zynqmpbif_check_params,
+	NULL,
+	zynqmpimage_print_header,
+	zynqmpbif_set_header,
+	NULL,
+	zynqmpbif_check_image_types,
+	NULL,
+	NULL
+);

+ 100 - 42
tools/zynqmpimage.c

@@ -6,6 +6,7 @@
  * The following Boot Header format/structures and values are defined in the
  * following documents:
  *   * ug1085 ZynqMP TRM doc v1.4 (Chapter 11, Table 11-4)
+ *   * ug1137 ZynqMP Software Developer Guide v6.0 (Chapter 16)
  *
  * Expected Header Size = 0x9C0
  * Forced as 'little' endian, 32-bit words
@@ -56,47 +57,9 @@
 
 #include "imagetool.h"
 #include "mkimage.h"
+#include "zynqmpimage.h"
 #include <image.h>
 
-#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe))
-#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
-#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
-#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
-
-enum {
-	ENCRYPTION_EFUSE = 0xa5c3c5a3,
-	ENCRYPTION_OEFUSE = 0xa5c3c5a7,
-	ENCRYPTION_BBRAM = 0x3a5c3c5a,
-	ENCRYPTION_OBBRAM = 0xa35c7ca5,
-	ENCRYPTION_NONE = 0x0,
-};
-
-struct zynqmp_reginit {
-	uint32_t address;
-	uint32_t data;
-};
-
-#define HEADER_INTERRUPT_VECTORS	8
-#define HEADER_REGINITS			256
-
-struct zynqmp_header {
-	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
-	uint32_t width_detection; /* 0x20 */
-	uint32_t image_identifier; /* 0x24 */
-	uint32_t encryption; /* 0x28 */
-	uint32_t image_load; /* 0x2c */
-	uint32_t image_offset; /* 0x30 */
-	uint32_t pfw_image_length; /* 0x34 */
-	uint32_t total_pfw_image_length; /* 0x38 */
-	uint32_t image_size; /* 0x3c */
-	uint32_t image_stored_size; /* 0x40 */
-	uint32_t image_attributes; /* 0x44 */
-	uint32_t checksum; /* 0x48 */
-	uint32_t __reserved1[27]; /* 0x4c */
-	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
-	uint32_t __reserved4[66]; /* 0x9c0 */
-};
-
 static struct zynqmp_header zynqmpimage_header;
 static void *dynamic_header;
 static FILE *fpmu;
@@ -123,7 +86,7 @@ static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr)
 	return cpu_to_le32(checksum);
 }
 
-static void zynqmpimage_default_header(struct zynqmp_header *ptr)
+void zynqmpimage_default_header(struct zynqmp_header *ptr)
 {
 	int i;
 
@@ -131,7 +94,7 @@ static void zynqmpimage_default_header(struct zynqmp_header *ptr)
 		return;
 
 	ptr->width_detection = HEADER_WIDTHDETECTION;
-	ptr->image_attributes = 0x800;
+	ptr->image_attributes = HEADER_CPU_SELECT_A53_64BIT;
 	ptr->image_identifier = HEADER_IMAGEIDENTIFIER;
 	ptr->encryption = cpu_to_le32(ENCRYPTION_NONE);
 
@@ -172,7 +135,81 @@ static int zynqmpimage_verify_header(unsigned char *ptr, int image_size,
 	return 0;
 }
 
-static void zynqmpimage_print_header(const void *ptr)
+static void print_partition(const void *ptr, const struct partition_header *ph)
+{
+	uint32_t attr = le32_to_cpu(ph->attributes);
+	unsigned long len = le32_to_cpu(ph->len) * 4;
+	const char *part_owner;
+	const char *dest_devs[0x8] = {
+		"none", "PS", "PL", "PMU", "unknown", "unknown", "unknown",
+		"unknown"
+	};
+
+	switch (attr & PART_ATTR_PART_OWNER_MASK) {
+	case PART_ATTR_PART_OWNER_FSBL:
+		part_owner = "FSBL";
+		break;
+	case PART_ATTR_PART_OWNER_UBOOT:
+		part_owner = "U-Boot";
+		break;
+	default:
+		part_owner = "Unknown";
+		break;
+	}
+
+	printf("%s payload on CPU %s (%s):\n", part_owner,
+	       dest_cpus[(attr & PART_ATTR_DEST_CPU_MASK) >> 8],
+	       dest_devs[(attr & PART_ATTR_DEST_DEVICE_MASK) >> 4]);
+
+	printf("    Offset     : 0x%08x\n", le32_to_cpu(ph->offset) * 4);
+	printf("    Size       : %lu (0x%lx) bytes\n", len, len);
+	printf("    Load       : 0x%08llx",
+	       (unsigned long long)le64_to_cpu(ph->load_address));
+	if (ph->load_address != ph->entry_point)
+		printf(" (entry=0x%08llx)\n",
+		       (unsigned long long)le64_to_cpu(ph->entry_point));
+	else
+		printf("\n");
+	printf("    Attributes : ");
+
+	if (attr & PART_ATTR_VEC_LOCATION)
+		printf("vec ");
+
+	if (attr & PART_ATTR_ENCRYPTED)
+		printf("encrypted ");
+
+	switch (attr & PART_ATTR_CHECKSUM_MASK) {
+	case PART_ATTR_CHECKSUM_MD5:
+		printf("md5 ");
+		break;
+	case PART_ATTR_CHECKSUM_SHA2:
+		printf("sha2 ");
+		break;
+	case PART_ATTR_CHECKSUM_SHA3:
+		printf("sha3 ");
+		break;
+	}
+
+	if (attr & PART_ATTR_BIG_ENDIAN)
+		printf("BigEndian ");
+
+	if (attr & PART_ATTR_RSA_SIG)
+		printf("RSA ");
+
+	if (attr & PART_ATTR_A53_EXEC_AARCH32)
+		printf("AArch32 ");
+
+	if (attr & PART_ATTR_TARGET_EL_MASK)
+		printf("EL%d ", (attr & PART_ATTR_TARGET_EL_MASK) >> 1);
+
+	if (attr & PART_ATTR_TZ_SECURE)
+		printf("secure ");
+	printf("\n");
+
+	printf("    Checksum   : 0x%08x\n", le32_to_cpu(ph->checksum));
+}
+
+void zynqmpimage_print_header(const void *ptr)
 {
 	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
 	int i;
@@ -212,6 +249,27 @@ static void zynqmpimage_print_header(const void *ptr)
 		       le32_to_cpu(zynqhdr->register_init[i].data));
 	}
 
+	if (zynqhdr->image_header_table_offset) {
+		struct image_header_table *iht = (void *)ptr +
+			zynqhdr->image_header_table_offset;
+		struct partition_header *ph;
+		uint32_t ph_offset;
+		uint32_t next;
+		int i;
+
+		ph_offset = le32_to_cpu(iht->partition_header_offset) * 4;
+		ph = (void *)ptr + ph_offset;
+		for (i = 0; i < le32_to_cpu(iht->nr_parts); i++) {
+			next = le32_to_cpu(ph->next_partition_offset) * 4;
+
+			/* Partition 0 is the base image itself */
+			if (i)
+				print_partition(ptr, ph);
+
+			ph = (void *)ptr + next;
+		}
+	}
+
 	free(dynamic_header);
 }
 

+ 139 - 0
tools/zynqmpimage.h

@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 Michal Simek <michals@xilinx.com>
+ * Copyright (C) 2015 Nathan Rossi <nathan@nathanrossi.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * The following Boot Header format/structures and values are defined in the
+ * following documents:
+ *   * ug1085 ZynqMP TRM doc v1.4 (Chapter 11, Table 11-4)
+ *   * ug1137 ZynqMP Software Developer Guide v6.0 (Chapter 16)
+ */
+
+#ifndef _ZYNQMPIMAGE_H_
+#define _ZYNQMPIMAGE_H_
+
+#include <stdint.h>
+
+#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe))
+#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
+#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
+#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
+#define HEADER_CPU_SELECT_MASK		(0x3 << 10)
+#define HEADER_CPU_SELECT_R5_SINGLE	(0x0 << 10)
+#define HEADER_CPU_SELECT_A53_32BIT	(0x1 << 10)
+#define HEADER_CPU_SELECT_A53_64BIT	(0x2 << 10)
+#define HEADER_CPU_SELECT_R5_DUAL	(0x3 << 10)
+
+enum {
+	ENCRYPTION_EFUSE = 0xa5c3c5a3,
+	ENCRYPTION_OEFUSE = 0xa5c3c5a7,
+	ENCRYPTION_BBRAM = 0x3a5c3c5a,
+	ENCRYPTION_OBBRAM = 0xa35c7ca5,
+	ENCRYPTION_NONE = 0x0,
+};
+
+struct zynqmp_reginit {
+	uint32_t address;
+	uint32_t data;
+};
+
+#define HEADER_INTERRUPT_VECTORS	8
+#define HEADER_REGINITS			256
+
+struct image_header_table {
+	uint32_t version;		  /* 0x00 */
+	uint32_t nr_parts;		  /* 0x04 */
+	uint32_t partition_header_offset; /* 0x08, divided by 4 */
+	uint32_t image_header_offset;	  /* 0x0c, divided by 4 */
+	uint32_t auth_certificate_offset; /* 0x10 */
+	uint32_t boot_device;		  /* 0x14 */
+	uint32_t __reserved1[9];	  /* 0x18 - 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
+#define PART_ATTR_VEC_LOCATION		0x800000
+#define PART_ATTR_BS_BLOCK_SIZE_MASK	0x700000
+#define     PART_ATTR_BS_BLOCK_SIZE_DEFAULT	0x000000
+#define     PART_ATTR_BS_BLOCK_SIZE_8MB		0x400000
+#define PART_ATTR_BIG_ENDIAN		0x040000
+#define PART_ATTR_PART_OWNER_MASK	0x030000
+#define     PART_ATTR_PART_OWNER_FSBL		0x000000
+#define     PART_ATTR_PART_OWNER_UBOOT		0x010000
+#define PART_ATTR_RSA_SIG		0x008000
+#define PART_ATTR_CHECKSUM_MASK		0x007000
+#define    PART_ATTR_CHECKSUM_NONE		0x000000
+#define    PART_ATTR_CHECKSUM_MD5		0x001000
+#define    PART_ATTR_CHECKSUM_SHA2		0x002000
+#define    PART_ATTR_CHECKSUM_SHA3		0x003000
+#define PART_ATTR_DEST_CPU_SHIFT	8
+#define PART_ATTR_DEST_CPU_MASK		0x000f00
+#define    PART_ATTR_DEST_CPU_NONE		0x000000
+#define    PART_ATTR_DEST_CPU_A53_0		0x000100
+#define    PART_ATTR_DEST_CPU_A53_1		0x000200
+#define    PART_ATTR_DEST_CPU_A53_2		0x000300
+#define    PART_ATTR_DEST_CPU_A53_3		0x000400
+#define    PART_ATTR_DEST_CPU_R5_0		0x000500
+#define    PART_ATTR_DEST_CPU_R5_1		0x000600
+#define    PART_ATTR_DEST_CPU_R5_L		0x000700
+#define    PART_ATTR_DEST_CPU_PMU		0x000800
+#define PART_ATTR_ENCRYPTED		0x000080
+#define PART_ATTR_DEST_DEVICE_SHIFT	4
+#define PART_ATTR_DEST_DEVICE_MASK	0x000070
+#define    PART_ATTR_DEST_DEVICE_NONE		0x000000
+#define    PART_ATTR_DEST_DEVICE_PS		0x000010
+#define    PART_ATTR_DEST_DEVICE_PL		0x000020
+#define    PART_ATTR_DEST_DEVICE_PMU		0x000030
+#define    PART_ATTR_DEST_DEVICE_XIP		0x000040
+#define PART_ATTR_A53_EXEC_AARCH32	0x000008
+#define PART_ATTR_TARGET_EL_SHIFT	1
+#define PART_ATTR_TARGET_EL_MASK	0x000006
+#define PART_ATTR_TZ_SECURE		0x000001
+
+static const char *dest_cpus[0x10] = {
+	"none", "a5x-0", "a5x-1", "a5x-2", "a5x-3", "r5-0", "r5-1",
+	"r5-lockstep", "pmu", "unknown", "unknown", "unknown", "unknown",
+	"unknown", "unknown", "unknown"
+};
+
+struct partition_header {
+	uint32_t len_enc;		  /* 0x00, divided by 4 */
+	uint32_t len_unenc;		  /* 0x04, divided by 4 */
+	uint32_t len;			  /* 0x08, divided by 4 */
+	uint32_t next_partition_offset;   /* 0x0c */
+	uint64_t entry_point;		  /* 0x10 */
+	uint64_t load_address;		  /* 0x18 */
+	uint32_t offset;		  /* 0x20, divided by 4 */
+	uint32_t attributes;		  /* 0x24 */
+	uint32_t __reserved1;		  /* 0x28 */
+	uint32_t checksum_offset;	  /* 0x2c, divided by 4 */
+	uint32_t __reserved2;		  /* 0x30 */
+	uint32_t auth_certificate_offset; /* 0x34 */
+	uint32_t __reserved3;		  /* 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
+struct zynqmp_header {
+	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
+	uint32_t width_detection; /* 0x20 */
+	uint32_t image_identifier; /* 0x24 */
+	uint32_t encryption; /* 0x28 */
+	uint32_t image_load; /* 0x2c */
+	uint32_t image_offset; /* 0x30 */
+	uint32_t pfw_image_length; /* 0x34 */
+	uint32_t total_pfw_image_length; /* 0x38 */
+	uint32_t image_size; /* 0x3c */
+	uint32_t image_stored_size; /* 0x40 */
+	uint32_t image_attributes; /* 0x44 */
+	uint32_t checksum; /* 0x48 */
+	uint32_t __reserved1[19]; /* 0x4c */
+	uint32_t image_header_table_offset; /* 0x98 */
+	uint32_t __reserved2[7]; /* 0x9c */
+	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
+	uint32_t __reserved4[66]; /* 0x9c0 */
+};
+
+void zynqmpimage_default_header(struct zynqmp_header *ptr);
+void zynqmpimage_print_header(const void *ptr);
+
+#endif /* _ZYNQMPIMAGE_H_ */