diff mbox series

[U-Boot,v12,5/9] ARM: socfpga: Add FPGA drivers for Arria 10 FPGA bitstream loading

Message ID 20190319085019.6647-6-tien.fong.chee@intel.com
State Superseded
Delegated to: Marek Vasut
Headers show
Series Add support for loading FPGA bitstream | expand

Commit Message

Chee, Tien Fong March 19, 2019, 8:50 a.m. UTC
From: Tien Fong Chee <tien.fong.chee@intel.com>

Add FPGA driver to support program FPGA with FPGA bitstream loading from
filesystem. The driver are designed based on generic firmware loader
framework. The driver can handle FPGA program operation from loading FPGA
bitstream in flash to memory and then to program FPGA.

Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>

---

changes for v12
- No changes.

changes for v11
- No changes.

changes for v10
-Cleaned up the codes.
-Return -EPERM when programing core on non early IO release mode.
-Using live function to get rid of gd->
-Removed @0 for fs-loader node

changes for v9
- Support data offset
- Added default DDR load address
- Squashed the image.h
- Changed to phandle
- Ensure the DDR is fully up running by checking the gd->ram

changes for v8
- Added codes to discern bitstream type based on fpga node name.

changes for v7
- Restructure the FPGA driver to support both peripheral bitstream and core
  bitstream bundled into FIT image.
- Support loadable property for core bitstream. User can set loadable
  in DDR for better performance. This loading would be done in one large
  chunk instead of chunk by chunk loading with small memory buffer.
---
 arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
 .../include/mach/fpga_manager_arria10.h            |  39 +-
 drivers/fpga/socfpga_arria10.c                     | 497 ++++++++++++++++++++-
 include/image.h                                    |   4 +
 4 files changed, 542 insertions(+), 15 deletions(-)

Comments

Simon Goldschmidt April 27, 2019, 7:57 p.m. UTC | #1
On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> From: Tien Fong Chee <tien.fong.chee@intel.com>
> 
> Add FPGA driver to support program FPGA with FPGA bitstream loading from
> filesystem. The driver are designed based on generic firmware loader
> framework. The driver can handle FPGA program operation from loading FPGA
> bitstream in flash to memory and then to program FPGA.
> 
> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> 
> ---
> 
> changes for v12
> - No changes.
> 
> changes for v11
> - No changes.
> 
> changes for v10
> -Cleaned up the codes.
> -Return -EPERM when programing core on non early IO release mode. > -Using live function to get rid of gd->

You got rid of gd-> in v10? How come I see numerous references to it below?

Regards,
Simon

> -Removed @0 for fs-loader node
> 
> changes for v9
> - Support data offset
> - Added default DDR load address
> - Squashed the image.h
> - Changed to phandle
> - Ensure the DDR is fully up running by checking the gd->ram
> 
> changes for v8
> - Added codes to discern bitstream type based on fpga node name.
> 
> changes for v7
> - Restructure the FPGA driver to support both peripheral bitstream and core
>    bitstream bundled into FIT image.
> - Support loadable property for core bitstream. User can set loadable
>    in DDR for better performance. This loading would be done in one large
>    chunk instead of chunk by chunk loading with small memory buffer.
> ---
>   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
>   .../include/mach/fpga_manager_arria10.h            |  39 +-
>   drivers/fpga/socfpga_arria10.c                     | 497 ++++++++++++++++++++-
>   include/image.h                                    |   4 +
>   4 files changed, 542 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> index 998d811210..cc761967c7 100644
> --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> +++ b/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";
> diff --git a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> index 09d13f6fd3..c5f67714aa 100644
> --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> +++ b/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,39 @@ 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 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_ */
> diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
> index 9499d1a014..9df2c430d7 100644
> --- a/drivers/fpga/socfpga_arria10.c
> +++ b/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;
> @@ -448,13 +453,461 @@ 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;
> +
> +	memset(&rbfinfo, 0, sizeof(rbfinfo));
>   
>   	/* Disable all signals from hps peripheral controller to fpga */
>   	writel(0, &system_manager_base->fpgaintf_en_global);
> @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
>   	/* 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;
>   }
> diff --git a/include/image.h b/include/image.h
> index 765ffecee0..cc976f70ce 100644
> --- a/include/image.h
> +++ b/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
>
Chee, Tien Fong April 30, 2019, 12:09 p.m. UTC | #2
On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> 
> On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > 
> > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > 
> > Add FPGA driver to support program FPGA with FPGA bitstream loading
> > from
> > filesystem. The driver are designed based on generic firmware
> > loader
> > framework. The driver can handle FPGA program operation from
> > loading FPGA
> > bitstream in flash to memory and then to program FPGA.
> > 
> > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > 
> > ---
> > 
> > changes for v12
> > - No changes.
> > 
> > changes for v11
> > - No changes.
> > 
> > changes for v10
> > -Cleaned up the codes.
> > -Return -EPERM when programing core on non early IO release mode. >
> > -Using live function to get rid of gd->
> You got rid of gd-> in v10? How come I see numerous references to it
> below?

get rid of using gd->fdt_blob for finding the node_offset.
Details in https://patchwork.ozlabs.org/patch/1044415/ 

-/*
- * 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(void)
+{
+	int node_offset;
+
+	fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",

nit: using of live functions would be better to get rid of gd->.

+				COMPAT_ALTERA_SOCFPGA_FPGA0,
+				&node_offset, 1);

Thanks.
> 
> > 
> > -Removed @0 for fs-loader node
> > 
> > changes for v9
> > - Support data offset
> > - Added default DDR load address
> > - Squashed the image.h
> > - Changed to phandle
> > - Ensure the DDR is fully up running by checking the gd->ram
> > 
> > changes for v8
> > - Added codes to discern bitstream type based on fpga node name.
> > 
> > changes for v7
> > - Restructure the FPGA driver to support both peripheral bitstream
> > and core
> >    bitstream bundled into FIT image.
> > - Support loadable property for core bitstream. User can set
> > loadable
> >    in DDR for better performance. This loading would be done in one
> > large
> >    chunk instead of chunk by chunk loading with small memory
> > buffer.
> > ---
> >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
> >   .../include/mach/fpga_manager_arria10.h            |  39 +-
> >   drivers/fpga/socfpga_arria10.c                     | 497
> > ++++++++++++++++++++-
> >   include/image.h                                    |   4 +
> >   4 files changed, 542 insertions(+), 15 deletions(-)
> > 
> > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > index 998d811210..cc761967c7 100644
> > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > +++ b/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";
> > diff --git a/arch/arm/mach-
> > socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-
> > socfpga/include/mach/fpga_manager_arria10.h
> > index 09d13f6fd3..c5f67714aa 100644
> > --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> > +++ b/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,39 @@ 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 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_ */
> > diff --git a/drivers/fpga/socfpga_arria10.c
> > b/drivers/fpga/socfpga_arria10.c
> > index 9499d1a014..9df2c430d7 100644
> > --- a/drivers/fpga/socfpga_arria10.c
> > +++ b/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;
> > @@ -448,13 +453,461 @@ 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_F
> > PGA_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_mod
> > e() &&
> > +					!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_load
> > fs,
> > +							&buffer,
> > +							&buffer_si
> > zebytes_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;
> > +
> > +	memset(&rbfinfo, 0, sizeof(rbfinfo));
> >   
> >   	/* Disable all signals from hps peripheral controller to
> > fpga */
> >   	writel(0, &system_manager_base->fpgaintf_en_global);
> > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const
> > void *rbf_data, size_t rbf_size)
> >   	/* 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;
> >   }
> > diff --git a/include/image.h b/include/image.h
> > index 765ffecee0..cc976f70ce 100644
> > --- a/include/image.h
> > +++ b/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
> >
Simon Goldschmidt April 30, 2019, 12:24 p.m. UTC | #3
On Tue, Apr 30, 2019 at 2:09 PM Chee, Tien Fong
<tien.fong.chee@intel.com> wrote:
>
> On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> >
> > On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > >
> > > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > >
> > > Add FPGA driver to support program FPGA with FPGA bitstream loading
> > > from
> > > filesystem. The driver are designed based on generic firmware
> > > loader
> > > framework. The driver can handle FPGA program operation from
> > > loading FPGA
> > > bitstream in flash to memory and then to program FPGA.
> > >
> > > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > >
> > > ---
> > >
> > > changes for v12
> > > - No changes.
> > >
> > > changes for v11
> > > - No changes.
> > >
> > > changes for v10
> > > -Cleaned up the codes.
> > > -Return -EPERM when programing core on non early IO release mode. >
> > > -Using live function to get rid of gd->
> > You got rid of gd-> in v10? How come I see numerous references to it
> > below?
>
> get rid of using gd->fdt_blob for finding the node_offset.
> Details in https://patchwork.ozlabs.org/patch/1044415/

Ah, ok. But still, here you're introducing yet more references to gd->fdt_blob.
That wouldn't work with a live tree, either, or would it?

Regards,
Simon

>
> -/*
> - * 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(void)
> +{
> +       int node_offset;
> +
> +       fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",
>
> nit: using of live functions would be better to get rid of gd->.
>
> +                               COMPAT_ALTERA_SOCFPGA_FPGA0,
> +                               &node_offset, 1);
>
> Thanks.
> >
> > >
> > > -Removed @0 for fs-loader node
> > >
> > > changes for v9
> > > - Support data offset
> > > - Added default DDR load address
> > > - Squashed the image.h
> > > - Changed to phandle
> > > - Ensure the DDR is fully up running by checking the gd->ram
> > >
> > > changes for v8
> > > - Added codes to discern bitstream type based on fpga node name.
> > >
> > > changes for v7
> > > - Restructure the FPGA driver to support both peripheral bitstream
> > > and core
> > >    bitstream bundled into FIT image.
> > > - Support loadable property for core bitstream. User can set
> > > loadable
> > >    in DDR for better performance. This loading would be done in one
> > > large
> > >    chunk instead of chunk by chunk loading with small memory
> > > buffer.
> > > ---
> > >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
> > >   .../include/mach/fpga_manager_arria10.h            |  39 +-
> > >   drivers/fpga/socfpga_arria10.c                     | 497
> > > ++++++++++++++++++++-
> > >   include/image.h                                    |   4 +
> > >   4 files changed, 542 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > index 998d811210..cc761967c7 100644
> > > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > +++ b/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";
> > > diff --git a/arch/arm/mach-
> > > socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-
> > > socfpga/include/mach/fpga_manager_arria10.h
> > > index 09d13f6fd3..c5f67714aa 100644
> > > --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> > > +++ b/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,39 @@ 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 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_ */
> > > diff --git a/drivers/fpga/socfpga_arria10.c
> > > b/drivers/fpga/socfpga_arria10.c
> > > index 9499d1a014..9df2c430d7 100644
> > > --- a/drivers/fpga/socfpga_arria10.c
> > > +++ b/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;
> > > @@ -448,13 +453,461 @@ 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_F
> > > PGA_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_mod
> > > e() &&
> > > +                                   !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_load
> > > fs,
> > > +                                                   &buffer,
> > > +                                                   &buffer_si
> > > zebytes_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;
> > > +
> > > +   memset(&rbfinfo, 0, sizeof(rbfinfo));
> > >
> > >     /* Disable all signals from hps peripheral controller to
> > > fpga */
> > >     writel(0, &system_manager_base->fpgaintf_en_global);
> > > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const
> > > void *rbf_data, size_t rbf_size)
> > >     /* 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;
> > >   }
> > > diff --git a/include/image.h b/include/image.h
> > > index 765ffecee0..cc976f70ce 100644
> > > --- a/include/image.h
> > > +++ b/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
> > >
Chee, Tien Fong May 2, 2019, 7:49 a.m. UTC | #4
On Tue, 2019-04-30 at 14:24 +0200, Simon Goldschmidt wrote:
> On Tue, Apr 30, 2019 at 2:09 PM Chee, Tien Fong
> <tien.fong.chee@intel.com> wrote:
> > 
> > 
> > On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> > > 
> > > 
> > > On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > > > 
> > > > 
> > > > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > 
> > > > Add FPGA driver to support program FPGA with FPGA bitstream
> > > > loading
> > > > from
> > > > filesystem. The driver are designed based on generic firmware
> > > > loader
> > > > framework. The driver can handle FPGA program operation from
> > > > loading FPGA
> > > > bitstream in flash to memory and then to program FPGA.
> > > > 
> > > > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > 
> > > > ---
> > > > 
> > > > changes for v12
> > > > - No changes.
> > > > 
> > > > changes for v11
> > > > - No changes.
> > > > 
> > > > changes for v10
> > > > -Cleaned up the codes.
> > > > -Return -EPERM when programing core on non early IO release
> > > > mode. >
> > > > -Using live function to get rid of gd->
> > > You got rid of gd-> in v10? How come I see numerous references to
> > > it
> > > below?
> > get rid of using gd->fdt_blob for finding the node_offset.
> > Details in https://patchwork.ozlabs.org/patch/1044415/
> Ah, ok. But still, here you're introducing yet more references to gd-
> >fdt_blob.
> That wouldn't work with a live tree, either, or would it?

Yeah, few direct call to config_pin function are still using gd-
fdt_blob as argument. But, i'm not sure i should fix this function in
this series patch set, or separately patch after this series patch set?

What do you think?

Thanks,
TF
> 
> > 
> > 
> > -/*
> > - * 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(void)
> > +{
> > +       int node_offset;
> > +
> > +       fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",
> > 
> > nit: using of live functions would be better to get rid of gd->.
> > 
> > +                               COMPAT_ALTERA_SOCFPGA_FPGA0,
> > +                               &node_offset, 1);
> > 
> > Thanks.
> > > 
> > > 
> > > > 
> > > > 
> > > > -Removed @0 for fs-loader node
> > > > 
> > > > changes for v9
> > > > - Support data offset
> > > > - Added default DDR load address
> > > > - Squashed the image.h
> > > > - Changed to phandle
> > > > - Ensure the DDR is fully up running by checking the gd->ram
> > > > 
> > > > changes for v8
> > > > - Added codes to discern bitstream type based on fpga node
> > > > name.
> > > > 
> > > > changes for v7
> > > > - Restructure the FPGA driver to support both peripheral
> > > > bitstream
> > > > and core
> > > >    bitstream bundled into FIT image.
> > > > - Support loadable property for core bitstream. User can set
> > > > loadable
> > > >    in DDR for better performance. This loading would be done in
> > > > one
> > > > large
> > > >    chunk instead of chunk by chunk loading with small memory
> > > > buffer.
> > > > ---
> > > >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
> > > >   .../include/mach/fpga_manager_arria10.h            |  39 +-
> > > >   drivers/fpga/socfpga_arria10.c                     | 497
> > > > ++++++++++++++++++++-
> > > >   include/image.h                                    |   4 +
> > > >   4 files changed, 542 insertions(+), 15 deletions(-)
> > > > 
> > > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > index 998d811210..cc761967c7 100644
> > > > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > +++ b/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";
> > > > diff --git a/arch/arm/mach-
> > > > socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-
> > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > index 09d13f6fd3..c5f67714aa 100644
> > > > --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> > > > +++ b/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,39 @@ 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 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_ */
> > > > diff --git a/drivers/fpga/socfpga_arria10.c
> > > > b/drivers/fpga/socfpga_arria10.c
> > > > index 9499d1a014..9df2c430d7 100644
> > > > --- a/drivers/fpga/socfpga_arria10.c
> > > > +++ b/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;
> > > > @@ -448,13 +453,461 @@ 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_F
> > > > PGA_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_mod
> > > > e() &&
> > > > +                                   !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_load
> > > > fs,
> > > > +                                                   &buffer,
> > > > +                                                   &buffer_si
> > > > zebytes_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;
> > > > +
> > > > +   memset(&rbfinfo, 0, sizeof(rbfinfo));
> > > > 
> > > >     /* Disable all signals from hps peripheral controller to
> > > > fpga */
> > > >     writel(0, &system_manager_base->fpgaintf_en_global);
> > > > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const
> > > > void *rbf_data, size_t rbf_size)
> > > >     /* 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;
> > > >   }
> > > > diff --git a/include/image.h b/include/image.h
> > > > index 765ffecee0..cc976f70ce 100644
> > > > --- a/include/image.h
> > > > +++ b/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
> > > >
Simon Goldschmidt May 3, 2019, 11:26 a.m. UTC | #5
On Thu, May 2, 2019 at 9:49 AM Chee, Tien Fong <tien.fong.chee@intel.com> wrote:
>
> On Tue, 2019-04-30 at 14:24 +0200, Simon Goldschmidt wrote:
> > On Tue, Apr 30, 2019 at 2:09 PM Chee, Tien Fong
> > <tien.fong.chee@intel.com> wrote:
> > >
> > >
> > > On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> > > >
> > > >
> > > > On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > > > >
> > > > >
> > > > > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > >
> > > > > Add FPGA driver to support program FPGA with FPGA bitstream
> > > > > loading
> > > > > from
> > > > > filesystem. The driver are designed based on generic firmware
> > > > > loader
> > > > > framework. The driver can handle FPGA program operation from
> > > > > loading FPGA
> > > > > bitstream in flash to memory and then to program FPGA.
> > > > >
> > > > > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > >
> > > > > ---
> > > > >
> > > > > changes for v12
> > > > > - No changes.
> > > > >
> > > > > changes for v11
> > > > > - No changes.
> > > > >
> > > > > changes for v10
> > > > > -Cleaned up the codes.
> > > > > -Return -EPERM when programing core on non early IO release
> > > > > mode. >
> > > > > -Using live function to get rid of gd->
> > > > You got rid of gd-> in v10? How come I see numerous references to
> > > > it
> > > > below?
> > > get rid of using gd->fdt_blob for finding the node_offset.
> > > Details in https://patchwork.ozlabs.org/patch/1044415/
> > Ah, ok. But still, here you're introducing yet more references to gd-
> > >fdt_blob.
> > That wouldn't work with a live tree, either, or would it?
>
> Yeah, few direct call to config_pin function are still using gd-
> fdt_blob as argument. But, i'm not sure i should fix this function in
> this series patch set, or separately patch after this series patch set?
>
> What do you think?

While I do have a strong opinion that this should be cleaned up,
it would be kind of off-topic in this patch. I was just confused by the
version log.

Regards,
Simon

>
> Thanks,
> TF
> >
> > >
> > >
> > > -/*
> > > - * 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(void)
> > > +{
> > > +       int node_offset;
> > > +
> > > +       fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",
> > >
> > > nit: using of live functions would be better to get rid of gd->.
> > >
> > > +                               COMPAT_ALTERA_SOCFPGA_FPGA0,
> > > +                               &node_offset, 1);
> > >
> > > Thanks.
> > > >
> > > >
> > > > >
> > > > >
> > > > > -Removed @0 for fs-loader node
> > > > >
> > > > > changes for v9
> > > > > - Support data offset
> > > > > - Added default DDR load address
> > > > > - Squashed the image.h
> > > > > - Changed to phandle
> > > > > - Ensure the DDR is fully up running by checking the gd->ram
> > > > >
> > > > > changes for v8
> > > > > - Added codes to discern bitstream type based on fpga node
> > > > > name.
> > > > >
> > > > > changes for v7
> > > > > - Restructure the FPGA driver to support both peripheral
> > > > > bitstream
> > > > > and core
> > > > >    bitstream bundled into FIT image.
> > > > > - Support loadable property for core bitstream. User can set
> > > > > loadable
> > > > >    in DDR for better performance. This loading would be done in
> > > > > one
> > > > > large
> > > > >    chunk instead of chunk by chunk loading with small memory
> > > > > buffer.
> > > > > ---
> > > > >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17 +
> > > > >   .../include/mach/fpga_manager_arria10.h            |  39 +-
> > > > >   drivers/fpga/socfpga_arria10.c                     | 497
> > > > > ++++++++++++++++++++-
> > > > >   include/image.h                                    |   4 +
> > > > >   4 files changed, 542 insertions(+), 15 deletions(-)
> > > > >
> > > > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > index 998d811210..cc761967c7 100644
> > > > > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > +++ b/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";
> > > > > diff --git a/arch/arm/mach-
> > > > > socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-
> > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > index 09d13f6fd3..c5f67714aa 100644
> > > > > --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> > > > > +++ b/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,39 @@ 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 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_ */
> > > > > diff --git a/drivers/fpga/socfpga_arria10.c
> > > > > b/drivers/fpga/socfpga_arria10.c
> > > > > index 9499d1a014..9df2c430d7 100644
> > > > > --- a/drivers/fpga/socfpga_arria10.c
> > > > > +++ b/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;
> > > > > @@ -448,13 +453,461 @@ 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_F
> > > > > PGA_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_mod
> > > > > e() &&
> > > > > +                                   !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_load
> > > > > fs,
> > > > > +                                                   &buffer,
> > > > > +                                                   &buffer_si
> > > > > zebytes_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;
> > > > > +
> > > > > +   memset(&rbfinfo, 0, sizeof(rbfinfo));
> > > > >
> > > > >     /* Disable all signals from hps peripheral controller to
> > > > > fpga */
> > > > >     writel(0, &system_manager_base->fpgaintf_en_global);
> > > > > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const
> > > > > void *rbf_data, size_t rbf_size)
> > > > >     /* 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;
> > > > >   }
> > > > > diff --git a/include/image.h b/include/image.h
> > > > > index 765ffecee0..cc976f70ce 100644
> > > > > --- a/include/image.h
> > > > > +++ b/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
> > > > >
Chee, Tien Fong May 6, 2019, 3:36 a.m. UTC | #6
On Fri, 2019-05-03 at 13:26 +0200, Simon Goldschmidt wrote:
> On Thu, May 2, 2019 at 9:49 AM Chee, Tien Fong <tien.fong.chee@intel.
> com> wrote:
> > 
> > 
> > On Tue, 2019-04-30 at 14:24 +0200, Simon Goldschmidt wrote:
> > > 
> > > On Tue, Apr 30, 2019 at 2:09 PM Chee, Tien Fong
> > > <tien.fong.chee@intel.com> wrote:
> > > > 
> > > > 
> > > > 
> > > > On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> > > > > 
> > > > > 
> > > > > 
> > > > > On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > > > 
> > > > > > Add FPGA driver to support program FPGA with FPGA bitstream
> > > > > > loading
> > > > > > from
> > > > > > filesystem. The driver are designed based on generic
> > > > > > firmware
> > > > > > loader
> > > > > > framework. The driver can handle FPGA program operation
> > > > > > from
> > > > > > loading FPGA
> > > > > > bitstream in flash to memory and then to program FPGA.
> > > > > > 
> > > > > > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > > > 
> > > > > > ---
> > > > > > 
> > > > > > changes for v12
> > > > > > - No changes.
> > > > > > 
> > > > > > changes for v11
> > > > > > - No changes.
> > > > > > 
> > > > > > changes for v10
> > > > > > -Cleaned up the codes.
> > > > > > -Return -EPERM when programing core on non early IO release
> > > > > > mode. >
> > > > > > -Using live function to get rid of gd->
> > > > > You got rid of gd-> in v10? How come I see numerous
> > > > > references to
> > > > > it
> > > > > below?
> > > > get rid of using gd->fdt_blob for finding the node_offset.
> > > > Details in https://patchwork.ozlabs.org/patch/1044415/
> > > Ah, ok. But still, here you're introducing yet more references to
> > > gd-
> > > > 
> > > > fdt_blob.
> > > That wouldn't work with a live tree, either, or would it?
> > Yeah, few direct call to config_pin function are still using gd-
> > fdt_blob as argument. But, i'm not sure i should fix this function
> > in
> > this series patch set, or separately patch after this series patch
> > set?
> > 
> > What do you think?
> While I do have a strong opinion that this should be cleaned up,
> it would be kind of off-topic in this patch. I was just confused by
> the
> version log.
> 
> Regards,
> Simon
Okay, how about we keep these changes. I will send out the fix
separately after this patch set.

Thanks.
> 
> > 
> > 
> > Thanks,
> > TF
> > > 
> > > 
> > > > 
> > > > 
> > > > 
> > > > -/*
> > > > - * 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(void)
> > > > +{
> > > > +       int node_offset;
> > > > +
> > > > +       fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",
> > > > 
> > > > nit: using of live functions would be better to get rid of gd-
> > > > >.
> > > > 
> > > > +                               COMPAT_ALTERA_SOCFPGA_FPGA0,
> > > > +                               &node_offset, 1);
> > > > 
> > > > Thanks.
> > > > > 
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > -Removed @0 for fs-loader node
> > > > > > 
> > > > > > changes for v9
> > > > > > - Support data offset
> > > > > > - Added default DDR load address
> > > > > > - Squashed the image.h
> > > > > > - Changed to phandle
> > > > > > - Ensure the DDR is fully up running by checking the gd-
> > > > > > >ram
> > > > > > 
> > > > > > changes for v8
> > > > > > - Added codes to discern bitstream type based on fpga node
> > > > > > name.
> > > > > > 
> > > > > > changes for v7
> > > > > > - Restructure the FPGA driver to support both peripheral
> > > > > > bitstream
> > > > > > and core
> > > > > >    bitstream bundled into FIT image.
> > > > > > - Support loadable property for core bitstream. User can
> > > > > > set
> > > > > > loadable
> > > > > >    in DDR for better performance. This loading would be
> > > > > > done in
> > > > > > one
> > > > > > large
> > > > > >    chunk instead of chunk by chunk loading with small
> > > > > > memory
> > > > > > buffer.
> > > > > > ---
> > > > > >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17
> > > > > > +
> > > > > >   .../include/mach/fpga_manager_arria10.h            |  39
> > > > > > +-
> > > > > >   drivers/fpga/socfpga_arria10.c                     | 497
> > > > > > ++++++++++++++++++++-
> > > > > >   include/image.h                                    |   4
> > > > > > +
> > > > > >   4 files changed, 542 insertions(+), 15 deletions(-)
> > > > > > 
> > > > > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > index 998d811210..cc761967c7 100644
> > > > > > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > +++ b/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";
> > > > > > diff --git a/arch/arm/mach-
> > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > b/arch/arm/mach-
> > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > index 09d13f6fd3..c5f67714aa 100644
> > > > > > --- a/arch/arm/mach-
> > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > +++ b/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.co
> > > > > > m>
> > > > > >    * 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,39 @@ 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 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_ */
> > > > > > diff --git a/drivers/fpga/socfpga_arria10.c
> > > > > > b/drivers/fpga/socfpga_arria10.c
> > > > > > index 9499d1a014..9df2c430d7 100644
> > > > > > --- a/drivers/fpga/socfpga_arria10.c
> > > > > > +++ b/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.co
> > > > > > m>
> > > > > >    */
> > > > > > -
> > > > > >   #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;
> > > > > > @@ -448,13 +453,461 @@ 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_UNENCRYPTE
> > > > > > D)
> > > > > > {
> > > > > > +                   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,
> > > > > > +                                                        co
> > > > > > nfs
> > > > > > _noffset,
> > > > > > +                                                        FI
> > > > > > T_F
> > > > > > PGA_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_
> > > > > > mod
> > > > > > e() &&
> > > > > > +                                   !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_l
> > > > > > oad
> > > > > > fs,
> > > > > > +                                                   &buffer
> > > > > > ,
> > > > > > +                                                   &buffer
> > > > > > _si
> > > > > > zebytes_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;
> > > > > > +
> > > > > > +   memset(&rbfinfo, 0, sizeof(rbfinfo));
> > > > > > 
> > > > > >     /* Disable all signals from hps peripheral controller
> > > > > > to
> > > > > > fpga */
> > > > > >     writel(0, &system_manager_base->fpgaintf_en_global);
> > > > > > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc,
> > > > > > const
> > > > > > void *rbf_data, size_t rbf_size)
> > > > > >     /* 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;
> > > > > >   }
> > > > > > diff --git a/include/image.h b/include/image.h
> > > > > > index 765ffecee0..cc976f70ce 100644
> > > > > > --- a/include/image.h
> > > > > > +++ b/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
> > > > > >
Simon Goldschmidt May 6, 2019, 7:14 a.m. UTC | #7
On Mon, May 6, 2019 at 5:36 AM Chee, Tien Fong <tien.fong.chee@intel.com> wrote:
>
> On Fri, 2019-05-03 at 13:26 +0200, Simon Goldschmidt wrote:
> > On Thu, May 2, 2019 at 9:49 AM Chee, Tien Fong <tien.fong.chee@intel.
> > com> wrote:
> > >
> > >
> > > On Tue, 2019-04-30 at 14:24 +0200, Simon Goldschmidt wrote:
> > > >
> > > > On Tue, Apr 30, 2019 at 2:09 PM Chee, Tien Fong
> > > > <tien.fong.chee@intel.com> wrote:
> > > > >
> > > > >
> > > > >
> > > > > On Sat, 2019-04-27 at 21:57 +0200, Simon Goldschmidt wrote:
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 19.03.19 09:50, tien.fong.chee@intel.com wrote:
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > From: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > > > >
> > > > > > > Add FPGA driver to support program FPGA with FPGA bitstream
> > > > > > > loading
> > > > > > > from
> > > > > > > filesystem. The driver are designed based on generic
> > > > > > > firmware
> > > > > > > loader
> > > > > > > framework. The driver can handle FPGA program operation
> > > > > > > from
> > > > > > > loading FPGA
> > > > > > > bitstream in flash to memory and then to program FPGA.
> > > > > > >
> > > > > > > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> > > > > > >
> > > > > > > ---
> > > > > > >
> > > > > > > changes for v12
> > > > > > > - No changes.
> > > > > > >
> > > > > > > changes for v11
> > > > > > > - No changes.
> > > > > > >
> > > > > > > changes for v10
> > > > > > > -Cleaned up the codes.
> > > > > > > -Return -EPERM when programing core on non early IO release
> > > > > > > mode. >
> > > > > > > -Using live function to get rid of gd->
> > > > > > You got rid of gd-> in v10? How come I see numerous
> > > > > > references to
> > > > > > it
> > > > > > below?
> > > > > get rid of using gd->fdt_blob for finding the node_offset.
> > > > > Details in https://patchwork.ozlabs.org/patch/1044415/
> > > > Ah, ok. But still, here you're introducing yet more references to
> > > > gd-
> > > > >
> > > > > fdt_blob.
> > > > That wouldn't work with a live tree, either, or would it?
> > > Yeah, few direct call to config_pin function are still using gd-
> > > fdt_blob as argument. But, i'm not sure i should fix this function
> > > in
> > > this series patch set, or separately patch after this series patch
> > > set?
> > >
> > > What do you think?
> > While I do have a strong opinion that this should be cleaned up,
> > it would be kind of off-topic in this patch. I was just confused by
> > the
> > version log.
> >
> > Regards,
> > Simon
> Okay, how about we keep these changes. I will send out the fix
> separately after this patch set.

That would be best, I think, yes.

Regards,
Simon

>
> Thanks.
> >
> > >
> > >
> > > Thanks,
> > > TF
> > > >
> > > >
> > > > >
> > > > >
> > > > >
> > > > > -/*
> > > > > - * 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(void)
> > > > > +{
> > > > > +       int node_offset;
> > > > > +
> > > > > +       fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr",
> > > > >
> > > > > nit: using of live functions would be better to get rid of gd-
> > > > > >.
> > > > >
> > > > > +                               COMPAT_ALTERA_SOCFPGA_FPGA0,
> > > > > +                               &node_offset, 1);
> > > > >
> > > > > Thanks.
> > > > > >
> > > > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -Removed @0 for fs-loader node
> > > > > > >
> > > > > > > changes for v9
> > > > > > > - Support data offset
> > > > > > > - Added default DDR load address
> > > > > > > - Squashed the image.h
> > > > > > > - Changed to phandle
> > > > > > > - Ensure the DDR is fully up running by checking the gd-
> > > > > > > >ram
> > > > > > >
> > > > > > > changes for v8
> > > > > > > - Added codes to discern bitstream type based on fpga node
> > > > > > > name.
> > > > > > >
> > > > > > > changes for v7
> > > > > > > - Restructure the FPGA driver to support both peripheral
> > > > > > > bitstream
> > > > > > > and core
> > > > > > >    bitstream bundled into FIT image.
> > > > > > > - Support loadable property for core bitstream. User can
> > > > > > > set
> > > > > > > loadable
> > > > > > >    in DDR for better performance. This loading would be
> > > > > > > done in
> > > > > > > one
> > > > > > > large
> > > > > > >    chunk instead of chunk by chunk loading with small
> > > > > > > memory
> > > > > > > buffer.
> > > > > > > ---
> > > > > > >   arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  17
> > > > > > > +
> > > > > > >   .../include/mach/fpga_manager_arria10.h            |  39
> > > > > > > +-
> > > > > > >   drivers/fpga/socfpga_arria10.c                     | 497
> > > > > > > ++++++++++++++++++++-
> > > > > > >   include/image.h                                    |   4
> > > > > > > +
> > > > > > >   4 files changed, 542 insertions(+), 15 deletions(-)
> > > > > > >
> > > > > > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > > index 998d811210..cc761967c7 100644
> > > > > > > --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
> > > > > > > +++ b/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";
> > > > > > > diff --git a/arch/arm/mach-
> > > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > > b/arch/arm/mach-
> > > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > > index 09d13f6fd3..c5f67714aa 100644
> > > > > > > --- a/arch/arm/mach-
> > > > > > > socfpga/include/mach/fpga_manager_arria10.h
> > > > > > > +++ b/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.co
> > > > > > > m>
> > > > > > >    * 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,39 @@ 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 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_ */
> > > > > > > diff --git a/drivers/fpga/socfpga_arria10.c
> > > > > > > b/drivers/fpga/socfpga_arria10.c
> > > > > > > index 9499d1a014..9df2c430d7 100644
> > > > > > > --- a/drivers/fpga/socfpga_arria10.c
> > > > > > > +++ b/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.co
> > > > > > > m>
> > > > > > >    */
> > > > > > > -
> > > > > > >   #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;
> > > > > > > @@ -448,13 +453,461 @@ 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_UNENCRYPTE
> > > > > > > D)
> > > > > > > {
> > > > > > > +                   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,
> > > > > > > +                                                        co
> > > > > > > nfs
> > > > > > > _noffset,
> > > > > > > +                                                        FI
> > > > > > > T_F
> > > > > > > PGA_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_
> > > > > > > mod
> > > > > > > e() &&
> > > > > > > +                                   !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_l
> > > > > > > oad
> > > > > > > fs,
> > > > > > > +                                                   &buffer
> > > > > > > ,
> > > > > > > +                                                   &buffer
> > > > > > > _si
> > > > > > > zebytes_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;
> > > > > > > +
> > > > > > > +   memset(&rbfinfo, 0, sizeof(rbfinfo));
> > > > > > >
> > > > > > >     /* Disable all signals from hps peripheral controller
> > > > > > > to
> > > > > > > fpga */
> > > > > > >     writel(0, &system_manager_base->fpgaintf_en_global);
> > > > > > > @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc,
> > > > > > > const
> > > > > > > void *rbf_data, size_t rbf_size)
> > > > > > >     /* 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;
> > > > > > >   }
> > > > > > > diff --git a/include/image.h b/include/image.h
> > > > > > > index 765ffecee0..cc976f70ce 100644
> > > > > > > --- a/include/image.h
> > > > > > > +++ b/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
> > > > > > >
diff mbox series

Patch

diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
index 998d811210..cc761967c7 100644
--- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
+++ b/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";
diff --git a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
index 09d13f6fd3..c5f67714aa 100644
--- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
+++ b/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,39 @@  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 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_ */
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 9499d1a014..9df2c430d7 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/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;
@@ -448,13 +453,461 @@  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;
+
+	memset(&rbfinfo, 0, sizeof(rbfinfo));
 
 	/* Disable all signals from hps peripheral controller to fpga */
 	writel(0, &system_manager_base->fpgaintf_en_global);
@@ -462,13 +915,31 @@  int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
 	/* 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;
 }
diff --git a/include/image.h b/include/image.h
index 765ffecee0..cc976f70ce 100644
--- a/include/image.h
+++ b/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