Merge branch 'master' of git://git.denx.de/u-boot-socfpga
authorTom Rini <trini@konsulko.com>
Mon, 13 May 2019 11:13:03 +0000 (07:13 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 13 May 2019 11:13:03 +0000 (07:13 -0400)
- A10 FPGA programming support, Gen5 livetree conversion

16 files changed:
arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
arch/arm/mach-socfpga/spl_a10.c
board/altera/arria10-socdk/fit_spl_fpga.its [new file with mode: 0644]
configs/socfpga_arria10_defconfig
configs/socfpga_stratix10_defconfig
doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
drivers/fpga/socfpga_arria10.c
drivers/gpio/dwapb_gpio.c
drivers/reset/reset-socfpga.c
drivers/serial/altera_uart.c
drivers/spi/cadence_qspi.c
drivers/spi/designware_spi.c
drivers/timer/dw-apb-timer.c
include/configs/socfpga_arria10_socdk.h
include/image.h

index 998d811..cc76196 100644 (file)
 /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";
index 09d13f6..62249b3 100644 (file)
@@ -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_
 
 #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_ */
index c8e73d4..b466307 100644 (file)
@@ -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>
 #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 (file)
index 0000000..adae997
--- /dev/null
@@ -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";
+               };
+       };
+};
index 47fe1d9..09a018c 100644 (file)
@@ -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
index 18cc959..fbab388 100644 (file)
@@ -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
index 2fd8e7a..da210bf 100644 (file)
@@ -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";
        };
index 114dd91..285280e 100644 (file)
@@ -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;
 }
index e55fb4a..04a2381 100644 (file)
@@ -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++;
        }
 
index cb83126..ee4cbcb 100644 (file)
@@ -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;
index 67d4719..436cf23 100644 (file)
@@ -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;
 }
index 41c8700..e2e54cd 100644 (file)
@@ -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,
index dadb6fa..7d58cfa 100644 (file)
@@ -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);
 
index cb48801..86312b8 100644 (file)
@@ -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;
 };
index 92630c5..645e66e 100644 (file)
@@ -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>
 
index bfe4e0b..bb7089e 100644 (file)
@@ -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