Browse Source

Merge branch '2021.04-rc' of https://github.com/lftan/u-boot

- Add ATF flow for SoC64 devices
- Update socfpgaimage to support print header and update padding flow
Tom Rini 3 years ago
parent
commit
83e13c3469

+ 4 - 1
Makefile

@@ -1583,7 +1583,10 @@ u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE
 
 ifneq ($(CONFIG_ARCH_SOCFPGA),)
 quiet_cmd_gensplx4 = GENSPLX4 $@
-cmd_gensplx4 = cat	spl/u-boot-spl.sfp spl/u-boot-spl.sfp	\
+cmd_gensplx4 = $(OBJCOPY) -I binary -O binary --gap-fill=0x0		\
+			--pad-to=$(CONFIG_SPL_PAD_TO)			\
+			spl/u-boot-spl.sfp spl/u-boot-spl.sfp &&        \
+		cat	spl/u-boot-spl.sfp spl/u-boot-spl.sfp		\
 			spl/u-boot-spl.sfp spl/u-boot-spl.sfp > $@ || { rm -f $@; false; }
 spl/u-boot-splx4.sfp: spl/u-boot-spl.sfp FORCE
 	$(call if_changed,gensplx4)

+ 3 - 1
arch/arm/dts/socfpga_agilex-u-boot.dtsi

@@ -2,9 +2,11 @@
 /*
  * U-Boot additions
  *
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2019-2020 Intel Corporation <www.intel.com>
  */
 
+#include "socfpga_soc64_fit-u-boot.dtsi"
+
 /{
 	memory {
 		#address-cells = <2>;

+ 120 - 0
arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ */
+
+#if defined(CONFIG_FIT)
+
+/ {
+	binman: binman {
+		multiple-images;
+	};
+};
+
+&binman {
+	u-boot {
+		filename = "u-boot.itb";
+		fit {
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+			description = "FIT with firmware and bootloader";
+			#address-cells = <1>;
+
+			images {
+				uboot {
+					description = "U-Boot SoC64";
+					type = "standalone";
+					os = "U-Boot";
+					arch = "arm64";
+					compression = "none";
+					load = <0x00200000>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					os = "arm-trusted-firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x00001000>;
+					entry = <0x00001000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "U-Boot SoC64 flat device-tree";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+				conf {
+					description = "Intel SoC64 FPGA";
+					firmware = "atf";
+					loadables = "uboot";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+
+	kernel {
+		filename = "kernel.itb";
+		fit {
+			description = "FIT with Linux kernel image and FDT blob";
+			#address-cells = <1>;
+
+			images {
+				kernel {
+					description = "Linux Kernel";
+					type = "kernel";
+					arch = "arm64";
+					os = "linux";
+					compression = "none";
+					load = <0x4080000>;
+					entry = <0x4080000>;
+
+					kernel_blob: blob-ext {
+						filename = "Image";
+					};
+				};
+
+				fdt {
+					description = "Linux DTB";
+					type = "flat_dt";
+					arch = "arm64";
+					compression = "none";
+
+					kernel_fdt_blob: blob-ext {
+						filename = "linux.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+				conf {
+					description = "Intel SoC64 FPGA";
+					kernel = "kernel";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+};
+
+#endif

+ 8 - 0
arch/arm/dts/socfpga_stratix10-u-boot.dtsi

@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ */
+
+#include "socfpga_soc64_fit-u-boot.dtsi"

+ 3 - 1
arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi

@@ -2,9 +2,11 @@
 /*
  * U-Boot additions
  *
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2019-2020 Intel Corporation <www.intel.com>
  */
 
+#include "socfpga_stratix10-u-boot.dtsi"
+
 /{
 	aliases {
 		spi0 = &qspi;

+ 2 - 2
arch/arm/mach-socfpga/Kconfig

@@ -33,7 +33,7 @@ config TARGET_SOCFPGA_AGILEX
 	bool
 	select ARMV8_MULTIENTRY
 	select ARMV8_SET_SMPEN
-	select ARMV8_SPIN_TABLE
+	select BINMAN if SPL_ATF
 	select CLK
 	select FPGA_INTEL_SDM_MAILBOX
 	select NCORE_CACHE
@@ -79,7 +79,7 @@ config TARGET_SOCFPGA_STRATIX10
 	bool
 	select ARMV8_MULTIENTRY
 	select ARMV8_SET_SMPEN
-	select ARMV8_SPIN_TABLE
+	select BINMAN if SPL_ATF
 	select FPGA_INTEL_SDM_MAILBOX
 
 choice

+ 5 - 0
arch/arm/mach-socfpga/Makefile

@@ -29,6 +29,7 @@ endif
 
 ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
 obj-y	+= clock_manager_s10.o
+obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
 obj-y	+= misc_s10.o
 obj-y	+= mmu-arm64_s10.o
@@ -41,6 +42,7 @@ endif
 
 ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 obj-y	+= clock_manager_agilex.o
+obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
 obj-y	+= misc_s10.o
 obj-y	+= mmu-arm64_s10.o
@@ -70,6 +72,9 @@ ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 obj-y	+= firewall.o
 obj-y	+= spl_agilex.o
 endif
+else
+obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o
+obj-$(CONFIG_SPL_ATF) += smc_api.o
 endif
 
 ifdef CONFIG_TARGET_SOCFPGA_GEN5

+ 11 - 1
arch/arm/mach-socfpga/board.c

@@ -13,7 +13,7 @@
 #include <asm/arch/clock_manager.h>
 #include <asm/arch/misc.h>
 #include <asm/io.h>
-
+#include <log.h>
 #include <usb.h>
 #include <usb/dwc2_udc.h>
 
@@ -87,3 +87,13 @@ int g_dnl_board_usb_cable_connected(void)
 	return 1;
 }
 #endif
+
+#ifdef CONFIG_SPL_BUILD
+__weak int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif

+ 19 - 0
arch/arm/mach-socfpga/include/mach/secure_reg_helper.h

@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef	_SECURE_REG_HELPER_H_
+#define	_SECURE_REG_HELPER_H_
+
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC 1
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 2
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1 3
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2 4
+
+int socfpga_secure_reg_read32(u32 id, u32 *val);
+int socfpga_secure_reg_write32(u32 id, u32 val);
+int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val);
+
+#endif /* _SECURE_REG_HELPER_H_ */

+ 13 - 0
arch/arm/mach-socfpga/include/mach/smc_api.h

@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Intel Corporation
+ */
+
+#ifndef _SMC_API_H_
+#define _SMC_API_H_
+
+int invoke_smc(u32 func_id, u64 *args, int arg_len, u64 *ret_arg, int ret_len);
+int smc_send_mailbox(u32 cmd, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len,
+		     u32 *resp_buf);
+
+#endif /* _SMC_API_H_ */

+ 76 - 0
arch/arm/mach-socfpga/lowlevel_init_soc64.S

@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 Intel Corporation. All rights reserved
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/macro.h>
+
+ENTRY(lowlevel_init)
+	mov	x29, lr			/* Save LR */
+
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+wait_for_atf:
+	ldr	x4, =CPU_RELEASE_ADDR
+	ldr	x5, [x4]
+	cbz	x5, slave_wait_atf
+	br	x5
+slave_wait_atf:
+	branch_if_slave x0, wait_for_atf
+#else
+	branch_if_slave x0, 1f
+#endif
+	ldr	x0, =GICD_BASE
+	bl	gic_init_secure
+1:
+#if defined(CONFIG_GICV3)
+	ldr	x0, =GICR_BASE
+	bl	gic_init_secure_percpu
+#elif defined(CONFIG_GICV2)
+	ldr	x0, =GICD_BASE
+	ldr	x1, =GICC_BASE
+	bl	gic_init_secure_percpu
+#endif
+#endif
+
+#ifdef CONFIG_ARMV8_MULTIENTRY
+	branch_if_master x0, x1, 2f
+
+	/*
+	 * Slave should wait for master clearing spin table.
+	 * This sync prevent slaves observing incorrect
+	 * value of spin table and jumping to wrong place.
+	 */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+#ifdef CONFIG_GICV2
+	ldr	x0, =GICC_BASE
+#endif
+	bl	gic_wait_for_interrupt
+#endif
+
+	/*
+	 * All slaves will enter EL2 and optionally EL1.
+	 */
+	adr	x4, lowlevel_in_el2
+	ldr	x5, =ES_TO_AARCH64
+	bl	armv8_switch_to_el2
+
+lowlevel_in_el2:
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+	adr	x4, lowlevel_in_el1
+	ldr	x5, =ES_TO_AARCH64
+	bl	armv8_switch_to_el1
+
+lowlevel_in_el1:
+#endif
+
+#endif /* CONFIG_ARMV8_MULTIENTRY */
+
+2:
+	mov	lr, x29			/* Restore LR */
+	ret
+ENDPROC(lowlevel_init)

+ 5 - 0
arch/arm/mach-socfpga/mailbox_s10.c

@@ -11,6 +11,7 @@
 #include <asm/arch/mailbox_s10.h>
 #include <asm/arch/system_manager.h>
 #include <asm/secure.h>
+#include <asm/system.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -398,6 +399,9 @@ error:
 
 int mbox_reset_cold(void)
 {
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+	psci_system_reset();
+#else
 	int ret;
 
 	ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT,
@@ -406,6 +410,7 @@ int mbox_reset_cold(void)
 		/* mailbox sent failure, wait for watchdog to kick in */
 		hang();
 	}
+#endif
 	return 0;
 }
 

+ 13 - 0
arch/arm/mach-socfpga/reset_manager_s10.c

@@ -5,11 +5,14 @@
  */
 
 #include <common.h>
+#include <hang.h>
 #include <asm/io.h>
 #include <asm/arch/reset_manager.h>
+#include <asm/arch/smc_api.h>
 #include <asm/arch/system_manager.h>
 #include <dt-bindings/reset/altr,rst-mgr-s10.h>
 #include <linux/iopoll.h>
+#include <linux/intel-smc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -55,6 +58,15 @@ void socfpga_per_reset_all(void)
 
 void socfpga_bridges_reset(int enable)
 {
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+	u64 arg = enable;
+
+	int ret = invoke_smc(INTEL_SIP_SMC_HPS_SET_BRIDGES, &arg, 1, NULL, 0);
+	if (ret) {
+		printf("SMC call failed with error %d in %s.\n", ret, __func__);
+		return;
+	}
+#else
 	u32 reg;
 
 	if (enable) {
@@ -101,6 +113,7 @@ void socfpga_bridges_reset(int enable)
 		/* Disable NOC timeout */
 		writel(0, socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NOC_TIMEOUT);
 	}
+#endif
 }
 
 /*

+ 89 - 0
arch/arm/mach-socfpga/secure_reg_helper.c

@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <hang.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/misc.h>
+#include <asm/arch/secure_reg_helper.h>
+#include <asm/arch/smc_api.h>
+#include <asm/arch/system_manager.h>
+#include <linux/errno.h>
+#include <linux/intel-smc.h>
+
+int socfpga_secure_convert_reg_id_to_addr(u32 id, phys_addr_t *reg_addr)
+{
+	switch (id) {
+	case SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC:
+		*reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC;
+		break;
+	case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0:
+		*reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0;
+		break;
+	case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1:
+		*reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1;
+		break;
+	case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2:
+		*reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2;
+		break;
+	default:
+		return -EADDRNOTAVAIL;
+	}
+	return 0;
+}
+
+int socfpga_secure_reg_read32(u32 id, u32 *val)
+{
+	int ret;
+	u64 ret_arg;
+	u64 args[1];
+
+	phys_addr_t reg_addr;
+	ret = socfpga_secure_convert_reg_id_to_addr(id, &reg_addr);
+	if (ret)
+		return ret;
+
+	args[0] = (u64)reg_addr;
+	ret = invoke_smc(INTEL_SIP_SMC_REG_READ, args, 1, &ret_arg, 1);
+	if (ret)
+		return ret;
+
+	*val = (u32)ret_arg;
+
+	return 0;
+}
+
+int socfpga_secure_reg_write32(u32 id, u32 val)
+{
+	int ret;
+	u64 args[2];
+
+	phys_addr_t reg_addr;
+	ret = socfpga_secure_convert_reg_id_to_addr(id, &reg_addr);
+	if (ret)
+		return ret;
+
+	args[0] = (u64)reg_addr;
+	args[1] = val;
+	return invoke_smc(INTEL_SIP_SMC_REG_WRITE, args, 2, NULL, 0);
+}
+
+int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val)
+{
+	int ret;
+	u64 args[3];
+
+	phys_addr_t reg_addr;
+	ret = socfpga_secure_convert_reg_id_to_addr(id, &reg_addr);
+	if (ret)
+		return ret;
+
+	args[0] = (u64)reg_addr;
+	args[1] = mask;
+	args[2] = val;
+	return invoke_smc(INTEL_SIP_SMC_REG_UPDATE, args, 3, NULL, 0);
+}

+ 56 - 0
arch/arm/mach-socfpga/smc_api.c

@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <linux/intel-smc.h>
+
+int invoke_smc(u32 func_id, u64 *args, int arg_len, u64 *ret_arg, int ret_len)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	regs.regs[0] = func_id;
+
+	if (args)
+		memcpy(&regs.regs[1], args, arg_len * sizeof(*args));
+
+	smc_call(&regs);
+
+	if (ret_arg)
+		memcpy(ret_arg, &regs.regs[1], ret_len * sizeof(*ret_arg));
+
+	return regs.regs[0];
+}
+
+int smc_send_mailbox(u32 cmd, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len,
+		     u32 *resp_buf)
+{
+	int ret;
+	u64 args[6];
+	u64 resp[3];
+
+	args[0] = cmd;
+	args[1] = (u64)arg;
+	args[2] = len;
+	args[3] = urgent;
+	args[4] = (u64)resp_buf;
+	if (resp_buf_len)
+		args[5] = *resp_buf_len;
+	else
+		args[5] = 0;
+
+	ret = invoke_smc(INTEL_SIP_SMC_MBOX_SEND_CMD, args, ARRAY_SIZE(args),
+			 resp, ARRAY_SIZE(resp));
+
+	if (ret == INTEL_SIP_SMC_STATUS_OK && resp_buf && resp_buf_len) {
+		if (!resp[0])
+			*resp_buf_len = resp[1];
+	}
+
+	return (int)resp[0];
+}

+ 2 - 1
arch/arm/mach-socfpga/wrap_pll_config_s10.c

@@ -12,6 +12,7 @@
 
 const struct cm_config * const cm_get_default_config(void)
 {
+#ifdef CONFIG_SPL_BUILD
 	struct cm_config *cm_handoff_cfg = (struct cm_config *)
 		(S10_HANDOFF_CLOCK + S10_HANDOFF_OFFSET_DATA);
 	u32 *conversion = (u32 *)cm_handoff_cfg;
@@ -26,7 +27,7 @@ const struct cm_config * const cm_get_default_config(void)
 	} else if (handoff_clk == S10_HANDOFF_MAGIC_CLOCK) {
 		return cm_handoff_cfg;
 	}
-
+#endif
 	return NULL;
 }
 

+ 1 - 0
board/altera/stratix10-socdk/MAINTAINERS

@@ -4,4 +4,5 @@ M:	Dinh Nguyen <dinh.nguyen@intel.com>
 S:	Maintained
 F:	board/altera/stratix10-socdk/
 F:	include/configs/socfpga_stratix10_socdk.h
+F:	configs/socfpga_stratix10_atf_defconfig
 F:	configs/socfpga_stratix10_defconfig

+ 1 - 0
board/intel/agilex-socdk/MAINTAINERS

@@ -4,4 +4,5 @@ M:	Chee Hong Ang <chee.hong.ang@intel.com>
 S:	Maintained
 F:	board/intel/agilex-socdk/
 F:	include/configs/socfpga_agilex_socdk.h
+F:	configs/socfpga_agilex_atf_defconfig
 F:	configs/socfpga_agilex_defconfig

+ 72 - 0
configs/socfpga_agilex_atf_defconfig

@@ -0,0 +1,72 @@
+CONFIG_ARM=y
+CONFIG_ARM_SMCCC=y
+CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds"
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x200
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_SOCFPGA_AGILEX_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_agilex"
+CONFIG_SPL_FS_FAT=y
+CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTDELAY=5
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon"
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="SOCFPGA_AGILEX # "
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_ALTERA_SDRAM=y
+CONFIG_DWAPB_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_MODE=0x2003
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_MII=y
+CONFIG_DM_RESET=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_PANIC_HANG=y

+ 74 - 0
configs/socfpga_stratix10_atf_defconfig

@@ -0,0 +1,74 @@
+CONFIG_ARM=y
+CONFIG_ARM_SMCCC=y
+CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds"
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x200
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_SOCFPGA_STRATIX10_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_stratix10"
+CONFIG_SPL_FS_FAT=y
+CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTDELAY=5
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon"
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="SOCFPGA_STRATIX10 # "
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_stratix10_socdk"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_ALTERA_SDRAM=y
+CONFIG_FPGA_INTEL_PR=y
+CONFIG_DWAPB_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_MODE=0x2003
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_MII=y
+CONFIG_DM_RESET=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_PANIC_HANG=y

+ 139 - 0
drivers/fpga/intel_sdm_mb.c

@@ -8,11 +8,149 @@
 #include <log.h>
 #include <watchdog.h>
 #include <asm/arch/mailbox_s10.h>
+#include <asm/arch/smc_api.h>
 #include <linux/delay.h>
+#include <linux/intel-smc.h>
 
 #define RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS		60000
 #define RECONFIG_STATUS_INTERVAL_DELAY_US		1000000
 
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+
+#define BITSTREAM_CHUNK_SIZE				0xFFFF0
+#define RECONFIG_STATUS_POLL_RETRY_MAX			100
+
+/*
+ * Polling the FPGA configuration status.
+ * Return 0 for success, non-zero for error.
+ */
+static int reconfig_status_polling_resp(void)
+{
+	int ret;
+	unsigned long start = get_timer(0);
+
+	while (1) {
+		ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, NULL, 0,
+				 NULL, 0);
+
+		if (!ret)
+			return 0;	/* configuration success */
+
+		if (ret != INTEL_SIP_SMC_STATUS_BUSY)
+			return ret;
+
+		if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS)
+			return -ETIMEDOUT;	/* time out */
+
+		puts(".");
+		udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+		WATCHDOG_RESET();
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int send_bitstream(const void *rbf_data, size_t rbf_size)
+{
+	int i;
+	u64 res_buf[3];
+	u64 args[2];
+	u32 xfer_count = 0;
+	int ret, wr_ret = 0, retry = 0;
+	size_t buf_size = (rbf_size > BITSTREAM_CHUNK_SIZE) ?
+				BITSTREAM_CHUNK_SIZE : rbf_size;
+
+	while (rbf_size || xfer_count) {
+		if (!wr_ret && rbf_size) {
+			args[0] = (u64)rbf_data;
+			args[1] = buf_size;
+			wr_ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_WRITE,
+					    args, 2, NULL, 0);
+
+			debug("wr_ret = %d, rbf_data = %p, buf_size = %08lx\n",
+			      wr_ret, rbf_data, buf_size);
+
+			if (wr_ret)
+				continue;
+
+			rbf_size -= buf_size;
+			rbf_data += buf_size;
+
+			if (buf_size >= rbf_size)
+				buf_size = rbf_size;
+
+			xfer_count++;
+			puts(".");
+		} else {
+			ret = invoke_smc(
+				INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE,
+				NULL, 0, res_buf, ARRAY_SIZE(res_buf));
+			if (!ret) {
+				for (i = 0; i < ARRAY_SIZE(res_buf); i++) {
+					if (!res_buf[i])
+						break;
+					xfer_count--;
+					wr_ret = 0;
+					retry = 0;
+				}
+			} else if (ret !=
+				   INTEL_SIP_SMC_STATUS_BUSY)
+				return ret;
+			else if (!xfer_count)
+				return INTEL_SIP_SMC_STATUS_ERROR;
+
+			if (++retry >= RECONFIG_STATUS_POLL_RETRY_MAX)
+				return -ETIMEDOUT;
+
+			udelay(20000);
+		}
+		WATCHDOG_RESET();
+	}
+
+	return 0;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for success, non-zero for error.
+ */
+int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+	int ret;
+	u64 arg = 1;
+
+	debug("Invoking FPGA_CONFIG_START...\n");
+
+	ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0);
+
+	if (ret) {
+		puts("Failure in RECONFIG mailbox command!\n");
+		return ret;
+	}
+
+	ret = send_bitstream(rbf_data, rbf_size);
+	if (ret) {
+		puts("Error sending bitstream!\n");
+		return ret;
+	}
+
+	/* Make sure we don't send MBOX_RECONFIG_STATUS too fast */
+	udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+
+	debug("Polling with MBOX_RECONFIG_STATUS...\n");
+	ret = reconfig_status_polling_resp();
+	if (ret) {
+		puts("FPGA reconfiguration failed!");
+		return ret;
+	}
+
+	puts("FPGA reconfiguration OK!\n");
+
+	return ret;
+}
+
+#else
+
 static const struct mbox_cfgstat_state {
 	int			err_no;
 	const char		*error_name;
@@ -286,3 +424,4 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
 
 	return ret;
 }
+#endif

+ 3 - 1
drivers/mmc/ca_dw_mmc.c

@@ -40,7 +40,7 @@ struct ca_dwmmc_priv_data {
 	u8 ds;
 };
 
-static void ca_dwmci_clksel(struct dwmci_host *host)
+static int ca_dwmci_clksel(struct dwmci_host *host)
 {
 	struct ca_dwmmc_priv_data *priv = host->priv;
 	u32 val = readl(priv->sd_dll_reg);
@@ -52,6 +52,8 @@ static void ca_dwmci_clksel(struct dwmci_host *host)
 		val |= SD_CLK_SEL_100MHZ;
 
 	writel(val, priv->sd_dll_reg);
+
+	return 0;
 }
 
 static void ca_dwmci_board_init(struct dwmci_host *host)

+ 7 - 2
drivers/mmc/dw_mmc.c

@@ -496,8 +496,13 @@ static int dwmci_set_ios(struct mmc *mmc)
 
 	dwmci_writel(host, DWMCI_UHS_REG, regs);
 
-	if (host->clksel)
-		host->clksel(host);
+	if (host->clksel) {
+		int ret;
+
+		ret = host->clksel(host);
+		if (ret)
+			return ret;
+	}
 
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
 	if (mmc->vqmmc_supply) {

+ 3 - 1
drivers/mmc/exynos_dw_mmc.c

@@ -44,7 +44,7 @@ struct dwmci_exynos_priv_data {
  * Function used as callback function to initialise the
  * CLKSEL register for every mmc channel.
  */
-static void exynos_dwmci_clksel(struct dwmci_host *host)
+static int exynos_dwmci_clksel(struct dwmci_host *host)
 {
 #ifdef CONFIG_DM_MMC
 	struct dwmci_exynos_priv_data *priv =
@@ -53,6 +53,8 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
 	struct dwmci_exynos_priv_data *priv = host->priv;
 #endif
 	dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
+
+	return 0;
 }
 
 unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)

+ 3 - 1
drivers/mmc/nexell_dw_mmc.c

@@ -51,7 +51,7 @@ struct nexell_dwmmc_priv {
 
 struct clk *clk_get(const char *id);
 
-static void nx_dw_mmc_clksel(struct dwmci_host *host)
+static int nx_dw_mmc_clksel(struct dwmci_host *host)
 {
 	/* host->priv is pointer to "struct udevice" */
 	struct nexell_dwmmc_priv *priv = dev_get_priv(host->priv);
@@ -65,6 +65,8 @@ static void nx_dw_mmc_clksel(struct dwmci_host *host)
 		      DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
 
 	dwmci_writel(host, DWMCI_CLKSEL, val);
+
+	return 0;
 }
 
 static void nx_dw_mmc_reset(int ch)

+ 17 - 1
drivers/mmc/socfpga_dw_mmc.c

@@ -6,6 +6,7 @@
 #include <common.h>
 #include <log.h>
 #include <asm/arch/clock_manager.h>
+#include <asm/arch/secure_reg_helper.h>
 #include <asm/arch/system_manager.h>
 #include <clk.h>
 #include <dm.h>
@@ -13,6 +14,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <dm/device_compat.h>
+#include <linux/intel-smc.h>
 #include <linux/libfdt.h>
 #include <linux/err.h>
 #include <malloc.h>
@@ -46,7 +48,7 @@ static void socfpga_dwmci_reset(struct udevice *dev)
 	reset_deassert_bulk(&reset_bulk);
 }
 
-static void socfpga_dwmci_clksel(struct dwmci_host *host)
+static int socfpga_dwmci_clksel(struct dwmci_host *host)
 {
 	struct dwmci_socfpga_priv_data *priv = host->priv;
 	u32 sdmmc_mask = ((priv->smplsel & 0x7) << SYSMGR_SDMMC_SMPLSEL_SHIFT) |
@@ -58,14 +60,28 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host)
 
 	debug("%s: drvsel %d smplsel %d\n", __func__,
 	      priv->drvsel, priv->smplsel);
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+	int ret;
+
+	ret = socfpga_secure_reg_write32(SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC,
+					 sdmmc_mask);
+	if (ret) {
+		printf("DWMMC: Failed to set clksel via SMC call");
+		return ret;
+	}
+#else
 	writel(sdmmc_mask, socfpga_get_sysmgr_addr() + SYSMGR_SDMMC);
 
 	debug("%s: SYSMGR_SDMMCGRP_CTRL_REG = 0x%x\n", __func__,
 		readl(socfpga_get_sysmgr_addr() + SYSMGR_SDMMC));
+#endif
 
 	/* Enable SDMMC clock */
 	setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN,
 		     CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK);
+
+	return 0;
 }
 
 static int socfpga_dwmmc_get_clk_rate(struct udevice *dev)

+ 31 - 6
drivers/net/dwmac_socfpga.c

@@ -6,6 +6,8 @@
  */
 
 #include <common.h>
+#include <asm/arch/secure_reg_helper.h>
+#include <asm/arch/system_manager.h>
 #include <asm/io.h>
 #include <dm.h>
 #include <clk.h>
@@ -17,8 +19,6 @@
 #include <dm/device_compat.h>
 #include <linux/err.h>
 
-#include <asm/arch/system_manager.h>
-
 struct dwmac_socfpga_plat {
 	struct dw_eth_pdata	dw_eth_pdata;
 	void			*phy_intf;
@@ -64,6 +64,32 @@ static int dwmac_socfpga_of_to_plat(struct udevice *dev)
 	return designware_eth_of_to_plat(dev);
 }
 
+static int dwmac_socfpga_do_setphy(struct udevice *dev, u32 modereg)
+{
+	struct dwmac_socfpga_plat *pdata = dev_get_plat(dev);
+	u32 modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift;
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+	u32 index = ((u64)pdata->phy_intf - socfpga_get_sysmgr_addr() -
+		     SYSMGR_SOC64_EMAC0) >> 2;
+
+	u32 id = SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 + index;
+
+	int ret = socfpga_secure_reg_update32(id,
+					     modemask,
+					     modereg << pdata->reg_shift);
+	if (ret) {
+		dev_err(dev, "Failed to set PHY register via SMC call\n");
+		return ret;
+	}
+#else
+	clrsetbits_le32(pdata->phy_intf, modemask,
+			modereg << pdata->reg_shift);
+#endif
+
+	return 0;
+}
+
 static int dwmac_socfpga_probe(struct udevice *dev)
 {
 	struct dwmac_socfpga_plat *pdata = dev_get_plat(dev);
@@ -71,7 +97,6 @@ static int dwmac_socfpga_probe(struct udevice *dev)
 	struct reset_ctl_bulk reset_bulk;
 	int ret;
 	u32 modereg;
-	u32 modemask;
 
 	switch (edata->phy_interface) {
 	case PHY_INTERFACE_MODE_MII:
@@ -97,9 +122,9 @@ static int dwmac_socfpga_probe(struct udevice *dev)
 
 	reset_assert_bulk(&reset_bulk);
 
-	modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift;
-	clrsetbits_le32(pdata->phy_intf, modemask,
-			modereg << pdata->reg_shift);
+	ret = dwmac_socfpga_do_setphy(dev, modereg);
+	if (ret)
+		return ret;
 
 	reset_release_bulk(&reset_bulk);
 

+ 2 - 0
include/configs/socfpga_common.h

@@ -22,8 +22,10 @@
 #if defined(CONFIG_TARGET_SOCFPGA_GEN5)
 #define CONFIG_SYS_INIT_RAM_ADDR	0xFFFF0000
 #define CONFIG_SYS_INIT_RAM_SIZE	SOCFPGA_PHYS_OCRAM_SIZE
+#define CONFIG_SPL_PAD_TO		0x10000
 #elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
 #define CONFIG_SYS_INIT_RAM_ADDR	0xFFE00000
+#define CONFIG_SPL_PAD_TO		0x40000
 /* SPL memory allocation configuration, this is for FAT implementation */
 #ifndef CONFIG_SYS_SPL_MALLOC_SIZE
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x10000

+ 23 - 1
include/configs/socfpga_soc64_common.h

@@ -40,9 +40,14 @@
  */
 #define CONFIG_SYS_INIT_RAM_ADDR	0xFFE00000
 #define CONFIG_SYS_INIT_RAM_SIZE	0x40000
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INIT_RAM_ADDR  \
 					+ CONFIG_SYS_INIT_RAM_SIZE \
 					- S10_HANDOFF_SIZE)
+#else
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE \
+					+ 0x100000)
+#endif
 #define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_INIT_SP_ADDR)
 #define CONFIG_SYS_MALLOC_LEN		(5 * 1024 * 1024)
 
@@ -78,12 +83,20 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
  * CONFIG_BOOTARGS goes into the environment value "bootargs".
  * Do note the value will override also the chosen node in FDT blob.
  */
+
+#ifdef CONFIG_FIT
+#define CONFIG_BOOTFILE "kernel.itb"
+#define CONFIG_BOOTCOMMAND "run fatscript; run mmcfitload;run linux_qspi_enable;" \
+			   "run mmcfitboot"
+#else
+#define CONFIG_BOOTFILE "Image"
 #define CONFIG_BOOTCOMMAND "run fatscript; run mmcload;run linux_qspi_enable;" \
 			   "run mmcboot"
+#endif
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
-	"bootfile=Image\0" \
+	"bootfile=" CONFIG_BOOTFILE "\0" \
 	"fdt_addr=8000000\0" \
 	"fdtimage=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
 	"mmcroot=/dev/mmcblk0p2\0" \
@@ -93,6 +106,11 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
 	"mmcload=mmc rescan;" \
 		"load mmc 0:1 ${loadaddr} ${bootfile};" \
 		"load mmc 0:1 ${fdt_addr} ${fdtimage}\0" \
+	"mmcfitboot=setenv bootargs " CONFIG_BOOTARGS \
+		" root=${mmcroot} rw rootwait;" \
+		"bootm ${loadaddr}\0" \
+	"mmcfitload=mmc rescan;" \
+		"load mmc 0:1 ${loadaddr} ${bootfile}\0" \
 	"linux_qspi_enable=if sf probe; then " \
 		"echo Enabling QSPI at Linux DTB...;" \
 		"fdt addr ${fdt_addr}; fdt resize;" \
@@ -193,6 +211,10 @@ unsigned int cm_get_l4_sys_free_clk_hz(void);
 					- CONFIG_SYS_SPL_MALLOC_SIZE)
 
 /* SPL SDMMC boot support */
+#ifdef CONFIG_SPL_LOAD_FIT
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.itb"
+#else
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
+#endif
 
 #endif	/* __CONFIG_SOCFPGA_SOC64_COMMON_H__ */

+ 1 - 1
include/dwmmc.h

@@ -174,7 +174,7 @@ struct dwmci_host {
 	struct mmc *mmc;
 	void *priv;
 
-	void (*clksel)(struct dwmci_host *host);
+	int (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
 
 	/**

+ 573 - 0
include/linux/intel-smc.h

@@ -0,0 +1,573 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2018, Intel Corporation
+ */
+
+#ifndef __INTEL_SMC_H
+#define __INTEL_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+/*
+ * This file defines the Secure Monitor Call (SMC) message protocol used for
+ * service layer driver in normal world (EL1) to communicate with secure
+ * monitor software in Secure Monitor Exception Level 3 (EL3).
+ *
+ * This file is shared with secure firmware (FW) which is out of u-boot tree.
+ *
+ * An ARM SMC instruction takes a function identifier and up to 6 64-bit
+ * register values as arguments, and can return up to 4 64-bit register
+ * values. The operation of the secure monitor is determined by the parameter
+ * values passed in through registers.
+
+ * EL1 and EL3 communicates pointer as physical address rather than the
+ * virtual address.
+ */
+
+/*
+ * Functions specified by ARM SMC Calling convention:
+ *
+ * FAST call executes atomic operations, returns when the requested operation
+ * has completed.
+ * STD call starts a operation which can be preempted by a non-secure
+ * interrupt. The call can return before the requested operation has
+ * completed.
+ *
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7.
+ */
+
+#define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \
+	ARM_SMCCC_OWNER_SIP, (func_num))
+
+#define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
+	ARM_SMCCC_OWNER_SIP, (func_num))
+
+/*
+ * Return values in INTEL_SIP_SMC_* call
+ *
+ * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION:
+ * Secure monitor software doesn't recognize the request.
+ *
+ * INTEL_SIP_SMC_STATUS_OK:
+ * SMC call completed successfully,
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software can accept the next chunk of FPGA configuration data.
+ *
+ * INTEL_SIP_SMC_STATUS_BUSY:
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software is still processing previous data & can't accept the next chunk
+ * of data. Service driver needs to issue
+ * INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE call to query the
+ * completed block(s).
+ *
+ * INTEL_SIP_SMC_STATUS_ERROR:
+ * There is error during the SMC call process.
+ *
+ * INTEL_SIP_SMC_REG_ERROR:
+ * There is error during a read or write operation of the protected
+ * registers.
+ */
+#define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION		0xFFFFFFFF
+#define INTEL_SIP_SMC_STATUS_OK				0x0
+#define INTEL_SIP_SMC_STATUS_BUSY			0x1
+#define INTEL_SIP_SMC_STATUS_REJECTED			0x2
+#define INTEL_SIP_SMC_STATUS_ERROR			0x4
+#define INTEL_SIP_SMC_REG_ERROR				0x5
+#define INTEL_SIP_SMC_RSU_ERROR				0x7
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_START
+ *
+ * Sync call used by service driver at EL1 to request the FPGA in EL3 to
+ * be prepare to receive a new configuration.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_START.
+ * a1: flag for full or partial configuration
+ *    0 full reconfiguration.
+ *    1 partial reconfiguration.
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START 1
+#define INTEL_SIP_SMC_FPGA_CONFIG_START \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ *
+ * Async call used by service driver at EL1 to provide FPGA configuration data
+ * to secure world.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_WRITE.
+ * a1: 64bit physical address of the configuration data memory block
+ * a2: Size of configuration data block.
+ * a3-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY,
+ * INTEL_SIP_SMC_STATUS_REJECTED or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block if any completed
+ * block, otherwise zero value.
+ * a2: 64bit physical address of 2nd completed memory block if any completed
+ * block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if any completed
+ * block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE 2
+#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE \
+	INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE
+ *
+ * Sync call used by service driver at EL1 to track the completed write
+ * transactions. This request is called after INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ * call returns INTEL_SIP_SMC_STATUS_BUSY.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or
+ * INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block.
+ * a2: 64bit physical address of 2nd completed memory block if
+ * any completed block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if
+ * any completed block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE 3
+#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE \
+INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_ISDONE
+ *
+ * Sync call used by service driver at EL1 to inform secure world that all
+ * data are sent, to check whether or not the secure world had completed
+ * the FPGA configuration process.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_ISDONE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or
+ * INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE 4
+#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM
+ *
+ * Sync call used by service driver at EL1 to query the physical address of
+ * memory block reserved by secure monitor software.
+ *
+ * Call register usage:
+ * a0:INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: start of physical address of reserved memory block.
+ * a2: size of reserved memory block.
+ * a3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM 5
+#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK
+ *
+ * For SMC loop-back mode only, used for internal integration, debugging
+ * or troubleshooting.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK 6
+#define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK)
+
+/*
+ * Request INTEL_SIP_SMC_REG_READ
+ *
+ * Read a protected register using SMCCC
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_READ.
+ * a1: register address.
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1: Value in the register
+ * a2-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_READ 7
+#define INTEL_SIP_SMC_REG_READ \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ)
+
+/*
+ * Request INTEL_SIP_SMC_REG_WRITE
+ *
+ * Write a protected register using SMCCC
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_WRITE.
+ * a1: register address
+ * a2: value to program into register.
+ * a3-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_WRITE 8
+#define INTEL_SIP_SMC_REG_WRITE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FUNCID_REG_UPDATE
+ *
+ * Update one or more bits in a protected register using a
+ * read-modify-write operation.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_UPDATE.
+ * a1: register address
+ * a2: Write Mask.
+ * a3: Value to write.
+ * a4-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1-3: Not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_UPDATE 9
+#define INTEL_SIP_SMC_REG_UPDATE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_UPDATE)
+
+/*
+* Request INTEL_SIP_SMC_RSU_STATUS
+*
+* Sync call used by service driver at EL1 to query the RSU status
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_STATUS
+* a1-7 not used
+*
+* Return status
+* a0: Current Image
+* a1: Last Failing Image
+* a2: Version [width 32 bit] | State [width 32 bit]
+* a3: Error details [width 32 bit] | Error location [width 32 bit]
+*
+* Or
+*
+* a0: INTEL_SIP_SMC_RSU_ERROR
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_STATUS 11
+#define INTEL_SIP_SMC_RSU_STATUS \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_STATUS)
+
+/*
+* Request INTEL_SIP_SMC_RSU_UPDATE
+*
+* Sync call used by service driver at EL1 to tell you next reboot is RSU_UPDATE
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_UPDATE
+* a1 64bit physical address of the configuration data memory in flash
+* a2-7 not used
+*
+* Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_UPDATE 12
+#define INTEL_SIP_SMC_RSU_UPDATE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_UPDATE)
+
+/*
+ * Request INTEL_SIP_SMC_ECC_DBE
+ *
+ * Sync call used by service driver at EL1 alert EL3 that a Double Bit
+ * ECC error has occurred.
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_ECC_DBE
+ * a1 SysManager Double Bit Error value
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_ECC_DBE 13
+#define INTEL_SIP_SMC_ECC_DBE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_ECC_DBE)
+
+/*
+* Request INTEL_SIP_SMC_RSU_NOTIFY
+*
+* Sync call used by service driver at EL1 to report HPS software execution stage
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_NOTIFY
+* a1 32bit HPS software execution stage
+* a2-7 not used
+*
+* Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_NOTIFY 14
+#define INTEL_SIP_SMC_RSU_NOTIFY \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_NOTIFY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_RETRY_COUNTER
+ *
+ * Sync call used by service driver at EL1 to query the RSU retry counter
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_RETRY_COUNTER
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_RSU_ERROR.
+ * a1 retry counter
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER 15
+#define INTEL_SIP_SMC_RSU_RETRY_COUNTER \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_DCMF_VERSION
+ *
+ * Sync call used by service driver at EL1 to query DCMF version
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_DCMF_VERSION
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 dcmf1 version | dcmf0 version
+ * a2 dcmf3 version | dcmf2 version
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION 16
+#define INTEL_SIP_SMC_RSU_DCMF_VERSION \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION
+ *
+ * Sync call used by SSBL (EL2) to copy DCMF version to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION
+ * a1 dcmf1 version | dcmf0 version
+ * a2 dcmf3 version | dcmf2 version
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION 17
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_MAX_RETRY
+ *
+ * Sync call used by service driver at EL1 to query max_retry parameter
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_MAX_RETRY
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 max_retry
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY 18
+#define INTEL_SIP_SMC_RSU_MAX_RETRY \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_MAX_RETRY
+ *
+ * Sync call used by SSBL (EL2) to copy RSU 'max retry' to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_MAX_RETRY
+ * a1 max retry
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY 19
+#define INTEL_SIP_SMC_RSU_COPY_MAX_RETRY \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_DCMF_STATUS
+ *
+ * Sync call used by service driver at EL1 to query DCMF status
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_DCMF_STATUS
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 dcmf3 status | dcmf2 status | dcmf1 status | dcmf0 status
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS 20
+#define INTEL_SIP_SMC_RSU_DCMF_STATUS \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS
+ *
+ * Sync call used by SSBL (EL2) to copy RSU 'dcmf status' to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS
+ * a1 dcmf status
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS 21
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS)
+
+/*
+ * Request INTEL_SIP_SMC_HPS_SET_BRIDGES
+ *
+ * Enable/disable the SoC FPGA bridges
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_HPS_SET_BRIDGES
+ * a1 Set bridges status:
+ *      0 - Disable
+ *      1 - Enable
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES	50
+#define INTEL_SIP_SMC_HPS_SET_BRIDGES \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES)
+
+/*
+ * Request INTEL_SIP_SMC_MBOX_SEND_CMD
+ *
+ * Send mailbox command to SDM
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_MBOX_SEND_CMD
+ * a1 Mailbox command
+ * a2 64bit physical address pointer to command's arguments
+ * a3 Length of the argument
+ * a4 Urgent command:
+ *      0 - Disable
+ *      1 - Enable
+ * a5 64bit physical address pointer to a buffer for receiving responses
+ * a6 Length of the buffer
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR
+ * a1 Status of mailbox response
+ * a2 Received length in the buffer
+ */
+#define INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD	60
+#define INTEL_SIP_SMC_MBOX_SEND_CMD \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD)
+
+/*
+ * Request INTEL_SIP_SMC_HPS_SET_PHYINTF
+ *
+ * Select EMACx PHY interface
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_HPS_SET_PHYINTF
+ * a1 EMAC number:
+ *      0 - EMAC0
+ *      1 - EMAC1
+ *      2 - EMAC2
+ * a2 Type of PHY interface:
+ *      0 - GMII_MII
+ *      1 - RGMII
+ *      2 - RMII
+ *      3 - RESET
+ * a3-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF	61
+#define INTEL_SIP_SMC_HPS_SET_PHYINTF \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF)
+
+/*
+ * Request INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK
+ *
+ * Select which phase shift of the clocks (drvsel & smplsel) for SDMMC
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK
+ * a1 Select which phase shift of the clock for cclk_in_drv (drvsel):
+ *      0 - 0 degree
+ *      1 - 45 degrees
+ *      2 - 90 degrees
+ *      3 - 135 degrees
+ *      4 - 180 degrees
+ *      5 - 225 degrees
+ *      6 - 270 degrees
+ *      7 - 315 degrees
+ * a2 Select which phase shift of the clock for cclk_in_sample (smplsel):
+ *      (Same as above)
+ * a3-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK	62
+#define INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK)
+
+#endif

+ 70 - 16
tools/socfpgaimage.c

@@ -61,6 +61,7 @@
 
 #define HEADER_OFFSET	0x40
 #define VALIDATION_WORD	0x31305341
+#define IMAGE_ALIGN	16
 
 /* Minimum and default entry point offset */
 #define ENTRY_POINT_OFFSET	0x14
@@ -97,7 +98,7 @@ static unsigned int sfp_hdr_size(uint8_t ver)
 	return 0;
 }
 
-static unsigned int sfp_pad_size(uint8_t ver)
+static unsigned int sfp_max_size(uint8_t ver)
 {
 	if (ver == 0)
 		return sizeof(buffer_v0);
@@ -106,6 +107,12 @@ static unsigned int sfp_pad_size(uint8_t ver)
 	return 0;
 }
 
+static unsigned int sfp_aligned_len(uint32_t size)
+{
+	/* Add 4 bytes for CRC and align to 16 bytes */
+	return ALIGN(size + sizeof(uint32_t), IMAGE_ALIGN);
+}
+
 /*
  * The header checksum is just a very simple checksum over
  * the header area.
@@ -208,22 +215,24 @@ static int sfp_sign_buffer(uint8_t *buf, uint8_t ver, uint8_t flags,
 			   struct image_tool_params *params)
 {
 	uint32_t calc_crc;
+	uint32_t crc_off;
 
 	/* Align the length up */
-	len = ALIGN(len, 4);
+	len = sfp_aligned_len(len);
 
-	/* Build header, adding 4 bytes to length to hold the CRC32. */
-	sfp_build_header(buf + HEADER_OFFSET, ver, flags, len + 4, params);
+	/* Build header */
+	sfp_build_header(buf + HEADER_OFFSET, ver, flags, len, params);
 
 	/* Calculate and apply the CRC */
-	calc_crc = ~pbl_crc32(0, (char *)buf, len);
+	crc_off = len - sizeof(uint32_t); /* at last 4 bytes of image */
+	calc_crc = ~pbl_crc32(0, (char *)buf, crc_off);
 
-	*((uint32_t *)(buf + len)) = cpu_to_le32(calc_crc);
+	*((uint32_t *)(buf + crc_off)) = cpu_to_le32(calc_crc);
 
 	if (!pad_64k)
 		return len + 4;
 
-	return sfp_pad_size(ver);
+	return sfp_max_size(ver);
 }
 
 /* Verify that the buffer looks sane */
@@ -240,7 +249,7 @@ static int sfp_verify_buffer(const uint8_t *buf)
 		return -1;
 	}
 
-	if (len < HEADER_OFFSET || len > sfp_pad_size(ver)) {
+	if (len < HEADER_OFFSET || len > sfp_max_size(ver)) {
 		debug("Invalid header length (%i)\n", len);
 		return -1;
 	}
@@ -274,12 +283,51 @@ static int socfpgaimage_verify_header(unsigned char *ptr, int image_size,
 	return sfp_verify_buffer(ptr);
 }
 
+static void socfpgaimage_print_header_v0(struct socfpga_header_v0 *header)
+{
+	printf("Image Type\t: Cyclone V / Arria V SoC Image\n");
+	printf("Validation word\t: 0x%08x\n",
+	       le32_to_cpu(header->validation));
+	printf("Version\t\t: 0x%08x\n", header->version);
+	printf("Flags\t\t: 0x%08x\n", header->flags);
+	printf("Program length\t: 0x%08x\n",
+	       le16_to_cpu(header->length_u32));
+	printf("Header checksum\t: 0x%08x\n",
+	       le16_to_cpu(header->checksum));
+}
+
+static void socfpgaimage_print_header_v1(struct socfpga_header_v1 *header)
+{
+	printf("Image Type\t: Arria 10 SoC Image\n");
+	printf("Validation word\t: 0x%08x\n",
+	       le32_to_cpu(header->validation));
+	printf("Version\t\t: 0x%08x\n", header->version);
+	printf("Flags\t\t: 0x%08x\n", header->flags);
+	printf("Header length\t: 0x%08x\n",
+	       le16_to_cpu(header->header_u8));
+	printf("Program length\t: 0x%08x\n",
+	       le32_to_cpu(header->length_u8));
+	printf("Program entry\t: 0x%08x\n",
+	       le32_to_cpu(header->entry_offset));
+	printf("Header checksum\t: 0x%08x\n",
+	       le16_to_cpu(header->checksum));
+}
+
 static void socfpgaimage_print_header(const void *ptr)
 {
-	if (sfp_verify_buffer(ptr) == 0)
-		printf("Looks like a sane SOCFPGA preloader\n");
-	else
+	const void *header = ptr + HEADER_OFFSET;
+	struct socfpga_header_v0 *header_v0;
+
+	if (sfp_verify_buffer(ptr) == 0) {
+		header_v0 = (struct socfpga_header_v0 *)header;
+
+		if (header_v0->version == 0)
+			socfpgaimage_print_header_v0(header_v0);
+		else
+			socfpgaimage_print_header_v1((struct socfpga_header_v1 *)header);
+	} else {
 		printf("Not a sane SOCFPGA preloader\n");
+	}
 }
 
 static int socfpgaimage_check_params_v0(struct image_tool_params *params)
@@ -328,19 +376,25 @@ static int socfpgaimage_check_image_types_v1(uint8_t type)
  * To work in with the mkimage framework, we do some ugly stuff...
  *
  * First, socfpgaimage_vrec_header() is called.
- * We prepend a fake header big enough to make the file sfp_pad_size().
+ * We prepend a fake header big enough to include crc32 and align image to 16
+ * bytes.
  * This gives us enough space to do what we want later.
  *
  * Next, socfpgaimage_set_header() is called.
  * We fix up the buffer by moving the image to the start of the buffer.
- * We now have some room to do what we need (add CRC and padding).
+ * We now have some room to do what we need (add CRC).
  */
 
 static int data_size;
 
 static int sfp_fake_header_size(unsigned int size, uint8_t ver)
 {
-	return sfp_pad_size(ver) - size;
+	unsigned int align_size;
+
+	align_size = sfp_aligned_len(size);
+
+	/* extra bytes needed */
+	return align_size - size;
 }
 
 static int sfp_vrec_header(struct image_tool_params *params,
@@ -350,7 +404,7 @@ static int sfp_vrec_header(struct image_tool_params *params,
 
 	if (params->datafile &&
 	    stat(params->datafile, &sbuf) == 0 &&
-	    sbuf.st_size <= (sfp_pad_size(ver) - sizeof(uint32_t))) {
+	    sbuf.st_size <= (sfp_max_size(ver) - sizeof(uint32_t))) {
 		data_size = sbuf.st_size;
 		tparams->header_size = sfp_fake_header_size(data_size, ver);
 	}
@@ -378,7 +432,7 @@ static void sfp_set_header(void *ptr, unsigned char ver,
 	/*
 	 * This function is called after vrec_header() has been called.
 	 * At this stage we have the sfp_fake_header_size() dummy bytes
-	 * followed by data_size image bytes. Total = sfp_pad_size().
+	 * followed by data_size image bytes.
 	 * We need to fix the buffer by moving the image bytes back to
 	 * the beginning of the buffer, then actually do the signing stuff...
 	 */