On 26. 02. 19 15:53, Chee, Tien Fong wrote: > On Tue, 2019-02-26 at 15:20 +0100, Michal Simek wrote: >> On 19. 02. 19 4:47, tien.fong.c...@intel.com wrote: >>> >>> From: Tien Fong Chee <tien.fong.c...@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.c...@intel.com> >>> >>> --- >>> >>> 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 | 40 +- >>> drivers/fpga/socfpga_arria10.c | 533 >>> ++++++++++++++++++++- >>> include/image.h | 4 + >>> 4 files changed, 571 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..9d43111 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@0 { >> again @0 without reg properly is wrong. > Mind to explain more? >> >>> >>> + u-boot,dm-pre-reloc; >>> + compatible = "u-boot,fs-loader"; >>> + phandlepart = <&mmc 1>; >>> + }; >> I think that this will be nacked by DT guys. >> >>> >>> +}; >>> + >>> +&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..7a4f723 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,40 @@ struct socfpga_fpga_manager { >>> u32 imgcfg_fifo_status; >>> }; >>> >>> +enum rbf_type { >>> + unknown, >>> + periph_section, >>> + core_section >>> +}; >>> + >>> +enum rbf_security { >>> + invalid, >>> + unencrypted, >>> + encrypted >>> +}; >>> + >>> +struct rbf_info { >>> + enum rbf_type section; >>> + enum rbf_security security; >>> +}; >>> + >>> +struct fpga_loadfs_info { >>> + fpga_fs_info *fpga_fsinfo; >>> + u32 remaining; >>> + u32 offset; >>> + struct rbf_info rbfinfo; >>> +}; >>> + >>> /* Functions */ >>> int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size); >>> int fpgamgr_program_finish(void); >>> int is_fpgamgr_user_mode(void); >>> int fpgamgr_wait_early_user_mode(void); >>> - >>> +int is_fpgamgr_early_user_mode(void); >>> +const 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); >>> +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 114dd91..9936b69 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; >>> @@ -64,7 +69,7 @@ static int wait_for_user_mode(void) >>> 1, FPGA_TIMEOUT_MSEC, false); >>> } >>> >>> -static int is_fpgamgr_early_user_mode(void) >>> +int is_fpgamgr_early_user_mode(void) >> This is called inside the same file that's why no reason for this >> change. >> Maybe you are using that later but it just suggest incorrect split. > This is part of complete fpga driver that was accepted long time ago, > and now we just submitted the complete fpga driver. I have no strong > opinion about this. > > Marek, what do you think? >> >> >>> >>> { >>> return (readl(&fpga_manager_base->imgcfg_stat) & >>> ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK >>> ) != 0; >>> @@ -94,7 +99,7 @@ int fpgamgr_wait_early_user_mode(void) >>> i++; >>> } >>> >>> - debug("Additional %i sync word needed\n", i); >>> + debug("FPGA: Additional %i sync word needed\n", i); >> it should be separate patch. >> >>> >>> >>> /* restoring original CDRATIO */ >>> fpgamgr_set_cd_ratio(cd_ratio); >>> @@ -172,9 +177,10 @@ static int >>> fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data, >>> compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1; >>> compress = !compress; >>> >>> - debug("header word %d = %08x\n", 69, rbf_data[69]); >>> - debug("header word %d = %08x\n", 229, rbf_data[229]); >>> - debug("read from rbf header: encrypt=%d compress=%d\n", >>> encrypt, compress); >>> + debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]); >>> + debug("FPGA: Header word %d = %08x.\n", 229, >>> rbf_data[229]); >>> + debug("FPGA: Read from rbf header: encrypt=%d >>> compress=%d.\n", encrypt, >>> + compress); >> separate patch - just disturbing reviewers and you are not saying >> nothing about it in commit message. >> >>> >>> >>> /* >>> * from the register map description of cdratio in >>> imgcfg_ctrl_02: >>> @@ -359,6 +365,7 @@ static int fpgamgr_program_poll_cd(void) >>> printf("nstatus == 0 while waiting for >>> condone\n"); >>> return -EPERM; >>> } >>> + WATCHDOG_RESET(); >>> } >>> >>> if (i == FPGA_TIMEOUT_CNT) >>> @@ -432,7 +439,6 @@ int fpgamgr_program_finish(void) >>> printf("FPGA: Poll CD failed with error code >>> %d\n", status); >>> return -EPERM; >>> } >>> - WATCHDOG_RESET(); >> These two looks like separate patch too. >> >>> >>> >>> /* Ensure the FPGA entering user mode */ >>> status = fpgamgr_program_poll_usermode(); >>> @@ -447,27 +453,512 @@ 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(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->. > Are you means using ofnode? >> >>> >>> + COMPAT_ALTERA_SOCFPGA_FPGA0, >>> + &node_offset, 1); >>> + >>> + return offset_to_ofnode(node_offset); >>> +} >>> + >>> +const char *get_fpga_filename(const void *fdt, int *len) >>> +{ >>> + const char *fpga_filename = NULL; >>> + >>> + ofnode fpgamgr_node = get_fpga_mgr_ofnode(); >>> + >>> + 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; >>> + int confs_noffset, images_noffset; >>> + int rbf_offset; >>> + int rbf_size; >> put them on the same line. > sure. >> >>> >>> + 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); >> nit: better buffer_p, fit_size, 0); > sure. >> >> >>> >>> + >> nit: remove empty line above > sure. >> >>> >>> + 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); >>> + >> nit: remove empty line. > sure. >> >>> >>> + 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; >>> + int status = 0; >>> + int ret = 0; >> no reason to initiate here. > sure. >> >>> >>> + u32 buffer = (uintptr_t)buf; >>> + size_t buffer_sizebytes = bsize; >>> + size_t buffer_sizebytes_ori = bsize; >>> + size_t total_sizeof_image = 0; >>> + struct udevice *dev; >>> + ofnode node; >>> + int size; >> another int - just put them on the same line. > sure. >> >>> >>> + const fdt32_t *phandle_p; >>> + u32 phandle; >>> + >>> + node = get_fpga_mgr_ofnode(); >>> + >>> + 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 0; >> This doesn't look like pass. 0 means pass but it should fail. > This is for supporting our specific use case. >> >>> >>> + } >>> + >>> + /* 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; >>> + int len; >>> + >>> + fpga_fsinfo.filename = get_fpga_filename(gd->fdt_blob, >>> &len); >>> + >>> + 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 */ >>> + /* 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) */ >> separate changes. >> >>> >>> 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); >>> >>> - /* Write the RBF data to FPGA Manager */ >>> + 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; >> 0 is supposed to be pass. This looks like a fail. > This is for supporting our specific use case.
Still if you call this function what you want to load/program something and you are not able to do it, it should return reasonable return value. I would say error value. Maybe you just need to improve that debug message to look more sensible. M -- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
signature.asc
Description: OpenPGP digital signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot