diff options
-rw-r--r-- | arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts | 17 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h | 40 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/spl_a10.c | 31 | ||||
-rw-r--r-- | board/altera/arria10-socdk/fit_spl_fpga.its | 38 | ||||
-rw-r--r-- | configs/socfpga_arria10_defconfig | 23 | ||||
-rw-r--r-- | configs/socfpga_stratix10_defconfig | 1 | ||||
-rw-r--r-- | doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt | 26 | ||||
-rw-r--r-- | drivers/fpga/socfpga_arria10.c | 514 | ||||
-rw-r--r-- | drivers/gpio/dwapb_gpio.c | 25 | ||||
-rw-r--r-- | drivers/reset/reset-socfpga.c | 4 | ||||
-rw-r--r-- | drivers/serial/altera_uart.c | 5 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.c | 39 | ||||
-rw-r--r-- | drivers/spi/designware_spi.c | 8 | ||||
-rw-r--r-- | drivers/timer/dw-apb-timer.c | 2 | ||||
-rw-r--r-- | include/configs/socfpga_arria10_socdk.h | 5 | ||||
-rw-r--r-- | include/image.h | 4 |
16 files changed, 702 insertions, 80 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..62249b3695 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); - +const char *get_fpga_filename(void); +int is_fpgamgr_early_user_mode(void); +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, + u32 offset); +void fpgamgr_program(const void *buf, size_t bsize, u32 offset); #endif /* __ASSEMBLY__ */ #endif /* _FPGA_MANAGER_ARRIA10_H_ */ diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index c8e73d47c0..b466307f98 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2012 Altera Corporation <www.altera.com> + * Copyright (C) 2012-2019 Altera Corporation <www.altera.com> */ #include <common.h> @@ -23,6 +23,11 @@ #include <fdtdec.h> #include <watchdog.h> #include <asm/arch/pinmux.h> +#include <asm/arch/fpga_manager.h> +#include <mmc.h> +#include <memalign.h> + +#define FPGA_BUFSIZ 16 * 1024 DECLARE_GLOBAL_DATA_PTR; @@ -68,11 +73,35 @@ u32 spl_boot_mode(const u32 boot_device) void spl_board_init(void) { + ALLOC_CACHE_ALIGN_BUFFER(char, buf, FPGA_BUFSIZ); + /* enable console uart printing */ preloader_console_init(); WATCHDOG_RESET(); arch_early_init_r(); + + /* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */ + if (is_fpgamgr_user_mode()) { + int ret = config_pins(gd->fdt_blob, "shared"); + + if (ret) + return; + + ret = config_pins(gd->fdt_blob, "fpga"); + if (ret) + return; + } else if (!is_fpgamgr_early_user_mode()) { + /* Program IOSSM(early IO release) or full FPGA */ + fpgamgr_program(buf, FPGA_BUFSIZ, 0); + } + + /* If the IOSSM/full FPGA is already loaded, start DDR */ + if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) + ddr_calibration_sequence(); + + if (!is_fpgamgr_user_mode()) + fpgamgr_program(buf, FPGA_BUFSIZ, 0); } void board_init_f(ulong dummy) diff --git a/board/altera/arria10-socdk/fit_spl_fpga.its b/board/altera/arria10-socdk/fit_spl_fpga.its new file mode 100644 index 0000000000..adae997213 --- /dev/null +++ b/board/altera/arria10-socdk/fit_spl_fpga.its @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 + /* + * Copyright (C) 2019 Intel Corporation <www.intel.com> + * + */ + +/dts-v1/; + +/ { + description = "FIT image with FPGA bistream"; + #address-cells = <1>; + + images { + fpga-periph-1 { + description = "FPGA peripheral bitstream"; + data = /incbin/("../../../ghrd_10as066n2.periph.rbf"); + type = "fpga"; + arch = "arm"; + compression = "none"; + }; + + fpga-core-1 { + description = "FPGA core bitstream"; + data = /incbin/("../../../ghrd_10as066n2.core.rbf"); + type = "fpga"; + arch = "arm"; + compression = "none"; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot with FPGA early IO release config"; + fpga = "fpga-periph-1", "fpga-core-1"; + }; + }; +}; diff --git a/configs/socfpga_arria10_defconfig b/configs/socfpga_arria10_defconfig index 47fe1d9690..09a018c97d 100644 --- a/configs/socfpga_arria10_defconfig +++ b/configs/socfpga_arria10_defconfig @@ -6,12 +6,15 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200" # CONFIG_USE_BOOTCOMMAND is not set +CONFIG_SYS_CONSOLE_IS_IN_ENV=y +CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y +CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y CONFIG_DEFAULT_FDT_FILE="socfpga_arria10_socdk_sdmmc.dtb" +CONFIG_VERSION_VARIABLE=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOUNCE_BUFFER=y CONFIG_SPL_TEXT_BASE=0xFFE00000 CONFIG_SPL_FPGA_SUPPORT=y -CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_ASKENV=y CONFIG_CMD_GREPENV=y # CONFIG_CMD_FLASH is not set @@ -20,19 +23,31 @@ CONFIG_CMD_MMC=y CONFIG_CMD_CACHE=y CONFIG_CMD_EXT4_WRITE=y CONFIG_MTDIDS_DEFAULT="nor0=ff705000.spi.0" -# CONFIG_SPL_DOS_PARTITION is not set -# CONFIG_ISO_PARTITION is not set -# CONFIG_EFI_PARTITION is not set +CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names" CONFIG_DEFAULT_DEVICE_TREE="socfpga_arria10_socdk_sdmmc" CONFIG_ENV_IS_IN_MMC=y +CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_DM_MMC=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_FS_FAT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_FS_LOADER=y +CONFIG_FPGA_SOCFPGA=y +CONFIG_SPL_FIT=y +CONFIG_FIT=y CONFIG_DM_GPIO=y CONFIG_DWAPB_GPIO=y CONFIG_DM_MMC=y CONFIG_MTD_DEVICE=y +CONFIG_MMC_DW=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y +CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig index 18cc959450..fbab388b43 100644 --- a/configs/socfpga_stratix10_defconfig +++ b/configs/socfpga_stratix10_defconfig @@ -42,7 +42,6 @@ CONFIG_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0x2003 CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y -# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y diff --git a/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt b/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt index 2fd8e7a847..da210bfc86 100644 --- a/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt +++ b/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt @@ -7,8 +7,31 @@ Required properties: - The second index is for writing FPGA configuration data. - resets : Phandle and reset specifier for the device's reset. - clocks : Clocks used by the device. +- altr,bitstream : Fit image file name for both FPGA peripheral bitstream, + FPGA core bitstream and full bitstream. -Example: + Full bitstream, consist of peripheral bitstream and core + bitstream. + + FPGA peripheral bitstream is used to initialize FPGA IOs, + PLL, IO48 and DDR. This bitstream is required to get DDR up + running. + + FPGA core bitstream contains FPGA design which is used to + program FPGA CRAM and ERAM. + +Example: Bundles both peripheral bitstream and core bitstream into FIT image + called fit_spl_fpga.itb. This FIT image can be created through running + this command: tools/mkimage + -E -p 400 + -f board/altera/arria10-socdk/fit_spl_fpga.its + fit_spl_fpga.itb + + For details of describing structure and contents of the FIT image, + please refer board/altera/arria10-socdk/fit_spl_fpga.its + +- Examples for booting with full release or booting with early IO release, then + follow by entering early user mode: fpga_mgr: fpga-mgr@ffd03000 { compatible = "altr,socfpga-a10-fpga-mgr"; @@ -16,4 +39,5 @@ Example: 0xffcfe400 0x20>; clocks = <&l4_mp_clk>; resets = <&rst FPGAMGR_RESET>; + altr,bitstream = "fit_spl_fpga.itb"; }; diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 114dd910ab..285280e507 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) { return (readl(&fpga_manager_base->imgcfg_stat) & ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0; @@ -94,7 +99,7 @@ int fpgamgr_wait_early_user_mode(void) i++; } - debug("Additional %i sync word needed\n", i); + debug("FPGA: Additional %i sync word needed\n", i); /* restoring original CDRATIO */ fpgamgr_set_cd_ratio(cd_ratio); @@ -172,9 +177,10 @@ static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data, compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1; compress = !compress; - debug("header word %d = %08x\n", 69, rbf_data[69]); - debug("header word %d = %08x\n", 229, rbf_data[229]); - debug("read from rbf header: encrypt=%d compress=%d\n", encrypt, compress); + debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]); + debug("FPGA: Header word %d = %08x.\n", 229, rbf_data[229]); + debug("FPGA: Read from rbf header: encrypt=%d compress=%d.\n", encrypt, + compress); /* * from the register map description of cdratio in imgcfg_ctrl_02: @@ -359,6 +365,7 @@ static int fpgamgr_program_poll_cd(void) printf("nstatus == 0 while waiting for condone\n"); return -EPERM; } + WATCHDOG_RESET(); } if (i == FPGA_TIMEOUT_CNT) @@ -432,7 +439,6 @@ int fpgamgr_program_finish(void) printf("FPGA: Poll CD failed with error code %d\n", status); return -EPERM; } - WATCHDOG_RESET(); /* Ensure the FPGA entering user mode */ status = fpgamgr_program_poll_usermode(); @@ -447,27 +453,493 @@ int fpgamgr_program_finish(void) return 0; } -/* - * FPGA Manager to program the FPGA. This is the interface used by FPGA driver. - * Return 0 for sucess, non-zero for error. - */ +ofnode get_fpga_mgr_ofnode(ofnode from) +{ + return ofnode_by_compatible(from, "altr,socfpga-a10-fpga-mgr"); +} + +const char *get_fpga_filename(void) +{ + const char *fpga_filename = NULL; + + ofnode fpgamgr_node = get_fpga_mgr_ofnode(ofnode_null()); + + if (ofnode_valid(fpgamgr_node)) + fpga_filename = ofnode_read_string(fpgamgr_node, + "altr,bitstream"); + + return fpga_filename; +} + +static void get_rbf_image_info(struct rbf_info *rbf, u16 *buffer) +{ + /* + * Magic ID starting at: + * -> 1st dword[15:0] in periph.rbf + * -> 2nd dword[15:0] in core.rbf + * Note: dword == 32 bits + */ + u32 word_reading_max = 2; + u32 i; + + for (i = 0; i < word_reading_max; i++) { + if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) { + rbf->security = unencrypted; + } else if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_ENCRYPTED) { + rbf->security = encrypted; + } else if (*(buffer + i + 1) == + FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) { + rbf->security = unencrypted; + } else if (*(buffer + i + 1) == + FPGA_SOCFPGA_A10_RBF_ENCRYPTED) { + rbf->security = encrypted; + } else { + rbf->security = invalid; + continue; + } + + /* PERIPH RBF(buffer + i + 1), CORE RBF(buffer + i + 2) */ + if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_PERIPH) { + rbf->section = periph_section; + break; + } else if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_CORE) { + rbf->section = core_section; + break; + } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_PERIPH) { + rbf->section = periph_section; + break; + } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_CORE) { + rbf->section = core_section; + break; + } + + rbf->section = unknown; + break; + + WATCHDOG_RESET(); + } +} + +#ifdef CONFIG_FS_LOADER +static int first_loading_rbf_to_buffer(struct udevice *dev, + struct fpga_loadfs_info *fpga_loadfs, + u32 *buffer, size_t *buffer_bsize) +{ + u32 *buffer_p = (u32 *)*buffer; + u32 *loadable = buffer_p; + size_t buffer_size = *buffer_bsize; + size_t fit_size; + int ret, i, count, confs_noffset, images_noffset, rbf_offset, rbf_size; + const char *fpga_node_name = NULL; + const char *uname = NULL; + + /* Load image header into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, sizeof(struct image_header), + 0); + if (ret < 0) { + debug("FPGA: Failed to read image header from flash.\n"); + return -ENOENT; + } + + if (image_get_magic((struct image_header *)buffer_p) != FDT_MAGIC) { + debug("FPGA: No FDT magic was found.\n"); + return -EBADF; + } + + fit_size = fdt_totalsize(buffer_p); + + if (fit_size > buffer_size) { + debug("FPGA: FIT image is larger than available buffer.\n"); + debug("Please use FIT external data or increasing buffer.\n"); + return -ENOMEM; + } + + /* Load entire FIT into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, fit_size, 0); + if (ret < 0) + return ret; + + ret = fit_check_format(buffer_p); + if (!ret) { + debug("FPGA: No valid FIT image was found.\n"); + return -EBADF; + } + + confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH); + images_noffset = fdt_path_offset(buffer_p, FIT_IMAGES_PATH); + if (confs_noffset < 0 || images_noffset < 0) { + debug("FPGA: No Configurations or images nodes were found.\n"); + return -ENOENT; + } + + /* Get default configuration unit name from default property */ + confs_noffset = fit_conf_get_node(buffer_p, NULL); + if (confs_noffset < 0) { + debug("FPGA: No default configuration was found in config.\n"); + return -ENOENT; + } + + count = fit_conf_get_prop_node_count(buffer_p, confs_noffset, + FIT_FPGA_PROP); + if (count < 0) { + debug("FPGA: Invalid configuration format for FPGA node.\n"); + return count; + } + debug("FPGA: FPGA node count: %d\n", count); + + for (i = 0; i < count; i++) { + images_noffset = fit_conf_get_prop_node_index(buffer_p, + confs_noffset, + FIT_FPGA_PROP, i); + uname = fit_get_name(buffer_p, images_noffset, NULL); + if (uname) { + debug("FPGA: %s\n", uname); + + if (strstr(uname, "fpga-periph") && + (!is_fpgamgr_early_user_mode() || + is_fpgamgr_user_mode())) { + fpga_node_name = uname; + printf("FPGA: Start to program "); + printf("peripheral/full bitstream ...\n"); + break; + } else if (strstr(uname, "fpga-core") && + (is_fpgamgr_early_user_mode() && + !is_fpgamgr_user_mode())) { + fpga_node_name = uname; + printf("FPGA: Start to program core "); + printf("bitstream ...\n"); + break; + } + } + WATCHDOG_RESET(); + } + + if (!fpga_node_name) { + debug("FPGA: No suitable bitstream was found, count: %d.\n", i); + return 1; + } + + images_noffset = fit_image_get_node(buffer_p, fpga_node_name); + if (images_noffset < 0) { + debug("FPGA: No node '%s' was found in FIT.\n", + fpga_node_name); + return -ENOENT; + } + + if (!fit_image_get_data_position(buffer_p, images_noffset, + &rbf_offset)) { + debug("FPGA: Data position was found.\n"); + } else if (!fit_image_get_data_offset(buffer_p, images_noffset, + &rbf_offset)) { + /* + * For FIT with external data, figure out where + * the external images start. This is the base + * for the data-offset properties in each image. + */ + rbf_offset += ((fdt_totalsize(buffer_p) + 3) & ~3); + debug("FPGA: Data offset was found.\n"); + } else { + debug("FPGA: No data position/offset was found.\n"); + return -ENOENT; + } + + ret = fit_image_get_data_size(buffer_p, images_noffset, &rbf_size); + if (ret < 0) { + debug("FPGA: No data size was found (err=%d).\n", ret); + return -ENOENT; + } + + if (gd->ram_size < rbf_size) { + debug("FPGA: Using default OCRAM buffer and size.\n"); + } else { + ret = fit_image_get_load(buffer_p, images_noffset, + (ulong *)loadable); + if (ret < 0) { + buffer_p = (u32 *)DEFAULT_DDR_LOAD_ADDRESS; + debug("FPGA: No loadable was found.\n"); + debug("FPGA: Using default DDR load address: 0x%x .\n", + DEFAULT_DDR_LOAD_ADDRESS); + } else { + buffer_p = (u32 *)*loadable; + debug("FPGA: Found loadable address = 0x%x.\n", + *loadable); + } + + buffer_size = rbf_size; + } + + debug("FPGA: External data: offset = 0x%x, size = 0x%x.\n", + rbf_offset, rbf_size); + + fpga_loadfs->remaining = rbf_size; + + /* + * Determine buffer size vs bitstream size, and calculating number of + * chunk by chunk transfer is required due to smaller buffer size + * compare to bitstream + */ + if (rbf_size <= buffer_size) { + /* Loading whole bitstream into buffer */ + buffer_size = rbf_size; + fpga_loadfs->remaining = 0; + } else { + fpga_loadfs->remaining -= buffer_size; + } + + fpga_loadfs->offset = rbf_offset; + /* Loading bitstream into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, buffer_size, + fpga_loadfs->offset); + if (ret < 0) { + debug("FPGA: Failed to read bitstream from flash.\n"); + return -ENOENT; + } + + /* Getting info about bitstream types */ + get_rbf_image_info(&fpga_loadfs->rbfinfo, (u16 *)buffer_p); + + /* Update next reading bitstream offset */ + fpga_loadfs->offset += buffer_size; + + /* Update the final addr for bitstream */ + *buffer = (u32)buffer_p; + + /* Update the size of bitstream to be programmed into FPGA */ + *buffer_bsize = buffer_size; + + return 0; +} + +static int subsequent_loading_rbf_to_buffer(struct udevice *dev, + struct fpga_loadfs_info *fpga_loadfs, + u32 *buffer, size_t *buffer_bsize) +{ + int ret = 0; + u32 *buffer_p = (u32 *)*buffer; + + /* Read the bitstream chunk by chunk. */ + if (fpga_loadfs->remaining > *buffer_bsize) { + fpga_loadfs->remaining -= *buffer_bsize; + } else { + *buffer_bsize = fpga_loadfs->remaining; + fpga_loadfs->remaining = 0; + } + + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, *buffer_bsize, + fpga_loadfs->offset); + if (ret < 0) { + debug("FPGA: Failed to read bitstream from flash.\n"); + return -ENOENT; + } + + /* Update next reading bitstream offset */ + fpga_loadfs->offset += *buffer_bsize; + + return 0; +} + +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, + u32 offset) +{ + struct fpga_loadfs_info fpga_loadfs; + struct udevice *dev; + int status, ret, size; + u32 buffer = (uintptr_t)buf; + size_t buffer_sizebytes = bsize; + size_t buffer_sizebytes_ori = bsize; + size_t total_sizeof_image = 0; + ofnode node; + const fdt32_t *phandle_p; + u32 phandle; + + node = get_fpga_mgr_ofnode(ofnode_null()); + + if (ofnode_valid(node)) { + phandle_p = ofnode_get_property(node, "firmware-loader", &size); + if (!phandle_p) { + node = ofnode_path("/chosen"); + if (!ofnode_valid(node)) { + debug("FPGA: /chosen node was not found.\n"); + return -ENOENT; + } + + phandle_p = ofnode_get_property(node, "firmware-loader", + &size); + if (!phandle_p) { + debug("FPGA: firmware-loader property was not"); + debug(" found.\n"); + return -ENOENT; + } + } + } else { + debug("FPGA: FPGA manager node was not found.\n"); + return -ENOENT; + } + + phandle = fdt32_to_cpu(*phandle_p); + ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER, + phandle, &dev); + if (ret) + return ret; + + memset(&fpga_loadfs, 0, sizeof(fpga_loadfs)); + + fpga_loadfs.fpga_fsinfo = fpga_fsinfo; + fpga_loadfs.offset = offset; + + printf("FPGA: Checking FPGA configuration setting ...\n"); + + /* + * Note: Both buffer and buffer_sizebytes values can be altered by + * function below. + */ + ret = first_loading_rbf_to_buffer(dev, &fpga_loadfs, &buffer, + &buffer_sizebytes); + if (ret == 1) { + printf("FPGA: Skipping configuration ...\n"); + return 0; + } else if (ret) { + return ret; + } + + if (fpga_loadfs.rbfinfo.section == core_section && + !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) { + debug("FPGA : Must be in Early Release mode to program "); + debug("core bitstream.\n"); + return -EPERM; + } + + /* Disable all signals from HPS peripheral controller to FPGA */ + writel(0, &system_manager_base->fpgaintf_en_global); + + /* Disable all axi bridges (hps2fpga, lwhps2fpga & fpga2hps) */ + socfpga_bridges_reset(); + + if (fpga_loadfs.rbfinfo.section == periph_section) { + /* Initialize the FPGA Manager */ + status = fpgamgr_program_init((u32 *)buffer, buffer_sizebytes); + if (status) { + debug("FPGA: Init with peripheral bitstream failed.\n"); + return -EPERM; + } + } + + /* Transfer bitstream to FPGA Manager */ + fpgamgr_program_write((void *)buffer, buffer_sizebytes); + + total_sizeof_image += buffer_sizebytes; + + while (fpga_loadfs.remaining) { + ret = subsequent_loading_rbf_to_buffer(dev, + &fpga_loadfs, + &buffer, + &buffer_sizebytes_ori); + + if (ret) + return ret; + + /* Transfer data to FPGA Manager */ + fpgamgr_program_write((void *)buffer, + buffer_sizebytes_ori); + + total_sizeof_image += buffer_sizebytes_ori; + + WATCHDOG_RESET(); + } + + if (fpga_loadfs.rbfinfo.section == periph_section) { + if (fpgamgr_wait_early_user_mode() != -ETIMEDOUT) { + config_pins(gd->fdt_blob, "shared"); + puts("FPGA: Early Release Succeeded.\n"); + } else { + debug("FPGA: Failed to see Early Release.\n"); + return -EIO; + } + + /* For monolithic bitstream */ + if (is_fpgamgr_user_mode()) { + /* Ensure the FPGA entering config done */ + status = fpgamgr_program_finish(); + if (status) + return status; + + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } + } else if (fpga_loadfs.rbfinfo.section == core_section) { + /* Ensure the FPGA entering config done */ + status = fpgamgr_program_finish(); + if (status) + return status; + + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } else { + debug("FPGA: Config Error: Unsupported bitstream type.\n"); + return -ENOEXEC; + } + + return (int)total_sizeof_image; +} + +void fpgamgr_program(const void *buf, size_t bsize, u32 offset) +{ + fpga_fs_info fpga_fsinfo; + + fpga_fsinfo.filename = get_fpga_filename(); + + if (fpga_fsinfo.filename) + socfpga_loadfs(&fpga_fsinfo, buf, bsize, offset); +} +#endif + +/* This function is used to load the core bitstream from the OCRAM. */ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) { - int status; + unsigned long status; + struct rbf_info rbfinfo; - /* disable all signals from hps peripheral controller to fpga */ + memset(&rbfinfo, 0, sizeof(rbfinfo)); + + /* Disable all signals from hps peripheral controller to fpga */ writel(0, &system_manager_base->fpgaintf_en_global); - /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ + /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ socfpga_bridges_reset(); - /* Initialize the FPGA Manager */ - status = fpgamgr_program_init((u32 *)rbf_data, rbf_size); - if (status) - return status; + /* Getting info about bitstream types */ + get_rbf_image_info(&rbfinfo, (u16 *)rbf_data); + + if (rbfinfo.section == periph_section) { + /* Initialize the FPGA Manager */ + status = fpgamgr_program_init((u32 *)rbf_data, rbf_size); + if (status) + return status; + } - /* Write the RBF data to FPGA Manager */ + if (rbfinfo.section == core_section && + !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) { + debug("FPGA : Must be in early release mode to program "); + debug("core bitstream.\n"); + return -EPERM; + } + + /* Write the bitstream to FPGA Manager */ fpgamgr_program_write(rbf_data, rbf_size); - return fpgamgr_program_finish(); + status = fpgamgr_program_finish(); + if (status) { + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } + + return status; } diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e55fb4ac73..04a2381acd 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -17,8 +17,6 @@ #include <errno.h> #include <reset.h> -DECLARE_GLOBAL_DATA_PTR; - #define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc) #define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc) #define GPIO_INTEN 0x30 @@ -150,10 +148,10 @@ static int gpio_dwapb_probe(struct udevice *dev) static int gpio_dwapb_bind(struct udevice *dev) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); - const void *blob = gd->fdt_blob; struct udevice *subdev; fdt_addr_t base; - int ret, node, bank = 0; + int ret, bank = 0; + ofnode node; /* If this is a child device, there is nothing to do here */ if (plat) @@ -165,10 +163,9 @@ static int gpio_dwapb_bind(struct udevice *dev) return -ENXIO; } - for (node = fdt_first_subnode(blob, dev_of_offset(dev)); - node > 0; - node = fdt_next_subnode(blob, node)) { - if (!fdtdec_get_bool(blob, node, "gpio-controller")) + for (node = dev_read_first_subnode(dev); ofnode_valid(node); + node = dev_read_next_subnode(node)) { + if (!ofnode_read_bool(node, "gpio-controller")) continue; plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL); @@ -177,15 +174,15 @@ static int gpio_dwapb_bind(struct udevice *dev) plat->base = base; plat->bank = bank; - plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0); - plat->name = fdt_stringlist_get(blob, node, "bank-name", 0, - NULL); - if (!plat->name) { + plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0); + + if (ofnode_read_string_index(node, "bank-name", 0, + &plat->name)) { /* * Fall back to node name. This means accessing pins * via bank name won't work. */ - plat->name = fdt_get_name(blob, node, NULL); + plat->name = ofnode_get_name(node); } ret = device_bind(dev, dev->driver, plat->name, @@ -193,7 +190,7 @@ static int gpio_dwapb_bind(struct udevice *dev) if (ret) return ret; - dev_set_of_offset(subdev, node); + dev->node = node; bank++; } diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index cb8312619f..ee4cbcb02f 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -107,14 +107,12 @@ static const struct reset_ops socfpga_reset_ops = { static int socfpga_reset_probe(struct udevice *dev) { struct socfpga_reset_data *data = dev_get_priv(dev); - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); u32 modrst_offset; void __iomem *membase; membase = devfdt_get_addr_ptr(dev); - modrst_offset = fdtdec_get_int(blob, node, "altr,modrst-offset", 0x10); + modrst_offset = dev_read_u32_default(dev, "altr,modrst-offset", 0x10); data->modrst_base = membase + modrst_offset; return 0; diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 67d47199aa..436cf2331d 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -10,8 +10,6 @@ #include <serial.h> #include <asm/io.h> -DECLARE_GLOBAL_DATA_PTR; - /* status register */ #define ALTERA_UART_TMT BIT(5) /* tx empty */ #define ALTERA_UART_TRDY BIT(6) /* tx ready */ @@ -91,8 +89,7 @@ static int altera_uart_ofdata_to_platdata(struct udevice *dev) plat->regs = map_physmem(devfdt_get_addr(dev), sizeof(struct altera_uart_regs), MAP_NOCACHE); - plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "clock-frequency", 0); + plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0); return 0; } diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 41c87004d8..e2e54cd277 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -18,8 +18,6 @@ #define CQSPI_INDIRECT_READ 2 #define CQSPI_INDIRECT_WRITE 3 -DECLARE_GLOBAL_DATA_PTR; - static int cadence_spi_write_speed(struct udevice *bus, uint hz) { struct cadence_spi_platdata *plat = bus->platdata; @@ -295,36 +293,37 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen, static int cadence_spi_ofdata_to_platdata(struct udevice *bus) { struct cadence_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus); - int subnode; + ofnode subnode; plat->regbase = (void *)devfdt_get_addr_index(bus, 0); plat->ahbbase = (void *)devfdt_get_addr_index(bus, 1); - plat->is_decoded_cs = fdtdec_get_bool(blob, node, "cdns,is-decoded-cs"); - plat->fifo_depth = fdtdec_get_uint(blob, node, "cdns,fifo-depth", 128); - plat->fifo_width = fdtdec_get_uint(blob, node, "cdns,fifo-width", 4); - plat->trigger_address = fdtdec_get_uint(blob, node, - "cdns,trigger-address", 0); + plat->is_decoded_cs = dev_read_bool(bus, "cdns,is-decoded-cs"); + plat->fifo_depth = dev_read_u32_default(bus, "cdns,fifo-depth", 128); + plat->fifo_width = dev_read_u32_default(bus, "cdns,fifo-width", 4); + plat->trigger_address = dev_read_u32_default(bus, + "cdns,trigger-address", + 0); /* All other paramters are embedded in the child node */ - subnode = fdt_first_subnode(blob, node); - if (subnode < 0) { + subnode = dev_read_first_subnode(bus); + if (!ofnode_valid(subnode)) { printf("Error: subnode with SPI flash config missing!\n"); return -ENODEV; } /* Use 500 KHz as a suitable default */ - plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency", - 500000); + plat->max_hz = ofnode_read_u32_default(subnode, "spi-max-frequency", + 500000); /* Read other parameters from DT */ - plat->page_size = fdtdec_get_uint(blob, subnode, "page-size", 256); - plat->block_size = fdtdec_get_uint(blob, subnode, "block-size", 16); - plat->tshsl_ns = fdtdec_get_uint(blob, subnode, "cdns,tshsl-ns", 200); - plat->tsd2d_ns = fdtdec_get_uint(blob, subnode, "cdns,tsd2d-ns", 255); - plat->tchsh_ns = fdtdec_get_uint(blob, subnode, "cdns,tchsh-ns", 20); - plat->tslch_ns = fdtdec_get_uint(blob, subnode, "cdns,tslch-ns", 20); + plat->page_size = ofnode_read_u32_default(subnode, "page-size", 256); + plat->block_size = ofnode_read_u32_default(subnode, "block-size", 16); + plat->tshsl_ns = ofnode_read_u32_default(subnode, "cdns,tshsl-ns", + 200); + plat->tsd2d_ns = ofnode_read_u32_default(subnode, "cdns,tsd2d-ns", + 255); + plat->tchsh_ns = ofnode_read_u32_default(subnode, "cdns,tchsh-ns", 20); + plat->tslch_ns = ofnode_read_u32_default(subnode, "cdns,tslch-ns", 20); debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n", __func__, plat->regbase, plat->ahbbase, plat->max_hz, diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index dadb6fa18b..7d58cfae55 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -22,8 +22,6 @@ #include <linux/iopoll.h> #include <asm/io.h> -DECLARE_GLOBAL_DATA_PTR; - /* Register offsets */ #define DW_SPI_CTRL0 0x00 #define DW_SPI_CTRL1 0x04 @@ -155,14 +153,12 @@ static int request_gpio_cs(struct udevice *bus) static int dw_spi_ofdata_to_platdata(struct udevice *bus) { struct dw_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus); plat->regs = (struct dw_spi *)devfdt_get_addr(bus); /* Use 500KHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 500000); + plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", + 500000); debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, plat->frequency); diff --git a/drivers/timer/dw-apb-timer.c b/drivers/timer/dw-apb-timer.c index cb48801af1..86312b8dc7 100644 --- a/drivers/timer/dw-apb-timer.c +++ b/drivers/timer/dw-apb-timer.c @@ -17,8 +17,6 @@ #define DW_APB_CURR_VAL 0x4 #define DW_APB_CTRL 0x8 -DECLARE_GLOBAL_DATA_PTR; - struct dw_apb_timer_priv { fdt_addr_t regs; }; diff --git a/include/configs/socfpga_arria10_socdk.h b/include/configs/socfpga_arria10_socdk.h index 92630c5e6e..645e66e6b0 100644 --- a/include/configs/socfpga_arria10_socdk.h +++ b/include/configs/socfpga_arria10_socdk.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2015-2017 Altera Corporation <www.altera.com> + * Copyright (C) 2015-2019 Altera Corporation <www.altera.com> */ #ifndef __CONFIG_SOCFGPA_ARRIA10_H__ @@ -36,6 +36,9 @@ */ #define CONFIG_SYS_MAX_FLASH_BANKS 1 +/* SPL memory allocation configuration, this is for FAT implementation */ +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00015000 + /* The rest of the configuration is shared */ #include <configs/socfpga_common.h> diff --git a/include/image.h b/include/image.h index bfe4e0b5e7..bb7089ef5d 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 |