All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v7 3/7] ARM: socfpga: Add FPGA drivers for Arria 10 FPGA bitstream loading
Date: Tue, 5 Feb 2019 09:41:51 +0100	[thread overview]
Message-ID: <052e84aa-7043-1508-eabb-b0e84cd4a687@denx.de> (raw)
In-Reply-To: <1549078036.9723.36.camel@intel.com>

On 2/2/19 4:27 AM, Chee, Tien Fong wrote:
> On Fri, 2019-02-01 at 12:12 -0800, Dalon L Westergreen wrote:
>> On Thu, 2019-01-31 at 22:51 +0800, tien.fong.chee at intel.com wrote:
>>>
>>> From: Tien Fong Chee <tien.fong.chee@intel.com>
>>>
>>> Add FPGA driver to support program FPGA with FPGA bitstream loading
>>> from
>>> filesystem. The driver are designed based on generic firmware
>>> loader
>>> framework. The driver can handle FPGA program operation from
>>> loading FPGA
>>> bitstream in flash to memory and then to program FPGA.
>>>
>>> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
>>>
>>> ---
>>>
>>> changes for v7
>>> - Restructure the FPGA driver to support both peripheral bitstream
>>> and core
>>>   bitstream bundled into FIT image.
>>> - Support loadable property for core bitstream. User can set
>>> loadable
>>>   in DDR for better performance. This loading would be done in one
>>> large
>>>   chunk instead of chunk by chunk loading with small memory buffer.
>>> ---
>>>  arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts       |  18 +
>>>  .../include/mach/fpga_manager_arria10.h            |  39 +-
>>>  drivers/fpga/socfpga_arria10.c                     | 417
>>> ++++++++++++++++++++-
>>>  3 files changed, 457 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
>>> b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
>>> index 998d811..dc55618 100644
>>> --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
>>> +++ b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
>>> @@ -18,6 +18,24 @@
>>>  /dts-v1/;
>>>  #include "socfpga_arria10_socdk.dtsi"
>>>  
>>> +/ {
>>> +	chosen {
>>> +		firmware-loader = &fs_loader0;
>>> +	};
>>> +
>>> +	fs_loader0: fs-loader at 0 {
>>> +		u-boot,dm-pre-reloc;
>>> +		compatible = "u-boot,fs-loader";
>>> +		phandlepart = <&mmc 1>;
>>> +	};
>>> +};
>>> +
>>> +&fpga_mgr {
>>> +	u-boot,dm-pre-reloc;
>>> +	altr,bitstream = "fit_spl_fpga.itb";
>>> +	altr,bitstream-core = "fit_spl_fpga.itb";
>>> +};
>>> +
>>>  &mmc {
>>>  	u-boot,dm-pre-reloc;
>>>  	status = "okay";
>>> diff --git a/arch/arm/mach-
>>> socfpga/include/mach/fpga_manager_arria10.h
>>> b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h
>>> index 09d13f6..683c84c 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.
>>>   */
>>>  
>>>
>> [...]	}
>>>
>>> +
>>> +	if (!is_fpgamgr_early_user_mode() ||
>>> is_fpgamgr_user_mode()) {
>>> +		fpga_node_name = "fpga-1";
>>> +		printf("FPGA: Start to program peripheral
>>> bitstream ...\n");
>>> +	} else if (!is_fpgamgr_user_mode()) {
>>> +		fpga_node_name = "fpga-2";
>>> +		printf("FPGA: Start to program core bitstream
>>> ...\n");
>>> +	}
>> Why are you relying on the node name to define the core / periph RBF?
>> Would
>> it not be better to define this in a property?
> I need to ensure correct sequence of programming the rbf images at
> different FPGA mode. fpga with index 1 always means the 1st to program.
> 
>>  how would one have multiple
>> core and periph rbfs in a single fit image?
> I want strict control to avoid the performance penalty, when this
> happen, performance is almost same as programming full image.
> 
> So, in a single FIT image, only have one core rbf and periph rbf, and
> core rbf must always be the 1st and with the right absolute data
> position to avoid the buffer unaligned. Strict sequence control is also
> one of the reason having one core rbf and one periph rbf in a single
> FIT image.

I thought we established that you cannot depend on the placement and
alignment of files within fitImage ?

Also, you should be able to use fitImage configurations to select from
multiple core and periph RBFs, there's no point in limiting ourselves to
1 core and 1 periph RBF with flexible format such as the fitImage.

> You can create multiple FIT image for multiple core and periph rbfs.
> There are properties such as "altr,bitstream" and "altr,bitstream-core" 
> for supporting different FIT image.
> 
> You can change those properties in U-Boot env(for runtime), or using
> different DTS for differnt configuration.
> 
>>
>> --dalon
>>
>>>
>>> +
>>> +	node_offset = fit_image_get_node(buffer_p,
>>> fpga_node_name);
>>> +	if (node_offset < 0) {
>>> +		debug("FPGA: Could not find node '%s' in FIT\n",
>>> +		     fpga_node_name);
>>> +		return -ENOENT;
>>> +	}
>>> +
>>> +	const char *uname = fit_get_name(buffer_p, node_offset,
>>> NULL);
>>> +
>>> +	if (uname)
>>> +		debug("FPGA: %s\n", uname);
>>> +
>>> +	ret = fit_image_get_data_position(buffer_p, node_offset,
>>> &rbf_offset);
>>> +	if (ret < 0) {
>>> +		debug("FPGA: Could not find data position
>>> (err=%d)\n", ret);
>>> +		return -ENOENT;
>>> +	}
>>> +
>>> +	ret = fit_image_get_data_size(buffer_p, node_offset,
>>> &rbf_size);
>>> +	if (ret < 0) {
>>> +		debug("FPGA: Could not find data size (err=%d)\n",
>>> ret);
>>> +		return -ENOENT;
>>> +	}
>>> +
>>> +	ret = fit_image_get_load(buffer_p, node_offset, (ulong
>>> *)loadable);
>>> +	if (ret < 0) {
>>> +		debug("FPGA: Could not find loadable (err=%d)\n",
>>> ret);
>>> +		debug("FPGA: Using default buffer and size\n");
>>> +	} else {
>>> +		buffer_p = (u32 *)*loadable;
>>> +		buffer_size = rbf_size;
>>> +		debug("FPGA: Found loadable address = 0x%x\n",
>>> *loadable);
>>> +	}
>>> +
>>> +	debug("FPGA: External data: offset = 0x%x, size = 0x%x\n",
>>> +	      rbf_offset, rbf_size);
>>> +
>>> +	fpga_loadfs->remaining = rbf_size;
>>> +
>>> +	/*
>>> +	 * Determine buffer size vs bitstream size, and
>>> calculating number of
>>> +	 * chunk by chunk transfer is required due to smaller
>>> buffer size
>>> +	 * compare to bitstream
>>> +	 */
>>> +	if (rbf_size <= buffer_size) {
>>> +		/* Loading whole bitstream into buffer */
>>> +		buffer_size = rbf_size;
>>> +		fpga_loadfs->remaining = 0;
>>> +	} else {
>>> +		fpga_loadfs->remaining -= buffer_size;
>>> +	}
>>> +
>>> +	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;
>>> +	}
>>> +
>>> +	/* Update next reading bitstream offset */
>>> +	fpga_loadfs->offset += buffer_size;
>>> +
>>> +	/* Getting info about bitstream types */
>>> +	get_rbf_image_info(&fpga_loadfs->rbfinfo, (u16
>>> *)buffer_p);
>>> +
>>> +	/* Update the final addr for bitstream */
>>> +	*buffer = (u32)buffer_p;
>>> +
>>> +	/* Update the size of bitstream to be programmed into FPGA
>>> */
>>> +	*buffer_bsize = buffer_size;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int subsequent_loading_rbf_to_buffer(struct udevice *dev,
>>> +					struct fpga_loadfs_info
>>> *fpga_loadfs,
>>> +					u32 *buffer, size_t
>>> *buffer_bsize)
>>> +{
>>> +	int ret = 0;
>>> +	u32 *buffer_p = (u32 *)*buffer;
>>> +
>>> +	/* Read the bitstream chunk by chunk. */
>>> +	if (fpga_loadfs->remaining > *buffer_bsize) {
>>> +		fpga_loadfs->remaining -= *buffer_bsize;
>>> +	} else {
>>> +		*buffer_bsize = fpga_loadfs->remaining;
>>> +		fpga_loadfs->remaining = 0;
>>> +	}
>>> +
>>> +	ret = request_firmware_into_buf(dev,
>>> +					fpga_loadfs->fpga_fsinfo-
>>>> filename,
>>> +					buffer_p,
>>> +					*buffer_bsize,
>>> +					fpga_loadfs->offset);
>>> +	if (ret < 0) {
>>> +		debug("FPGA: Failed to read bitstream from
>>> flash.\n");
>>> +		return -ENOENT;
>>> +	}
>>> +
>>> +	/* Update next reading bitstream offset */
>>> +	fpga_loadfs->offset += *buffer_bsize;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf,
>>> size_t bsize,
>>> +			u32 offset)
>>> +{
>>> +	struct fpga_loadfs_info fpga_loadfs;
>>> +	int status = 0;
>>> +	int ret = 0;
>>> +	u32 buffer = (u32)buf;
>>> +	size_t buffer_sizebytes = bsize;
>>> +	size_t buffer_sizebytes_ori = bsize;
>>> +	size_t total_sizeof_image = 0;
>>> +	struct udevice *dev;
>>> +
>>> +	ret = uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0,
>>> &dev);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	memset(&fpga_loadfs, 0, sizeof(fpga_loadfs));
>>> +
>>> +	WATCHDOG_RESET();
>>> +
>>> +	fpga_loadfs.fpga_fsinfo = fpga_fsinfo;
>>> +	fpga_loadfs.offset = offset;
>>> +
>>> +	printf("FPGA: Start to program ...\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)
>>> +		return ret;
>>> +
>>> +	if (fpga_loadfs.rbfinfo.section == core_section &&
>>> +		!(is_fpgamgr_early_user_mode() &&
>>> !is_fpgamgr_user_mode())) {
>>> +		debug("FPGA : Must be in Early Release mode to
>>> program ");
>>> +		debug("core bitstream.\n");
>>> +		return 0;
>>> +	}
>>> +
>>> +	/* Disable all signals from HPS peripheral controller to
>>> FPGA */
>>> +	writel(0, &system_manager_base->fpgaintf_en_global);
>>> +
>>> +	/* Disable all axi bridges (hps2fpga, lwhps2fpga &
>>> fpga2hps) */
>>> +	socfpga_bridges_reset();
>>> +
>>> +	if (fpga_loadfs.rbfinfo.section == periph_section) {
>>> +		/* Initialize the FPGA Manager */
>>> +		status = fpgamgr_program_init((u32 *)buffer,
>>> buffer_sizebytes);
>>> +		if (status) {
>>> +			debug("FPGA: Init with peripheral
>>> bitstream failed.\n");
>>> +			return -EPERM;
>>> +		}
>>> +	}
>>> +
>>> +	WATCHDOG_RESET();
>>> +
>>> +	/* Transfer bitstream to FPGA Manager */
>>> +	fpgamgr_program_write((void *)buffer, buffer_sizebytes);
>>> +
>>> +	total_sizeof_image += buffer_sizebytes;
>>> +
>>> +	WATCHDOG_RESET();
>>> +
>>> +	while (fpga_loadfs.remaining) {
>>> +		ret = subsequent_loading_rbf_to_buffer(dev,
>>> +							&fpga_load
>>> fs,
>>> +							&buffer,
>>> +							&buffer_si
>>> zebytes_ori);
>>> +
>>> +		if (ret)
>>> +			return ret;
>>> +
>>> +		/* Transfer data to FPGA Manager */
>>> +		fpgamgr_program_write((void *)buffer,
>>> +					buffer_sizebytes_ori);
>>> +
>>> +		total_sizeof_image += buffer_sizebytes_ori;
>>> +
>>> +		WATCHDOG_RESET();
>>> +	}
>>> +
>>> +	if (fpga_loadfs.rbfinfo.section == periph_section) {
>>> +		if (fpgamgr_wait_early_user_mode() != -ETIMEDOUT)
>>> {
>>> +			config_pins(gd->fdt_blob, "shared");
>>> +			puts("FPGA: Early Release Succeeded.\n");
>>> +		} else {
>>> +			debug("FPGA: Failed to see Early
>>> Release.\n");
>>> +			return -EIO;
>>> +		}
>>> +
>>> +		/* For monolithic bitstream */
>>> +		if (is_fpgamgr_user_mode()) {
>>> +			/* Ensure the FPGA entering config done */
>>> +			status = fpgamgr_program_finish();
>>> +			if (status)
>>> +				return status;
>>> +
>>> +			config_pins(gd->fdt_blob, "fpga");
>>> +			puts("FPGA: Enter user mode.\n");
>>> +		}
>>> +	} else if (fpga_loadfs.rbfinfo.section == core_section) {
>>> +		/* Ensure the FPGA entering config done */
>>> +		status = fpgamgr_program_finish();
>>> +		if (status)
>>> +			return status;
>>> +
>>> +		config_pins(gd->fdt_blob, "fpga");
>>> +		puts("FPGA: Enter user mode.\n");
>>> +	} else {
>>> +		debug("FPGA: Config Error: Unsupported bitstream
>>> type.\n");
>>> +		return -ENOEXEC;
>>> +	}
>>> +
>>> +	return (int)total_sizeof_image;
>>> +}
>>> +#endif
>>> +
>>> +/* This function is used to load the core bitstream from the
>>> OCRAM. */
>>>  int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t
>>> rbf_size)
>>>  {
>>> -	int status;
>>> +	unsigned long status;
>>> +	struct rbf_info rbfinfo;
>>>  
>>> -	/* disable all signals from hps peripheral controller to
>>> fpga */
>>> +	memset(&rbfinfo, 0, sizeof(rbfinfo));
>>> +
>>> +	/* Disable all signals from hps peripheral controller to
>>> fpga */
>>>  	writel(0, &system_manager_base->fpgaintf_en_global);
>>>  
>>> -	/* disable all axi bridge (hps2fpga, lwhps2fpga &
>>> fpga2hps) */
>>> +	/* Disable all axi bridge (hps2fpga, lwhps2fpga &
>>> fpga2hps) */
>>>  	socfpga_bridges_reset();
>>>  
>>> -	/* Initialize the FPGA Manager */
>>> -	status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
>>> -	if (status)
>>> -		return status;
>>> +	/* Getting info about bitstream types */
>>> +	get_rbf_image_info(&rbfinfo, (u16 *)rbf_data);
>>> +
>>> +	if (rbfinfo.section == periph_section) {
>>> +		/* Initialize the FPGA Manager */
>>> +		status = fpgamgr_program_init((u32 *)rbf_data,
>>> rbf_size);
>>> +		if (status)
>>> +			return status;
>>> +	}
>>> +
>>> +	if (rbfinfo.section == core_section &&
>>> +		!(is_fpgamgr_early_user_mode() &&
>>> !is_fpgamgr_user_mode())) {
>>> +		debug("FPGA : Must be in early release mode to
>>> program ");
>>> +		debug("core bitstream.\n");
>>> +		return 0;
>>> +	}
>>>  
>>> -	/* Write the RBF data to FPGA Manager */
>>> +	/* Write the bitstream to FPGA Manager */
>>>  	fpgamgr_program_write(rbf_data, rbf_size);
>>>  
>>> -	return fpgamgr_program_finish();
>>> +	status = fpgamgr_program_finish();
>>> +	if (status) {
>>> +		config_pins(gd->fdt_blob, "fpga");
>>> +		puts("FPGA: Enter user mode.\n");
>>> +	}
>>> +
>>> +	return status;
>>>  }


-- 
Best regards,
Marek Vasut

  reply	other threads:[~2019-02-05  8:41 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-31 14:51 [U-Boot] [PATCH v7 0/7] Add support for loading FPGA bitstream tien.fong.chee at intel.com
2019-01-31 14:51 ` [U-Boot] [PATCH v7 1/7] ARM: socfpga: Description on FPGA bitstream type and file name for Arria 10 tien.fong.chee at intel.com
2019-01-31 14:54   ` Marek Vasut
2019-02-01  3:48     ` Chee, Tien Fong
2019-02-01  8:25       ` Marek Vasut
2019-02-01 16:02         ` Chee, Tien Fong
2019-02-01 20:02           ` Dalon L Westergreen
2019-02-01 20:29             ` Dalon L Westergreen
2019-02-02  2:37               ` Chee, Tien Fong
2019-02-05  8:46           ` Marek Vasut
2019-02-11  5:36             ` Chee, Tien Fong
2019-02-11 11:01               ` Marek Vasut
2019-02-11 16:33                 ` Dalon L Westergreen
2019-02-11 17:01                 ` Chee, Tien Fong
2019-02-11 17:19                   ` Westergreen, Dalon
2019-02-12  9:35                     ` Chee, Tien Fong
2019-02-12  9:43                       ` Marek Vasut
2019-02-12 10:13                         ` Chee, Tien Fong
2019-02-12 10:17                           ` Marek Vasut
2019-02-12 13:49                             ` Dalon L Westergreen
2019-02-12 14:06                               ` Chee, Tien Fong
2019-01-31 14:51 ` [U-Boot] [PATCH v7 2/7] ARM: socfpga: Add default FPGA bitstream fitImage for Arria10 SoCDK tien.fong.chee at intel.com
2019-01-31 14:54   ` Marek Vasut
2019-02-01  3:59     ` Chee, Tien Fong
2019-02-01  8:29       ` Marek Vasut
2019-02-01 16:50         ` Chee, Tien Fong
2019-02-05  8:51           ` Marek Vasut
2019-02-11  6:23             ` Chee, Tien Fong
2019-02-11 11:06               ` Marek Vasut
2019-02-11 16:20                 ` Chee, Tien Fong
2019-01-31 14:51 ` [U-Boot] [PATCH v7 3/7] ARM: socfpga: Add FPGA drivers for Arria 10 FPGA bitstream loading tien.fong.chee at intel.com
2019-01-31 14:55   ` Marek Vasut
2019-02-01  4:04     ` Chee, Tien Fong
2019-02-01  8:29       ` Marek Vasut
2019-02-01 16:50         ` Chee, Tien Fong
2019-02-13  8:22         ` Chee, Tien Fong
2019-02-13 12:00           ` Marek Vasut
2019-02-13 12:15             ` Chee, Tien Fong
2019-02-13 12:34               ` Marek Vasut
2019-02-01 20:12   ` Dalon L Westergreen
2019-02-02  3:27     ` Chee, Tien Fong
2019-02-05  8:41       ` Marek Vasut [this message]
2019-02-11 11:19         ` Chee, Tien Fong
2019-01-31 14:51 ` [U-Boot] [PATCH v7 4/7] ARM: socfpga: Add the configuration for FPGA SoCFPGA A10 SoCDK tien.fong.chee at intel.com
2019-01-31 14:57   ` Marek Vasut
2019-02-01  4:07     ` Chee, Tien Fong
2019-01-31 14:51 ` [U-Boot] [PATCH v7 5/7] spl : socfpga: Implement fpga bitstream loading with socfpga loadfs tien.fong.chee at intel.com
2019-01-31 14:51 ` [U-Boot] [PATCH v7 6/7] ARM: socfpga: Synchronize the configuration for A10 SoCDK tien.fong.chee at intel.com
2019-01-31 14:51 ` [U-Boot] [PATCH v7 7/7] ARM: socfpga: Increase Malloc pool size to support FAT filesystem in SPL tien.fong.chee at intel.com
2019-01-31 14:58   ` Marek Vasut
2019-02-01  4:11     ` Chee, Tien Fong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=052e84aa-7043-1508-eabb-b0e84cd4a687@denx.de \
    --to=marex@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.