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 |
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 >
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 > >
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 > > >
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 > > > >
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 > > > > >
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 > > > > > >
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 --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