From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chee, Tien Fong Date: Thu, 14 Feb 2019 06:44:59 +0000 Subject: [U-Boot] [PATCH v8 4/8] ARM: socfpga: Add FPGA drivers for Arria 10 FPGA bitstream loading In-Reply-To: <8708acb5-9a10-1916-6a10-1f3f7c295a5d@denx.de> References: <1550067518-2542-1-git-send-email-tien.fong.chee@intel.com> <1550067518-2542-5-git-send-email-tien.fong.chee@intel.com> <8708acb5-9a10-1916-6a10-1f3f7c295a5d@denx.de> Message-ID: <1550126695.10728.36.camel@intel.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit To: u-boot@lists.denx.de On Wed, 2019-02-13 at 17:20 +0100, Marek Vasut wrote: > On 2/13/19 3:18 PM, tien.fong.chee at intel.com wrote: > > > > From: Tien Fong Chee > > > > 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 > > > > --- > > > > 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                     | 467 > > ++++++++++++++++++++- > >  3 files changed, 500 insertions(+), 23 deletions(-) > > > > diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts > > b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts > > index 998d811..14f1967 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; > Should be a phandle. Can we change this label to phandle stage by stage, may be after fpga driver? This requires time working on firmware loader. > > > > > + }; > > + > > + fs_loader0: fs-loader at 0 { > > + 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 09d13f6..5ef15bb 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 > > + * Copyright (C) 2017-2019 Intel Corporation > >   * All rights reserved. > >   */ > >   > > +#include > > +#include > > +#include > > + > >  #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); > > - > > +int is_fpgamgr_early_user_mode(void); > > +char *get_fpga_filename(const void *fdt, int *len); > > +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, 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 114dd91..630d5a3 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 > > + * Copyright (C) 2017-2019 Intel Corporation > >   */ > > - > >  #include > >  #include > >  #include > > @@ -10,8 +9,11 @@ > >  #include > >  #include > >  #include > > +#include > >  #include > > +#include > >  #include > > +#include > >  #include > >  #include > >   > > @@ -64,7 +66,7 @@ static int wait_for_user_mode(void) > >   1, FPGA_TIMEOUT_MSEC, false); > >  } > >   > > -static int is_fpgamgr_early_user_mode(void) > > +int is_fpgamgr_early_user_mode(void) > >  { > >   return (readl(&fpga_manager_base->imgcfg_stat) & > >   ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK > > ) != 0; > > @@ -92,9 +94,10 @@ int fpgamgr_wait_early_user_mode(void) > >   sizeof(sync_data)); > >   udelay(FPGA_TIMEOUT_MSEC); > >   i++; > > + WATCHDOG_RESET(); > udelay() already triggers watchdog, why is this needed here ? Then i can remove it. > > > > >   } > >   > > - debug("Additional %i sync word needed\n", i); > > + debug("FPGA: Additional %i sync word needed\n", i); > >   > >   /* restoring original CDRATIO */ > >   fpgamgr_set_cd_ratio(cd_ratio); > > @@ -172,9 +175,10 @@ static int > > fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data, > >   compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1; > >   compress = !compress; > >   > > - debug("header word %d = %08x\n", 69, rbf_data[69]); > > - debug("header word %d = %08x\n", 229, rbf_data[229]); > > - debug("read from rbf header: encrypt=%d compress=%d\n", > > encrypt, compress); > > + debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]); > > + debug("FPGA: Header word %d = %08x.\n", 229, > > rbf_data[229]); > > + debug("FPGA: Read from rbf header: encrypt=%d > > compress=%d.\n", encrypt, > > +      compress); > >   > >   /* > >    * from the register map description of cdratio in > > imgcfg_ctrl_02: > > @@ -359,6 +363,7 @@ static int fpgamgr_program_poll_cd(void) > >   printf("nstatus == 0nwhile waiting for > > condone\"); > >   return -EPERM; > >   } > > + WATCHDOG_RESET(); > Why is this needed ? This is polling of FPGA configuring done status. The polling could be long enough to reset the watchdog timely, hence we need this in the polling. > > > > >   } > >   > >   if (i == FPGA_TIMEOUT_CNT) > > @@ -432,7 +437,6 @@ int fpgamgr_program_finish(void) > >   printf("FPGA: Poll CD failed with error code > > %d\n", status); > >   return -EPERM; > >   } > > - WATCHDOG_RESET(); > >   > >   /* Ensure the FPGA entering user mode */ > >   status = fpgamgr_program_poll_usermode(); > > @@ -447,27 +451,448 @@ 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. > > - */ > > +char *get_fpga_filename(const void *fdt, int *len) > > +{ > > + char *fpga_filename = NULL; > > + int node_offset; > > + > > + fdtdec_find_aliases_for_id(gd->fdt_blob, "fpga_mgr", > > + COMPAT_ALTERA_SOCFPGA_FPGA0, > > + &node_offset, 1); > > + > > + ofnode fpgamgr_node = offset_to_ofnode(node_offset); > > + > > + if (ofnode_valid(fpgamgr_node)) > > + fpga_filename = (char > > *)ofnode_read_string(fpgamgr_node, > > + "altr,bitstream"); > > + > > + > Why is the cast needed ? The return string would be eventually set to the char *filename in common struct fpga_fsinfo. So, the cast here is to avoid the warning from compiler. > Drop the two newlines. Okay. > > > > > + 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; > > + int confs_noffset, images_noffset; > > + int rbf_offset; > > + int 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; > > + } else { > > + 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; > > + } > > + > > + ret = fit_image_get_data_position(buffer_p, > > images_noffset, > > +  &rbf_offset); > > + if (ret < 0) { > > + debug("FPGA: No data position was found > > (err=%d).\n", ret); > > + 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; > > + } > > + > > + ret = fit_image_get_load(buffer_p, images_noffset, (ulong > > *)loadable); > > + if (ret < 0) { > > + debug("FPGA: No loadable was found (err=%d).\n", > > ret); > > + debug("FPGA: Using default buffer and size.\n"); > > + } else { > > + buffer_p = (u32 *)*loadable; > > + buffer_size = rbf_size; > > + debug("FPGA: Found loadable address = 0x%x.\n", > > *loadable); > > + } > > + > > + 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; > > + } > Shouldn't all this parsing and calculation be done by the firmware > loader code ? The calculation here is to determine the available memory size can be used, it could be size from OCRAM buffer, or DDR. > > > > > + 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; > > + int status = 0; > > + int ret = 0; > > + u32 buffer = (u32)buf; > This will fail on arm64 , look at uintptr_t . This driver is only used by A10 which is arm32. You want me to use (u32)(uintptr_t)buf?  > > > > > + size_t buffer_sizebytes = bsize; > > + size_t buffer_sizebytes_ori = bsize; > > + size_t total_sizeof_image = 0; > > + struct udevice *dev; > > + > > + ret = uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, > > &dev); > Shouldn't the firmware loaded instance be obtained via the DT phandle > ? It just to get the device activated. The firmware loaded itself would go to choosen node(default) for getting the label. I can change to the phandle, may be after this? > > > > > + 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 0; > > + } > > + > > + /* 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; > > +} > > +#endif > > + > > +/* This function is used to load the core bitstream from the > > OCRAM. */ > >  int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t > > rbf_size) > >  { > > - int status; > > + unsigned long status; > > + struct rbf_info rbfinfo; > >   > > - /* disable all signals from hps peripheral controller to > > fpga */ > > + memset(&rbfinfo, 0, sizeof(rbfinfo)); > > + > > + /* Disable all signals from hps peripheral controller to > > fpga */ > >   writel(0, &system_manager_base->fpgaintf_en_global); > >   > > - /* disable all axi bridge (hps2fpga, lwhps2fpga & > > fpga2hps) */ > > + /* Disable all axi bridge (hps2fpga, lwhps2fpga & > > fpga2hps) */ > >   socfpga_bridges_reset(); > >   > > - /* Initialize the FPGA Manager */ > > - status = fpgamgr_program_init((u32 *)rbf_data, rbf_size); > > - if (status) > > - return status; > > + /* Getting info about bitstream types */ > > + get_rbf_image_info(&rbfinfo, (u16 *)rbf_data); > > + > > + if (rbfinfo.section == periph_section) { > > + /* Initialize the FPGA Manager */ > > + status = fpgamgr_program_init((u32 *)rbf_data, > > rbf_size); > > + if (status) > > + return status; > > + } > > + > > + 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 0; > > + } > >   > > - /* Write the RBF data to FPGA Manager */ > > + /* 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; > >  } > > >