From patchwork Thu Mar 12 13:23:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ang, Chee Hong" X-Patchwork-Id: 243587 List-Id: U-Boot discussion From: chee.hong.ang at intel.com (chee.hong.ang at intel.com) Date: Thu, 12 Mar 2020 06:23:52 -0700 Subject: [PATCH v5 15/17] arm: socfpga: stratix10: Add ATF support for FPGA reconfig driver In-Reply-To: <1584019434-45856-1-git-send-email-chee.hong.ang@intel.com> References: <1584019434-45856-1-git-send-email-chee.hong.ang@intel.com> Message-ID: <1584019434-45856-16-git-send-email-chee.hong.ang@intel.com> From: Chee Hong Ang In non-secure mode (EL2), FPGA reconfiguration driver calls the SMC/PSCI services provided by ATF to configure the FPGA. Signed-off-by: Chee Hong Ang --- drivers/fpga/stratix10.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/drivers/fpga/stratix10.c b/drivers/fpga/stratix10.c index d8e3250..d726a1b 100644 --- a/drivers/fpga/stratix10.c +++ b/drivers/fpga/stratix10.c @@ -5,11 +5,148 @@ #include #include -#include #define RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS 60000 #define RECONFIG_STATUS_INTERVAL_DELAY_US 1000000 +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + +#include +#include + +#define BITSTREAM_CHUNK_SIZE 0xFFFF0 +#define RECONFIG_STATUS_POLL_RETRY_MAX 100 + +/* + * Polling the FPGA configuration status. + * Return 0 for success, non-zero for error. + */ +static int reconfig_status_polling_resp(void) +{ + int ret; + unsigned long start = get_timer(0); + + while (1) { + ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, NULL, 0, + NULL, 0); + + if (!ret) + return 0; /* configuration success */ + + if (ret != INTEL_SIP_SMC_STATUS_BUSY) + return ret; + + if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS) + break; /* time out */ + + puts("."); + udelay(RECONFIG_STATUS_INTERVAL_DELAY_US); + } + + return -ETIMEDOUT; +} + +static int send_bistream(const void *rbf_data, size_t rbf_size) +{ + int i; + u64 res_buf[3]; + u64 args[2]; + u32 xfer_count = 0; + int ret, wr_ret = 0, retry = 0; + size_t buf_size = (rbf_size > BITSTREAM_CHUNK_SIZE) ? + BITSTREAM_CHUNK_SIZE : rbf_size; + + while (rbf_size || xfer_count) { + if (!wr_ret && rbf_size) { + args[0] = (u64)rbf_data; + args[1] = buf_size; + wr_ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_WRITE, + args, 2, NULL, 0); + + debug("wr_ret = %d, rbf_data = %p, buf_size = %08lx\n", + wr_ret, rbf_data, buf_size); + + if (wr_ret == INTEL_SIP_SMC_STATUS_REJECTED) + continue; + + rbf_size -= buf_size; + rbf_data += buf_size; + + if (buf_size >= rbf_size) + buf_size = rbf_size; + + xfer_count++; + puts("."); + } else { + ret = invoke_smc( + INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE, + NULL, 0, res_buf, 3); + if (!ret) { + for (i = 0; i < 3; i++) { + if (!res_buf[i]) + break; + xfer_count--; + wr_ret = 0; + retry = 0; + } + } else if (ret != + INTEL_SIP_SMC_STATUS_BUSY) + return ret; + else if (!xfer_count) + return INTEL_SIP_SMC_STATUS_ERROR; + + if (++retry >= RECONFIG_STATUS_POLL_RETRY_MAX) + return -ETIMEDOUT; + + udelay(20000); + } + } + + return 0; +} + +/* + * This is the interface used by FPGA driver. + * Return 0 for success, non-zero for error. + */ +int stratix10_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) +{ + int ret; + + debug("Invoking FPGA_CONFIG_START...\n"); + + ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, NULL, 0, NULL, 0); + + if (ret) { + puts("Failure in RECONFIG mailbox command!\n"); + return ret; + } + + ret = send_bistream(rbf_data, rbf_size); + if (ret) { + printf("Error sending bitstream!\n"); + return ret; + } + + /* Make sure we don't send MBOX_RECONFIG_STATUS too fast */ + udelay(RECONFIG_STATUS_INTERVAL_DELAY_US); + + debug("Polling with MBOX_RECONFIG_STATUS...\n"); + ret = reconfig_status_polling_resp(); + if (ret) { + printf("FPGA reconfiguration failed!"); + return ret; + } + + puts("FPGA reconfiguration OK!\n"); + + return ret; +} + +#else + +#include + static const struct mbox_cfgstat_state { int err_no; const char *error_name; @@ -281,3 +418,5 @@ int stratix10_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) return ret; } + +#endif