On 08/29/2017 12:45 PM, tien.fong.c...@intel.com wrote:
> From: Tien Fong Chee <tien.fong.c...@intel.com>
> 
> This driver handles FPGA program operation from flash loading
> RBF to memory and then to program FPGA.
> 
> Signed-off-by: Tien Fong Chee <tien.fong.c...@intel.com>
> ---
>  .../include/mach/fpga_manager_arria10.h            |   27 ++
>  drivers/fpga/socfpga_arria10.c                     |  386 
> +++++++++++++++++++-
>  include/altera.h                                   |    6 +
>  include/configs/socfpga_common.h                   |    4 +
>  4 files changed, 422 insertions(+), 1 deletions(-)
> 
> 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 9cbf696..93a9122 100644
> --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> +++ b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
> @@ -8,6 +8,8 @@
>  #ifndef _FPGA_MANAGER_ARRIA10_H_
>  #define _FPGA_MANAGER_ARRIA10_H_
>  
> +#include <asm/cache.h>
> +
>  #define ALT_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR_SET_MSK                BIT(0)
>  #define ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK   BIT(1)
>  #define ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK                 BIT(2)
> @@ -89,11 +91,36 @@ struct socfpga_fpga_manager {
>       u32  imgcfg_fifo_status;
>  };
>  
> +#if defined(CONFIG_CMD_FPGA_LOADFS)
> +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 flash_info {
> +     char *interface;
> +     char *dev_part;
> +     char *filename;
> +     int fstype;
> +     u32 remaining;
> +     u32 flash_offset;
> +     struct rbf_info rbfinfo;
> +     struct image_header header;
> +};
> +#endif
> +
>  /* 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);
> +#if defined(CONFIG_CMD_FPGA_LOADFS)
> +const char *get_cff_filename(const void *fdt, int *len, u32 core);
> +const char *get_cff_devpart(const void *fdt, int *len);
> +#endif
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
> index 5c1a68a..90c55e5 100644
> --- a/drivers/fpga/socfpga_arria10.c
> +++ b/drivers/fpga/socfpga_arria10.c
> @@ -13,6 +13,12 @@
>  #include <altera.h>
>  #include <common.h>
>  #include <errno.h>
> +#include <fat.h>
> +#include <fs.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <part.h>
> +#include <spl.h>
>  #include <wait_bit.h>
>  #include <watchdog.h>
>  
> @@ -22,6 +28,10 @@
>  #define COMPRESSION_OFFSET   229
>  #define FPGA_TIMEOUT_MSEC    1000  /* timeout in ms */
>  #define FPGA_TIMEOUT_CNT     0x1000000
> +#define RBF_UNENCRYPTED              0xa65c
> +#define RBF_ENCRYPTED                0xa65d
> +#define ARRIA10RBF_PERIPH    0x0001
> +#define ARRIA10RBF_CORE              0x8001
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> @@ -118,7 +128,7 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void)
>       return wait_for_bit(__func__,
>                           &fpga_manager_base->imgcfg_stat,
>                           mask,
> -                         false, FPGA_TIMEOUT_MSEC, false);
> +                         true, FPGA_TIMEOUT_MSEC, false);
>  }
>  
>  static int wait_for_f2s_nstatus_pin(unsigned long value)
> @@ -453,6 +463,281 @@ int fpgamgr_program_finish(void)
>       return 0;
>  }
>  
> +#if defined(CONFIG_CMD_FPGA_LOADFS)
> +const char *get_cff_filename(const void *fdt, int *len, u32 core)
> +{
> +     const char *cff_filename = NULL;
> +     const char *cell;
> +     int nodeoffset;
> +     nodeoffset = fdt_subnode_offset(fdt, 0, "chosen");
> +
> +     if (nodeoffset >= 0) {
> +             if (core)
> +                     cell = fdt_getprop(fdt,
> +                                     nodeoffset,
> +                                     "cffcore-file",
> +                                     len);
> +             else
> +                     cell = fdt_getprop(fdt, nodeoffset, "cff-file", len);

This should be a property of the FPGA , not the system . You can have
multiple FPGAs and then this would become a problem.

> +
> +             if (cell)
> +                     cff_filename = cell;
> +     }
> +
> +     return cff_filename;
> +}
> +
> +const char *get_cff_devpart(const void *fdt, int *len)
> +{
> +     const char *cff_devpart = NULL;
> +     const char *cell;
> +     int nodeoffset;
> +     nodeoffset = fdt_subnode_offset(fdt, 0, "chosen");
> +
> +             cell = fdt_getprop(fdt, nodeoffset, "cff_devpart", len);

Indent ? What is this new undocumented DT node about ?

> +             if (cell)
> +                     cff_devpart = cell;
> +
> +     return cff_devpart;
> +}
> +
> +void get_rbf_image_info(struct rbf_info *rbf, u16 *buffer)
> +{
> +     /*
> +       Magic ID starting at:
> +        -> 1st dword in periph.rbf
> +        -> 2nd dword in core.rbf
> +     */

Checkpatch should complain about incorrect multiline comment style here ...

> +     u32 word_reading_max = 2;
> +     u32 i;
> +
> +     for(i = 0; i < word_reading_max; i++)
> +     {
> +             if(RBF_UNENCRYPTED == *(buffer + i)) /* PERIPH RBF */
> +                     rbf->security = unencrypted;
> +             else if (RBF_ENCRYPTED == *(buffer + i))
> +                     rbf->security = encrypted;
> +             else if (RBF_UNENCRYPTED == *(buffer + i + 1)) /* CORE RBF */
> +                                     rbf->security = unencrypted;
> +             else if (RBF_ENCRYPTED == *(buffer + i + 1))
> +                                     rbf->security = encrypted;
> +             else {
> +                     rbf->security = invalid;
> +                     continue;
> +             }
> +
> +             /* PERIPH RBF */
> +             if (ARRIA10RBF_PERIPH == *(buffer + i + 1)) {
> +                     rbf->section = periph_section;
> +                     break;
> +             }
> +             else if (ARRIA10RBF_CORE == *(buffer + i + 1)) {
> +                     rbf->section = core_section;
> +                     break;
> +             } /* CORE RBF */
> +             else if (ARRIA10RBF_PERIPH == *(buffer + i + 2)) {
> +                     rbf->section = periph_section;
> +                     break;
> +             }
> +             else if (ARRIA10RBF_CORE == *(buffer + i + 2)) {
> +                     rbf->section = core_section;
> +                     break;
> +             }
> +             else {

} else { ... coding style ...

> +                     rbf->section = unknown;
> +                     break;
> +             }
> +     }
> +
> +     return;
> +}
> +
> +static int flash_read(struct flash_info *flashinfo,
> +     u32 size_read,
> +     u32 *buffer_ptr)
> +{
> +     size_t ret = EEXIST;
> +     loff_t actread = 0;
> +
> +#ifdef CONFIG_FS_FAT
> +             ret = fat_read_file(flashinfo->filename,
> +                             buffer_ptr, flashinfo->flash_offset,
> +                              size_read, &actread);
> +#endif

How can a generic FPGA driver depend on random FS functionality ?
This is broken ...

> +             if (ret || actread != size_read) {
> +                     printf("Failed to read %s from flash %d ",
> +                             flashinfo->filename,
> +                              ret);
> +                     printf("!= %d.\n", size_read);
> +                     return -EPERM;
> +             } else
> +                     ret = actread;
> +
> +     return ret;
> +}
> +
> +static int fs_flash_preinit(struct flash_info *flashinfo,
> +     u32 *buffer, u32 *buffer_sizebytes)

Is this an FPGA driver or MTD driver ?

> +{
> +     u32 *bufferptr_after_header = NULL;
> +     u32 buffersize_after_header = 0;
> +     u32 rbf_header_data_size = 0;
> +     int ret = 0;
> +
> +     flashinfo->flash_offset = 0;
> +
> +     /* To avoid from keeping re-read the contents */
> +     struct image_header *header = &(flashinfo->header);
> +     size_t buffer_size = *buffer_sizebytes;
> +     u32 *buffer_ptr = (u32 *)*buffer;
> +
> +

Two newlines ... fix

> +      /* Load mkimage header into buffer */
> +     ret = flash_read(flashinfo,
> +                     sizeof(struct image_header), buffer_ptr);
> +
> +     if (0 >= ret) {
> +             printf(" Failed to read mkimage header from flash.\n");
> +             return -ENOENT;
> +     }
> +
> +     WATCHDOG_RESET();
> +
> +     memcpy(header, (u_char *)buffer_ptr, sizeof(*header));
> +
> +     if (!image_check_magic(header)) {
> +             printf("FPGA: Bad Magic Number.\n");
> +             return -EBADF;
> +     }
> +
> +     if (!image_check_hcrc(header)) {
> +             printf("FPGA: Bad Header Checksum.\n");
> +             return -EPERM;
> +     }
> +
> +     /* Getting rbf data size */
> +     flashinfo->remaining =
> +             image_get_data_size(header);
> +
> +     /* Calculate total size of both rbf data with mkimage header */
> +     rbf_header_data_size = flashinfo->remaining +
> +                             sizeof(struct image_header);
> +
> +     /* Loading to buffer chunk by chunk, normally for OCRAM buffer */
> +     if (rbf_header_data_size > buffer_size) {
> +             /* Calculate size of rbf data in the buffer */
> +             buffersize_after_header =
> +                     buffer_size - sizeof(struct image_header);
> +             flashinfo->remaining -= buffersize_after_header;
> +     } else {
> +     /* Loading whole rbf image into buffer, normally for DDR buffer */
> +             buffer_size = rbf_header_data_size;
> +             /* Calculate size of rbf data in the buffer */
> +             buffersize_after_header =
> +                     buffer_size - sizeof(struct image_header);
> +             flashinfo->remaining = 0;
> +     }
> +
> +     /* Loading mkimage header and rbf data into buffer */
> +     ret = flash_read(flashinfo, buffer_size, buffer_ptr);
> +
> +     if (0 >= ret) {
> +             printf(" Failed to read mkimage header and rbf data ");
> +             printf("from flash.\n");
> +             return -ENOENT;
> +     }
> +
> +     /* Getting pointer of rbf data starting address where is it
> +        right after mkimage header */
> +     bufferptr_after_header =
> +             (u32 *)((u_char *)buffer_ptr + sizeof(struct image_header));
> +
> +     /* Update next reading rbf data flash offset */
> +     flashinfo->flash_offset += buffer_size;
> +
> +     /* Update the starting addr of rbf data to init FPGA & programming
> +        into FPGA */
> +     *buffer = (u32)bufferptr_after_header;
> +
> +     get_rbf_image_info(&flashinfo->rbfinfo, (u16 *)bufferptr_after_header);
> +
> +     /* Update the size of rbf data to be programmed into FPGA */
> +     *buffer_sizebytes = buffersize_after_header;
> +
> +#ifdef CONFIG_CHECK_FPGA_DATA_CRC
> +     flashinfo->datacrc =
> +             crc32(flashinfo->datacrc,
> +             (u_char *)bufferptr_after_header,
> +             buffersize_after_header);
> +#endif
> +
> +if (0 == flashinfo->remaining) {
> +#ifdef CONFIG_CHECK_FPGA_DATA_CRC
> +     if (flashinfo->datacrc !=
> +             image_get_dcrc(&(flashinfo->header))) {
> +             printf("FPGA: Bad Data Checksum.\n");
> +             return -EPERM;
> +     }
> +#endif
> +}
> +     return 0;
> +}
> +
> +static int fs_flash_read(struct flash_info *flashinfo, u32 *buffer,
> +     u32 *buffer_sizebytes)
> +{
> +     int ret = 0;
> +     /* To avoid from keeping re-read the contents */
> +     size_t buffer_size = *buffer_sizebytes;
> +     u32 *buffer_ptr = (u32 *)*buffer;
> +     u32 flash_addr = flashinfo->flash_offset;
> +
> +     /* Buffer allocated in OCRAM */
> +     /* Read the data by small chunk by chunk. */
> +     if (flashinfo->remaining > buffer_size)
> +             flashinfo->remaining -= buffer_size;
> +     else {
> +             /* Buffer allocated in DDR, larger than rbf data most
> +               of the time */
> +             buffer_size = flashinfo->remaining;
> +             flashinfo->remaining = 0;
> +     }
> +
> +     ret = flash_read(flashinfo, buffer_size, buffer_ptr);
> +
> +     if (0 >= ret) {
> +             printf(" Failed to read rbf data from flash.\n");
> +             return -ENOENT;
> +     }
> +
> +#ifdef CONFIG_CHECK_FPGA_DATA_CRC
> +     flashinfo->datacrc =
> +             crc32(flashinfo->datacrc,
> +                     (unsigned char *)buffer_ptr, buffer_size);
> +#endif
> +
> +if (0 == flashinfo->remaining) {
> +#ifdef CONFIG_CHECK_FPGA_DATA_CRC
> +     if (flashinfo->datacrc !=
> +             image_get_dcrc(&(flashinfo->header))) {
> +             printf("FPGA: Bad Data Checksum.\n");
> +             return -EPERM;
> +     }
> +#endif
> +}
> +     /* Update next reading rbf data flash offset */
> +     flash_addr += buffer_size;
> +
> +     flashinfo->flash_offset = flash_addr;
> +
> +     /* Update the size of rbf data to be programmed into FPGA */
> +     *buffer_sizebytes = buffer_size;
> +
> +     return 0;
> +}
> +
>  /*
>   * FPGA Manager to program the FPGA. This is the interface used by FPGA 
> driver.
>   * Return 0 for sucess, non-zero for error.
> @@ -469,6 +754,7 @@ int socfpga_load(Altera_desc *desc, const void *rbf_data, 
> size_t rbf_size)
>  
>       /* Initialize the FPGA Manager */
>       status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
> +
>       if (status)
>               return status;
>  
> @@ -477,3 +763,101 @@ int socfpga_load(Altera_desc *desc, const void 
> *rbf_data, size_t rbf_size)
>  
>       return fpgamgr_program_finish();
>  }
> +
> +int socfpga_loadfs(Altera_desc *desc, const void *buf, size_t bsize,
> +                fpga_fs_info *fpga_fsinfo)
> +{
> +     u32 buffer = 0;
> +     u32 buffer_ori = 0;
> +     size_t buffer_sizebytes = 0;
> +     size_t buffer_sizebytes_ori = 0;
> +     struct flash_info flashinfo;
> +     u32 status = 0;
> +     int ret = 0;
> +
> +     memset(&flashinfo, 0, sizeof(flashinfo));
> +
> +     if (fpga_fsinfo->filename == NULL) {
> +             printf("no peripheral RBF filename specified.\n");
> +             return -EINVAL;
> +     }
> +
> +     WATCHDOG_RESET();
> +
> +     buffer_sizebytes = buffer_sizebytes_ori = bsize;
> +     buffer = buffer_ori = (u32) buf;
> +     flashinfo.interface = fpga_fsinfo->interface;
> +     flashinfo.dev_part = fpga_fsinfo->dev_part;
> +     flashinfo.filename = fpga_fsinfo->filename;
> +     flashinfo.fstype = fpga_fsinfo->fstype;
> +
> +#ifndef CONFIG_SPL_BUILD
> +     if (fs_set_blk_dev(flashinfo.interface, flashinfo.dev_part,
> +                              flashinfo.fstype))
> +     return FPGA_FAIL;
> +#endif
> +
> +     /* Note: Both buffer and buffer_sizebytes values can be altered by
> +        function below. */
> +     ret = fs_flash_preinit(&flashinfo, &buffer, &buffer_sizebytes);
> +
> +     if (ret)
> +             return ret;
> +
> +     if (periph_section == flashinfo.rbfinfo.section) {
> +             /* Initialize the FPGA Manager */
> +             status = fpgamgr_program_init((u32 *)buffer, buffer_sizebytes);
> +             if (status) {
> +                     printf("FPGA: Init with periph rbf failed with error. 
> ");
> +                     printf("code %d\n", status);
> +                     return -EPERM;
> +             }
> +     }
> +
> +     WATCHDOG_RESET();
> +
> +     /* Transfer data to FPGA Manager */
> +     fpgamgr_program_write((void *)buffer,
> +             buffer_sizebytes);
> +
> +     WATCHDOG_RESET();
> +
> +     while (flashinfo.remaining) {
> +             ret = fs_flash_read(&flashinfo, &buffer_ori,
> +                     &buffer_sizebytes_ori);
> +
> +             if (ret)
> +                     return ret;
> +
> +             /* transfer data to FPGA Manager */
> +             fpgamgr_program_write((void *)buffer_ori,
> +                     buffer_sizebytes_ori);
> +
> +             WATCHDOG_RESET();
> +     }
> +
> +     if (periph_section == flashinfo.rbfinfo.section) {
> +             if (-ETIMEDOUT != fpgamgr_wait_early_user_mode())
> +                     printf("FPGA: Early Release Succeeded.\n");
> +             else {
> +                     printf("FPGA: Failed to see Early Release.\n");
> +                     return -EIO;
> +             }
> +     } else if (core_section == flashinfo.rbfinfo.section) {
> +             /* Ensure the FPGA entering config done */
> +             status = fpgamgr_program_finish();
> +             if (status)
> +                     return status;
> +             else
> +                     printf("FPGA: Enter user mode.\n");
> +
> +     } else {
> +             printf("Config Error: Unsupported FGPA raw binary type.\n");
> +             return -ENOEXEC;
> +     }
> +
> +     WATCHDOG_RESET();
> +     return 1;
> +
> +}
> +#endif
> diff --git a/include/altera.h b/include/altera.h
> index 48d3eb7..0597e8a 100644
> --- a/include/altera.h
> +++ b/include/altera.h
> @@ -84,6 +84,10 @@ typedef struct {
>  extern int altera_load(Altera_desc *desc, const void *image, size_t size);
>  extern int altera_dump(Altera_desc *desc, const void *buf, size_t bsize);
>  extern int altera_info(Altera_desc *desc);
> +#if defined(CONFIG_CMD_FPGA_LOADFS)
> +int altera_loadfs(Altera_desc *desc, const void *buf, size_t bsize,
> +                fpga_fs_info *fpga_fsinfo);
> +#endif
>  
>  /* Board specific implementation specific function types
>   *********************************************************************/
> @@ -111,6 +115,8 @@ typedef struct {
>  
>  #ifdef CONFIG_FPGA_SOCFPGA
>  int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
> +int socfpga_loadfs(Altera_desc *desc, const void *buf, size_t bsize,
> +                fpga_fs_info *fpga_fsinfo);
>  #endif
>  
>  #ifdef CONFIG_FPGA_STRATIX_V
> diff --git a/include/configs/socfpga_common.h 
> b/include/configs/socfpga_common.h
> index 9be9e79..c15d244 100644
> --- a/include/configs/socfpga_common.h
> +++ b/include/configs/socfpga_common.h
> @@ -27,7 +27,11 @@
>   */
>  #define CONFIG_NR_DRAM_BANKS         1
>  #define PHYS_SDRAM_1                 0x0
> +#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
>  #define CONFIG_SYS_MALLOC_LEN                (64 * 1024 * 1024)
> +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> +#define CONFIG_SYS_MALLOC_LEN                (128 * 1024 * 1024)
> +#endif

128 MiB malloc area is nonsense, even those 64 MiB are iffy. Why would
you ever need that in a bootloader ?

>  #define CONFIG_SYS_MEMTEST_START     PHYS_SDRAM_1
>  #define CONFIG_SYS_MEMTEST_END               PHYS_SDRAM_1_SIZE
>  #if defined(CONFIG_TARGET_SOCFPGA_GEN5)
> 


-- 
Best regards,
Marek Vasut
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to