Pārlūkot izejas kodu

Merge branch 'master' of git://git.denx.de/u-boot-socfpga

- A10 FPGA programming support, Gen5 livetree conversion
Tom Rini 5 gadi atpakaļ
vecāks
revīzija
d2d8f73da4

+ 17 - 0
arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts

@@ -18,6 +18,23 @@
 /dts-v1/;
 #include "socfpga_arria10_socdk.dtsi"
 
+/ {
+	chosen {
+		firmware-loader = <&fs_loader0>;
+	};
+
+	fs_loader0: fs-loader {
+		u-boot,dm-pre-reloc;
+		compatible = "u-boot,fs-loader";
+		phandlepart = <&mmc 1>;
+	};
+};
+
+&fpga_mgr {
+	u-boot,dm-pre-reloc;
+	altr,bitstream = "fit_spl_fpga.itb";
+};
+
 &mmc {
 	u-boot,dm-pre-reloc;
 	status = "okay";

+ 38 - 2
arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h

@@ -1,9 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2017 Intel Corporation <www.intel.com>
+ * Copyright (C) 2017-2019 Intel Corporation <www.intel.com>
  * All rights reserved.
  */
 
+#include <asm/cache.h>
+#include <altera.h>
+#include <image.h>
+
 #ifndef _FPGA_MANAGER_ARRIA10_H_
 #define _FPGA_MANAGER_ARRIA10_H_
 
@@ -51,6 +55,10 @@
 #define ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK		BIT(24)
 #define ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB			16
 
+#define FPGA_SOCFPGA_A10_RBF_UNENCRYPTED	0xa65c
+#define FPGA_SOCFPGA_A10_RBF_ENCRYPTED		0xa65d
+#define FPGA_SOCFPGA_A10_RBF_PERIPH		0x0001
+#define FPGA_SOCFPGA_A10_RBF_CORE		0x8001
 #ifndef __ASSEMBLY__
 
 struct socfpga_fpga_manager {
@@ -88,12 +96,40 @@ struct socfpga_fpga_manager {
 	u32  imgcfg_fifo_status;
 };
 
+enum rbf_type {
+	unknown,
+	periph_section,
+	core_section
+};
+
+enum rbf_security {
+	invalid,
+	unencrypted,
+	encrypted
+};
+
+struct rbf_info {
+	enum rbf_type section;
+	enum rbf_security security;
+};
+
+struct fpga_loadfs_info {
+	fpga_fs_info *fpga_fsinfo;
+	u32 remaining;
+	u32 offset;
+	struct rbf_info rbfinfo;
+};
+
 /* Functions */
 int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size);
 int fpgamgr_program_finish(void);
 int is_fpgamgr_user_mode(void);
 int fpgamgr_wait_early_user_mode(void);
-
+const char *get_fpga_filename(void);
+int is_fpgamgr_early_user_mode(void);
+int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize,
+		  u32 offset);
+void fpgamgr_program(const void *buf, size_t bsize, u32 offset);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _FPGA_MANAGER_ARRIA10_H_ */

+ 30 - 1
arch/arm/mach-socfpga/spl_a10.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- *  Copyright (C) 2012 Altera Corporation <www.altera.com>
+ *  Copyright (C) 2012-2019 Altera Corporation <www.altera.com>
  */
 
 #include <common.h>
@@ -23,6 +23,11 @@
 #include <fdtdec.h>
 #include <watchdog.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch/fpga_manager.h>
+#include <mmc.h>
+#include <memalign.h>
+
+#define FPGA_BUFSIZ	16 * 1024
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -68,11 +73,35 @@ u32 spl_boot_mode(const u32 boot_device)
 
 void spl_board_init(void)
 {
+	ALLOC_CACHE_ALIGN_BUFFER(char, buf, FPGA_BUFSIZ);
+
 	/* enable console uart printing */
 	preloader_console_init();
 	WATCHDOG_RESET();
 
 	arch_early_init_r();
+
+	/* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */
+	if (is_fpgamgr_user_mode()) {
+		int ret = config_pins(gd->fdt_blob, "shared");
+
+		if (ret)
+			return;
+
+		ret = config_pins(gd->fdt_blob, "fpga");
+		if (ret)
+			return;
+	} else if (!is_fpgamgr_early_user_mode()) {
+		/* Program IOSSM(early IO release) or full FPGA */
+		fpgamgr_program(buf, FPGA_BUFSIZ, 0);
+	}
+
+	/* If the IOSSM/full FPGA is already loaded, start DDR */
+	if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode())
+		ddr_calibration_sequence();
+
+	if (!is_fpgamgr_user_mode())
+		fpgamgr_program(buf, FPGA_BUFSIZ, 0);
 }
 
 void board_init_f(ulong dummy)

+ 38 - 0
board/altera/arria10-socdk/fit_spl_fpga.its

@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+ /*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ *
+ */
+
+/dts-v1/;
+
+/ {
+	description = "FIT image with FPGA bistream";
+	#address-cells = <1>;
+
+	images {
+		fpga-periph-1 {
+			description = "FPGA peripheral bitstream";
+			data = /incbin/("../../../ghrd_10as066n2.periph.rbf");
+			type = "fpga";
+			arch = "arm";
+			compression = "none";
+		};
+
+		fpga-core-1 {
+			description = "FPGA core bitstream";
+			data = /incbin/("../../../ghrd_10as066n2.core.rbf");
+			type = "fpga";
+			arch = "arm";
+			compression = "none";
+		};
+	};
+
+	configurations {
+		default = "config-1";
+		config-1 {
+			description = "Boot with FPGA early IO release config";
+			fpga = "fpga-periph-1", "fpga-core-1";
+		};
+	};
+};

+ 19 - 4
configs/socfpga_arria10_defconfig

@@ -6,12 +6,15 @@ CONFIG_DISTRO_DEFAULTS=y
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="console=ttyS0,115200"
 # CONFIG_USE_BOOTCOMMAND is not set
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
+CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
+CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y
 CONFIG_DEFAULT_FDT_FILE="socfpga_arria10_socdk_sdmmc.dtb"
+CONFIG_VERSION_VARIABLE=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_BOUNCE_BUFFER=y
 CONFIG_SPL_TEXT_BASE=0xFFE00000
 CONFIG_SPL_FPGA_SUPPORT=y
-CONFIG_SPL_SPI_LOAD=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 # CONFIG_CMD_FLASH is not set
@@ -20,19 +23,31 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MTDIDS_DEFAULT="nor0=ff705000.spi.0"
-# CONFIG_SPL_DOS_PARTITION is not set
-# CONFIG_ISO_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
 CONFIG_DEFAULT_DEVICE_TREE="socfpga_arria10_socdk_sdmmc"
 CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SPL_ENV_SUPPORT=y
+CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_DM_MMC=y
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_FS_FAT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_FS_LOADER=y
+CONFIG_FPGA_SOCFPGA=y
+CONFIG_SPL_FIT=y
+CONFIG_FIT=y
 CONFIG_DM_GPIO=y
 CONFIG_DWAPB_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_MTD_DEVICE=y
+CONFIG_MMC_DW=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
+CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_TIMER=y
 CONFIG_SPL_TIMER=y

+ 0 - 1
configs/socfpga_stratix10_defconfig

@@ -42,7 +42,6 @@ CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_MODE=0x2003
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
-# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y

+ 25 - 1
doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt

@@ -7,8 +7,31 @@ Required properties:
                - The second index is for writing FPGA configuration data.
 - resets     : Phandle and reset specifier for the device's reset.
 - clocks     : Clocks used by the device.
+- altr,bitstream : Fit image file name for both FPGA peripheral bitstream,
+		   FPGA core bitstream and full bitstream.
 
-Example:
+		   Full bitstream, consist of peripheral bitstream and core
+		   bitstream.
+
+		   FPGA peripheral bitstream is used to initialize FPGA IOs,
+		   PLL, IO48 and DDR. This bitstream is required to get DDR up
+		   running.
+
+		   FPGA core bitstream contains FPGA design which is used to
+		   program FPGA CRAM and ERAM.
+
+Example: Bundles both peripheral bitstream and core bitstream into FIT image
+	 called fit_spl_fpga.itb. This FIT image can be created through running
+	 this command: tools/mkimage
+		       -E -p 400
+		       -f board/altera/arria10-socdk/fit_spl_fpga.its
+		       fit_spl_fpga.itb
+
+	 For details of describing structure and contents of the FIT image,
+	 please refer board/altera/arria10-socdk/fit_spl_fpga.its
+
+- Examples for booting with full release or booting with early IO release, then
+  follow by entering early user mode:
 
 	fpga_mgr: fpga-mgr@ffd03000 {
 		compatible = "altr,socfpga-a10-fpga-mgr";
@@ -16,4 +39,5 @@ Example:
 		       0xffcfe400 0x20>;
 		clocks = <&l4_mp_clk>;
 		resets = <&rst FPGAMGR_RESET>;
+		altr,bitstream = "fit_spl_fpga.itb";
 	};

+ 493 - 21
drivers/fpga/socfpga_arria10.c

@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2017 Intel Corporation <www.intel.com>
+ * Copyright (C) 2017-2019 Intel Corporation <www.intel.com>
  */
-
 #include <asm/io.h>
 #include <asm/arch/fpga_manager.h>
 #include <asm/arch/reset_manager.h>
@@ -10,8 +9,11 @@
 #include <asm/arch/sdram.h>
 #include <asm/arch/misc.h>
 #include <altera.h>
+#include <asm/arch/pinmux.h>
 #include <common.h>
+#include <dm/ofnode.h>
 #include <errno.h>
+#include <fs_loader.h>
 #include <wait_bit.h>
 #include <watchdog.h>
 
@@ -21,6 +23,9 @@
 #define COMPRESSION_OFFSET	229
 #define FPGA_TIMEOUT_MSEC	1000  /* timeout in ms */
 #define FPGA_TIMEOUT_CNT	0x1000000
+#define DEFAULT_DDR_LOAD_ADDRESS	0x400
+
+DECLARE_GLOBAL_DATA_PTR;
 
 static const struct socfpga_fpga_manager *fpga_manager_base =
 		(void *)SOCFPGA_FPGAMGRREGS_ADDRESS;
@@ -64,7 +69,7 @@ static int wait_for_user_mode(void)
 		1, FPGA_TIMEOUT_MSEC, false);
 }
 
-static int is_fpgamgr_early_user_mode(void)
+int is_fpgamgr_early_user_mode(void)
 {
 	return (readl(&fpga_manager_base->imgcfg_stat) &
 		ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0;
@@ -94,7 +99,7 @@ int fpgamgr_wait_early_user_mode(void)
 		i++;
 	}
 
-	debug("Additional %i sync word needed\n", i);
+	debug("FPGA: Additional %i sync word needed\n", i);
 
 	/* restoring original CDRATIO */
 	fpgamgr_set_cd_ratio(cd_ratio);
@@ -172,9 +177,10 @@ static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data,
 	compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1;
 	compress = !compress;
 
-	debug("header word %d = %08x\n", 69, rbf_data[69]);
-	debug("header word %d = %08x\n", 229, rbf_data[229]);
-	debug("read from rbf header: encrypt=%d compress=%d\n", encrypt, compress);
+	debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]);
+	debug("FPGA: Header word %d = %08x.\n", 229, rbf_data[229]);
+	debug("FPGA: Read from rbf header: encrypt=%d compress=%d.\n", encrypt,
+	     compress);
 
 	/*
 	 * from the register map description of cdratio in imgcfg_ctrl_02:
@@ -359,6 +365,7 @@ static int fpgamgr_program_poll_cd(void)
 			printf("nstatus == 0 while waiting for condone\n");
 			return -EPERM;
 		}
+		WATCHDOG_RESET();
 	}
 
 	if (i == FPGA_TIMEOUT_CNT)
@@ -432,7 +439,6 @@ int fpgamgr_program_finish(void)
 		printf("FPGA: Poll CD failed with error code %d\n", status);
 		return -EPERM;
 	}
-	WATCHDOG_RESET();
 
 	/* Ensure the FPGA entering user mode */
 	status = fpgamgr_program_poll_usermode();
@@ -447,27 +453,493 @@ int fpgamgr_program_finish(void)
 	return 0;
 }
 
-/*
- * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
- * Return 0 for sucess, non-zero for error.
- */
+ofnode get_fpga_mgr_ofnode(ofnode from)
+{
+	return ofnode_by_compatible(from, "altr,socfpga-a10-fpga-mgr");
+}
+
+const char *get_fpga_filename(void)
+{
+	const char *fpga_filename = NULL;
+
+	ofnode fpgamgr_node = get_fpga_mgr_ofnode(ofnode_null());
+
+	if (ofnode_valid(fpgamgr_node))
+		fpga_filename = ofnode_read_string(fpgamgr_node,
+						"altr,bitstream");
+
+	return fpga_filename;
+}
+
+static void get_rbf_image_info(struct rbf_info *rbf, u16 *buffer)
+{
+	/*
+	 * Magic ID starting at:
+	 * -> 1st dword[15:0] in periph.rbf
+	 * -> 2nd dword[15:0] in core.rbf
+	 * Note: dword == 32 bits
+	 */
+	u32 word_reading_max = 2;
+	u32 i;
+
+	for (i = 0; i < word_reading_max; i++) {
+		if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) {
+			rbf->security = unencrypted;
+		} else if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_ENCRYPTED) {
+			rbf->security = encrypted;
+		} else if (*(buffer + i + 1) ==
+				FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) {
+			rbf->security = unencrypted;
+		} else if (*(buffer + i + 1) ==
+				FPGA_SOCFPGA_A10_RBF_ENCRYPTED) {
+			rbf->security = encrypted;
+		} else {
+			rbf->security = invalid;
+			continue;
+		}
+
+		/* PERIPH RBF(buffer + i + 1), CORE RBF(buffer + i + 2) */
+		if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_PERIPH) {
+			rbf->section = periph_section;
+			break;
+		} else if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_CORE) {
+			rbf->section = core_section;
+			break;
+		} else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_PERIPH) {
+			rbf->section = periph_section;
+			break;
+		} else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_CORE) {
+			rbf->section = core_section;
+			break;
+		}
+
+		rbf->section = unknown;
+		break;
+
+		WATCHDOG_RESET();
+	}
+}
+
+#ifdef CONFIG_FS_LOADER
+static int first_loading_rbf_to_buffer(struct udevice *dev,
+				struct fpga_loadfs_info *fpga_loadfs,
+				u32 *buffer, size_t *buffer_bsize)
+{
+	u32 *buffer_p = (u32 *)*buffer;
+	u32 *loadable = buffer_p;
+	size_t buffer_size = *buffer_bsize;
+	size_t fit_size;
+	int ret, i, count, confs_noffset, images_noffset, rbf_offset, rbf_size;
+	const char *fpga_node_name = NULL;
+	const char *uname = NULL;
+
+	/* Load image header into buffer */
+	ret = request_firmware_into_buf(dev,
+					fpga_loadfs->fpga_fsinfo->filename,
+					buffer_p, sizeof(struct image_header),
+					0);
+	if (ret < 0) {
+		debug("FPGA: Failed to read image header from flash.\n");
+		return -ENOENT;
+	}
+
+	if (image_get_magic((struct image_header *)buffer_p) != FDT_MAGIC) {
+		debug("FPGA: No FDT magic was found.\n");
+		return -EBADF;
+	}
+
+	fit_size = fdt_totalsize(buffer_p);
+
+	if (fit_size > buffer_size) {
+		debug("FPGA: FIT image is larger than available buffer.\n");
+		debug("Please use FIT external data or increasing buffer.\n");
+		return -ENOMEM;
+	}
+
+	/* Load entire FIT into buffer */
+	ret = request_firmware_into_buf(dev,
+					fpga_loadfs->fpga_fsinfo->filename,
+					buffer_p, fit_size, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = fit_check_format(buffer_p);
+	if (!ret) {
+		debug("FPGA: No valid FIT image was found.\n");
+		return -EBADF;
+	}
+
+	confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH);
+	images_noffset = fdt_path_offset(buffer_p, FIT_IMAGES_PATH);
+	if (confs_noffset < 0 || images_noffset < 0) {
+		debug("FPGA: No Configurations or images nodes were found.\n");
+		return -ENOENT;
+	}
+
+	/* Get default configuration unit name from default property */
+	confs_noffset = fit_conf_get_node(buffer_p, NULL);
+	if (confs_noffset < 0) {
+		debug("FPGA: No default configuration was found in config.\n");
+		return -ENOENT;
+	}
+
+	count = fit_conf_get_prop_node_count(buffer_p, confs_noffset,
+					    FIT_FPGA_PROP);
+	if (count < 0) {
+		debug("FPGA: Invalid configuration format for FPGA node.\n");
+		return count;
+	}
+	debug("FPGA: FPGA node count: %d\n", count);
+
+	for (i = 0; i < count; i++) {
+		images_noffset = fit_conf_get_prop_node_index(buffer_p,
+							     confs_noffset,
+							     FIT_FPGA_PROP, i);
+		uname = fit_get_name(buffer_p, images_noffset, NULL);
+		if (uname) {
+			debug("FPGA: %s\n", uname);
+
+			if (strstr(uname, "fpga-periph") &&
+				(!is_fpgamgr_early_user_mode() ||
+				is_fpgamgr_user_mode())) {
+				fpga_node_name = uname;
+				printf("FPGA: Start to program ");
+				printf("peripheral/full bitstream ...\n");
+				break;
+			} else if (strstr(uname, "fpga-core") &&
+					(is_fpgamgr_early_user_mode() &&
+					!is_fpgamgr_user_mode())) {
+				fpga_node_name = uname;
+				printf("FPGA: Start to program core ");
+				printf("bitstream ...\n");
+				break;
+			}
+		}
+		WATCHDOG_RESET();
+	}
+
+	if (!fpga_node_name) {
+		debug("FPGA: No suitable bitstream was found, count: %d.\n", i);
+		return 1;
+	}
+
+	images_noffset = fit_image_get_node(buffer_p, fpga_node_name);
+	if (images_noffset < 0) {
+		debug("FPGA: No node '%s' was found in FIT.\n",
+		     fpga_node_name);
+		return -ENOENT;
+	}
+
+	if (!fit_image_get_data_position(buffer_p, images_noffset,
+					&rbf_offset)) {
+		debug("FPGA: Data position was found.\n");
+	} else if (!fit_image_get_data_offset(buffer_p, images_noffset,
+		  &rbf_offset)) {
+		/*
+		 * For FIT with external data, figure out where
+		 * the external images start. This is the base
+		 * for the data-offset properties in each image.
+		 */
+		rbf_offset += ((fdt_totalsize(buffer_p) + 3) & ~3);
+		debug("FPGA: Data offset was found.\n");
+	} else {
+		debug("FPGA: No data position/offset was found.\n");
+		return -ENOENT;
+	}
+
+	ret = fit_image_get_data_size(buffer_p, images_noffset, &rbf_size);
+	if (ret < 0) {
+		debug("FPGA: No data size was found (err=%d).\n", ret);
+		return -ENOENT;
+	}
+
+	if (gd->ram_size < rbf_size) {
+		debug("FPGA: Using default OCRAM buffer and size.\n");
+	} else {
+		ret = fit_image_get_load(buffer_p, images_noffset,
+					(ulong *)loadable);
+		if (ret < 0) {
+			buffer_p = (u32 *)DEFAULT_DDR_LOAD_ADDRESS;
+			debug("FPGA: No loadable was found.\n");
+			debug("FPGA: Using default DDR load address: 0x%x .\n",
+			     DEFAULT_DDR_LOAD_ADDRESS);
+		} else {
+			buffer_p = (u32 *)*loadable;
+			debug("FPGA: Found loadable address = 0x%x.\n",
+			     *loadable);
+		}
+
+		buffer_size = rbf_size;
+	}
+
+	debug("FPGA: External data: offset = 0x%x, size = 0x%x.\n",
+	      rbf_offset, rbf_size);
+
+	fpga_loadfs->remaining = rbf_size;
+
+	/*
+	 * Determine buffer size vs bitstream size, and calculating number of
+	 * chunk by chunk transfer is required due to smaller buffer size
+	 * compare to bitstream
+	 */
+	if (rbf_size <= buffer_size) {
+		/* Loading whole bitstream into buffer */
+		buffer_size = rbf_size;
+		fpga_loadfs->remaining = 0;
+	} else {
+		fpga_loadfs->remaining -= buffer_size;
+	}
+
+	fpga_loadfs->offset = rbf_offset;
+	/* Loading bitstream into buffer */
+	ret = request_firmware_into_buf(dev,
+					fpga_loadfs->fpga_fsinfo->filename,
+					buffer_p, buffer_size,
+					fpga_loadfs->offset);
+	if (ret < 0) {
+		debug("FPGA: Failed to read bitstream from flash.\n");
+		return -ENOENT;
+	}
+
+	/* Getting info about bitstream types */
+	get_rbf_image_info(&fpga_loadfs->rbfinfo, (u16 *)buffer_p);
+
+	/* Update next reading bitstream offset */
+	fpga_loadfs->offset += buffer_size;
+
+	/* Update the final addr for bitstream */
+	*buffer = (u32)buffer_p;
+
+	/* Update the size of bitstream to be programmed into FPGA */
+	*buffer_bsize = buffer_size;
+
+	return 0;
+}
+
+static int subsequent_loading_rbf_to_buffer(struct udevice *dev,
+					struct fpga_loadfs_info *fpga_loadfs,
+					u32 *buffer, size_t *buffer_bsize)
+{
+	int ret = 0;
+	u32 *buffer_p = (u32 *)*buffer;
+
+	/* Read the bitstream chunk by chunk. */
+	if (fpga_loadfs->remaining > *buffer_bsize) {
+		fpga_loadfs->remaining -= *buffer_bsize;
+	} else {
+		*buffer_bsize = fpga_loadfs->remaining;
+		fpga_loadfs->remaining = 0;
+	}
+
+	ret = request_firmware_into_buf(dev,
+					fpga_loadfs->fpga_fsinfo->filename,
+					buffer_p, *buffer_bsize,
+					fpga_loadfs->offset);
+	if (ret < 0) {
+		debug("FPGA: Failed to read bitstream from flash.\n");
+		return -ENOENT;
+	}
+
+	/* Update next reading bitstream offset */
+	fpga_loadfs->offset += *buffer_bsize;
+
+	return 0;
+}
+
+int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize,
+			u32 offset)
+{
+	struct fpga_loadfs_info fpga_loadfs;
+	struct udevice *dev;
+	int status, ret, size;
+	u32 buffer = (uintptr_t)buf;
+	size_t buffer_sizebytes = bsize;
+	size_t buffer_sizebytes_ori = bsize;
+	size_t total_sizeof_image = 0;
+	ofnode node;
+	const fdt32_t *phandle_p;
+	u32 phandle;
+
+	node = get_fpga_mgr_ofnode(ofnode_null());
+
+	if (ofnode_valid(node)) {
+		phandle_p = ofnode_get_property(node, "firmware-loader", &size);
+		if (!phandle_p) {
+			node = ofnode_path("/chosen");
+			if (!ofnode_valid(node)) {
+				debug("FPGA: /chosen node was not found.\n");
+				return -ENOENT;
+			}
+
+			phandle_p = ofnode_get_property(node, "firmware-loader",
+						       &size);
+			if (!phandle_p) {
+				debug("FPGA: firmware-loader property was not");
+				debug(" found.\n");
+				return -ENOENT;
+			}
+		}
+	} else {
+		debug("FPGA: FPGA manager node was not found.\n");
+		return -ENOENT;
+	}
+
+	phandle = fdt32_to_cpu(*phandle_p);
+	ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
+					     phandle, &dev);
+	if (ret)
+		return ret;
+
+	memset(&fpga_loadfs, 0, sizeof(fpga_loadfs));
+
+	fpga_loadfs.fpga_fsinfo = fpga_fsinfo;
+	fpga_loadfs.offset = offset;
+
+	printf("FPGA: Checking FPGA configuration setting ...\n");
+
+	/*
+	 * Note: Both buffer and buffer_sizebytes values can be altered by
+	 * function below.
+	 */
+	ret = first_loading_rbf_to_buffer(dev, &fpga_loadfs, &buffer,
+					   &buffer_sizebytes);
+	if (ret == 1) {
+		printf("FPGA: Skipping configuration ...\n");
+		return 0;
+	} else if (ret) {
+		return ret;
+	}
+
+	if (fpga_loadfs.rbfinfo.section == core_section &&
+		!(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) {
+		debug("FPGA : Must be in Early Release mode to program ");
+		debug("core bitstream.\n");
+		return -EPERM;
+	}
+
+	/* Disable all signals from HPS peripheral controller to FPGA */
+	writel(0, &system_manager_base->fpgaintf_en_global);
+
+	/* Disable all axi bridges (hps2fpga, lwhps2fpga & fpga2hps) */
+	socfpga_bridges_reset();
+
+	if (fpga_loadfs.rbfinfo.section == periph_section) {
+		/* Initialize the FPGA Manager */
+		status = fpgamgr_program_init((u32 *)buffer, buffer_sizebytes);
+		if (status) {
+			debug("FPGA: Init with peripheral bitstream failed.\n");
+			return -EPERM;
+		}
+	}
+
+	/* Transfer bitstream to FPGA Manager */
+	fpgamgr_program_write((void *)buffer, buffer_sizebytes);
+
+	total_sizeof_image += buffer_sizebytes;
+
+	while (fpga_loadfs.remaining) {
+		ret = subsequent_loading_rbf_to_buffer(dev,
+							&fpga_loadfs,
+							&buffer,
+							&buffer_sizebytes_ori);
+
+		if (ret)
+			return ret;
+
+		/* Transfer data to FPGA Manager */
+		fpgamgr_program_write((void *)buffer,
+					buffer_sizebytes_ori);
+
+		total_sizeof_image += buffer_sizebytes_ori;
+
+		WATCHDOG_RESET();
+	}
+
+	if (fpga_loadfs.rbfinfo.section == periph_section) {
+		if (fpgamgr_wait_early_user_mode() != -ETIMEDOUT) {
+			config_pins(gd->fdt_blob, "shared");
+			puts("FPGA: Early Release Succeeded.\n");
+		} else {
+			debug("FPGA: Failed to see Early Release.\n");
+			return -EIO;
+		}
+
+		/* For monolithic bitstream */
+		if (is_fpgamgr_user_mode()) {
+			/* Ensure the FPGA entering config done */
+			status = fpgamgr_program_finish();
+			if (status)
+				return status;
+
+			config_pins(gd->fdt_blob, "fpga");
+			puts("FPGA: Enter user mode.\n");
+		}
+	} else if (fpga_loadfs.rbfinfo.section == core_section) {
+		/* Ensure the FPGA entering config done */
+		status = fpgamgr_program_finish();
+		if (status)
+			return status;
+
+		config_pins(gd->fdt_blob, "fpga");
+		puts("FPGA: Enter user mode.\n");
+	} else {
+		debug("FPGA: Config Error: Unsupported bitstream type.\n");
+		return -ENOEXEC;
+	}
+
+	return (int)total_sizeof_image;
+}
+
+void fpgamgr_program(const void *buf, size_t bsize, u32 offset)
+{
+	fpga_fs_info fpga_fsinfo;
+
+	fpga_fsinfo.filename = get_fpga_filename();
+
+	if (fpga_fsinfo.filename)
+		socfpga_loadfs(&fpga_fsinfo, buf, bsize, offset);
+}
+#endif
+
+/* This function is used to load the core bitstream from the OCRAM. */
 int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
 {
-	int status;
+	unsigned long status;
+	struct rbf_info rbfinfo;
 
-	/* disable all signals from hps peripheral controller to fpga */
+	memset(&rbfinfo, 0, sizeof(rbfinfo));
+
+	/* Disable all signals from hps peripheral controller to fpga */
 	writel(0, &system_manager_base->fpgaintf_en_global);
 
-	/* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+	/* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
 	socfpga_bridges_reset();
 
-	/* Initialize the FPGA Manager */
-	status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
-	if (status)
-		return status;
+	/* Getting info about bitstream types */
+	get_rbf_image_info(&rbfinfo, (u16 *)rbf_data);
+
+	if (rbfinfo.section == periph_section) {
+		/* Initialize the FPGA Manager */
+		status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
+		if (status)
+			return status;
+	}
 
-	/* Write the RBF data to FPGA Manager */
+	if (rbfinfo.section == core_section &&
+		!(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) {
+		debug("FPGA : Must be in early release mode to program ");
+		debug("core bitstream.\n");
+		return -EPERM;
+	}
+
+	/* Write the bitstream to FPGA Manager */
 	fpgamgr_program_write(rbf_data, rbf_size);
 
-	return fpgamgr_program_finish();
+	status = fpgamgr_program_finish();
+	if (status) {
+		config_pins(gd->fdt_blob, "fpga");
+		puts("FPGA: Enter user mode.\n");
+	}
+
+	return status;
 }

+ 11 - 14
drivers/gpio/dwapb_gpio.c

@@ -17,8 +17,6 @@
 #include <errno.h>
 #include <reset.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #define GPIO_SWPORT_DR(p)	(0x00 + (p) * 0xc)
 #define GPIO_SWPORT_DDR(p)	(0x04 + (p) * 0xc)
 #define GPIO_INTEN		0x30
@@ -150,10 +148,10 @@ static int gpio_dwapb_probe(struct udevice *dev)
 static int gpio_dwapb_bind(struct udevice *dev)
 {
 	struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
-	const void *blob = gd->fdt_blob;
 	struct udevice *subdev;
 	fdt_addr_t base;
-	int ret, node, bank = 0;
+	int ret, bank = 0;
+	ofnode node;
 
 	/* If this is a child device, there is nothing to do here */
 	if (plat)
@@ -165,10 +163,9 @@ static int gpio_dwapb_bind(struct udevice *dev)
 		return -ENXIO;
 	}
 
-	for (node = fdt_first_subnode(blob, dev_of_offset(dev));
-	     node > 0;
-	     node = fdt_next_subnode(blob, node)) {
-		if (!fdtdec_get_bool(blob, node, "gpio-controller"))
+	for (node = dev_read_first_subnode(dev); ofnode_valid(node);
+	     node = dev_read_next_subnode(node)) {
+		if (!ofnode_read_bool(node, "gpio-controller"))
 			continue;
 
 		plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL);
@@ -177,15 +174,15 @@ static int gpio_dwapb_bind(struct udevice *dev)
 
 		plat->base = base;
 		plat->bank = bank;
-		plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0);
-		plat->name = fdt_stringlist_get(blob, node, "bank-name", 0,
-						NULL);
-		if (!plat->name) {
+		plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0);
+
+		if (ofnode_read_string_index(node, "bank-name", 0,
+					     &plat->name)) {
 			/*
 			 * Fall back to node name. This means accessing pins
 			 * via bank name won't work.
 			 */
-			plat->name = fdt_get_name(blob, node, NULL);
+			plat->name = ofnode_get_name(node);
 		}
 
 		ret = device_bind(dev, dev->driver, plat->name,
@@ -193,7 +190,7 @@ static int gpio_dwapb_bind(struct udevice *dev)
 		if (ret)
 			return ret;
 
-		dev_set_of_offset(subdev, node);
+		dev->node = node;
 		bank++;
 	}
 

+ 1 - 3
drivers/reset/reset-socfpga.c

@@ -107,14 +107,12 @@ static const struct reset_ops socfpga_reset_ops = {
 static int socfpga_reset_probe(struct udevice *dev)
 {
 	struct socfpga_reset_data *data = dev_get_priv(dev);
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 	u32 modrst_offset;
 	void __iomem *membase;
 
 	membase = devfdt_get_addr_ptr(dev);
 
-	modrst_offset = fdtdec_get_int(blob, node, "altr,modrst-offset", 0x10);
+	modrst_offset = dev_read_u32_default(dev, "altr,modrst-offset", 0x10);
 	data->modrst_base = membase + modrst_offset;
 
 	return 0;

+ 1 - 4
drivers/serial/altera_uart.c

@@ -10,8 +10,6 @@
 #include <serial.h>
 #include <asm/io.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 /* status register */
 #define ALTERA_UART_TMT		BIT(5)	/* tx empty */
 #define ALTERA_UART_TRDY	BIT(6)	/* tx ready */
@@ -91,8 +89,7 @@ static int altera_uart_ofdata_to_platdata(struct udevice *dev)
 	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_uart_regs),
 				 MAP_NOCACHE);
-	plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-		"clock-frequency", 0);
+	plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0);
 
 	return 0;
 }

+ 19 - 20
drivers/spi/cadence_qspi.c

@@ -18,8 +18,6 @@
 #define CQSPI_INDIRECT_READ		2
 #define CQSPI_INDIRECT_WRITE		3
 
-DECLARE_GLOBAL_DATA_PTR;
-
 static int cadence_spi_write_speed(struct udevice *bus, uint hz)
 {
 	struct cadence_spi_platdata *plat = bus->platdata;
@@ -295,36 +293,37 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen,
 static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
 {
 	struct cadence_spi_platdata *plat = bus->platdata;
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(bus);
-	int subnode;
+	ofnode subnode;
 
 	plat->regbase = (void *)devfdt_get_addr_index(bus, 0);
 	plat->ahbbase = (void *)devfdt_get_addr_index(bus, 1);
-	plat->is_decoded_cs = fdtdec_get_bool(blob, node, "cdns,is-decoded-cs");
-	plat->fifo_depth = fdtdec_get_uint(blob, node, "cdns,fifo-depth", 128);
-	plat->fifo_width = fdtdec_get_uint(blob, node, "cdns,fifo-width", 4);
-	plat->trigger_address = fdtdec_get_uint(blob, node,
-						"cdns,trigger-address", 0);
+	plat->is_decoded_cs = dev_read_bool(bus, "cdns,is-decoded-cs");
+	plat->fifo_depth = dev_read_u32_default(bus, "cdns,fifo-depth", 128);
+	plat->fifo_width = dev_read_u32_default(bus, "cdns,fifo-width", 4);
+	plat->trigger_address = dev_read_u32_default(bus,
+						     "cdns,trigger-address",
+						     0);
 
 	/* All other paramters are embedded in the child node */
-	subnode = fdt_first_subnode(blob, node);
-	if (subnode < 0) {
+	subnode = dev_read_first_subnode(bus);
+	if (!ofnode_valid(subnode)) {
 		printf("Error: subnode with SPI flash config missing!\n");
 		return -ENODEV;
 	}
 
 	/* Use 500 KHz as a suitable default */
-	plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency",
-				       500000);
+	plat->max_hz = ofnode_read_u32_default(subnode, "spi-max-frequency",
+					       500000);
 
 	/* Read other parameters from DT */
-	plat->page_size = fdtdec_get_uint(blob, subnode, "page-size", 256);
-	plat->block_size = fdtdec_get_uint(blob, subnode, "block-size", 16);
-	plat->tshsl_ns = fdtdec_get_uint(blob, subnode, "cdns,tshsl-ns", 200);
-	plat->tsd2d_ns = fdtdec_get_uint(blob, subnode, "cdns,tsd2d-ns", 255);
-	plat->tchsh_ns = fdtdec_get_uint(blob, subnode, "cdns,tchsh-ns", 20);
-	plat->tslch_ns = fdtdec_get_uint(blob, subnode, "cdns,tslch-ns", 20);
+	plat->page_size = ofnode_read_u32_default(subnode, "page-size", 256);
+	plat->block_size = ofnode_read_u32_default(subnode, "block-size", 16);
+	plat->tshsl_ns = ofnode_read_u32_default(subnode, "cdns,tshsl-ns",
+						 200);
+	plat->tsd2d_ns = ofnode_read_u32_default(subnode, "cdns,tsd2d-ns",
+						 255);
+	plat->tchsh_ns = ofnode_read_u32_default(subnode, "cdns,tchsh-ns", 20);
+	plat->tslch_ns = ofnode_read_u32_default(subnode, "cdns,tslch-ns", 20);
 
 	debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n",
 	      __func__, plat->regbase, plat->ahbbase, plat->max_hz,

+ 2 - 6
drivers/spi/designware_spi.c

@@ -22,8 +22,6 @@
 #include <linux/iopoll.h>
 #include <asm/io.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 /* Register offsets */
 #define DW_SPI_CTRL0			0x00
 #define DW_SPI_CTRL1			0x04
@@ -155,14 +153,12 @@ static int request_gpio_cs(struct udevice *bus)
 static int dw_spi_ofdata_to_platdata(struct udevice *bus)
 {
 	struct dw_spi_platdata *plat = bus->platdata;
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(bus);
 
 	plat->regs = (struct dw_spi *)devfdt_get_addr(bus);
 
 	/* Use 500KHz as a suitable default */
-	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
-					500000);
+	plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
+					       500000);
 	debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs,
 	      plat->frequency);
 

+ 0 - 2
drivers/timer/dw-apb-timer.c

@@ -17,8 +17,6 @@
 #define DW_APB_CURR_VAL		0x4
 #define DW_APB_CTRL		0x8
 
-DECLARE_GLOBAL_DATA_PTR;
-
 struct dw_apb_timer_priv {
 	fdt_addr_t	regs;
 };

+ 4 - 1
include/configs/socfpga_arria10_socdk.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- *  Copyright (C) 2015-2017 Altera Corporation <www.altera.com>
+ *  Copyright (C) 2015-2019 Altera Corporation <www.altera.com>
  */
 
 #ifndef __CONFIG_SOCFGPA_ARRIA10_H__
@@ -36,6 +36,9 @@
  */
 #define CONFIG_SYS_MAX_FLASH_BANKS     1
 
+/* SPL memory allocation configuration, this is for FAT implementation */
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00015000
+
 /* The rest of the configuration is shared */
 #include <configs/socfpga_common.h>
 

+ 4 - 0
include/image.h

@@ -1046,6 +1046,10 @@ int fit_check_format(const void *fit);
 
 int fit_conf_find_compat(const void *fit, const void *fdt);
 int fit_conf_get_node(const void *fit, const char *conf_uname);
+int fit_conf_get_prop_node_count(const void *fit, int noffset,
+		const char *prop_name);
+int fit_conf_get_prop_node_index(const void *fit, int noffset,
+		const char *prop_name, int index);
 
 /**
  * fit_conf_get_prop_node() - Get node refered to by a configuration