summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-socfpga/arria10-xload.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-socfpga/arria10-xload.c')
-rw-r--r--arch/arm/mach-socfpga/arria10-xload.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/arch/arm/mach-socfpga/arria10-xload.c b/arch/arm/mach-socfpga/arria10-xload.c
index e52fd1ed87..db3cc209ee 100644
--- a/arch/arm/mach-socfpga/arria10-xload.c
+++ b/arch/arm/mach-socfpga/arria10-xload.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <asm/sections.h>
#include <debug_ll.h>
@@ -6,12 +8,12 @@
#include <filetype.h>
#include <io.h>
#include <asm/unaligned.h>
-#include <mach/arria10-pinmux.h>
-#include <mach/arria10-regs.h>
-#include <mach/arria10-system-manager.h>
-#include <mach/arria10-fpga.h>
-#include <mach/arria10-xload.h>
-#include <mach/generic.h>
+#include <mach/socfpga/arria10-pinmux.h>
+#include <mach/socfpga/arria10-regs.h>
+#include <mach/socfpga/arria10-system-manager.h>
+#include <mach/socfpga/arria10-fpga.h>
+#include <mach/socfpga/arria10-xload.h>
+#include <mach/socfpga/generic.h>
#include <linux/sizes.h>
int a10_update_bits(unsigned int reg, unsigned int mask,
@@ -351,17 +353,9 @@ int arria10_prepare_mmc(int barebox_part, int rbf_part)
return 0;
}
-int arria10_load_fpga(int offset, int bitstream_size)
+static inline int __arria10_load_fpga(void *buf, uint32_t count, uint32_t size)
{
- void *buf = (void *)0xffe00000 + SZ_256K - 256 - SZ_16K;
int ret;
- uint32_t count;
- uint32_t size = bitstream_size / SECTOR_SIZE;
-
- if (offset)
- offset = offset / SECTOR_SIZE;
-
- count = offset;
arria10_read_blocks(buf, count + bitstream.first_sec, SZ_16K);
@@ -369,23 +363,56 @@ int arria10_load_fpga(int offset, int bitstream_size)
ret = a10_fpga_init(buf);
if (ret)
- hang();
+ return -EAGAIN;
while (count <= size) {
ret = a10_fpga_write(buf, SZ_16K);
if (ret == -ENOSPC)
- break;
+ return -EAGAIN;
+
count += SZ_16K / SECTOR_SIZE;
ret = arria10_read_blocks(buf, count, SZ_16K);
+ // Reading failed, consider this a failed attempt to configure the FPGA and retry
+ if (ret)
+ return -EAGAIN;
}
ret = a10_fpga_write_complete();
if (ret)
- hang();
+ return -EAGAIN;
return 0;
}
+int arria10_load_fpga(int offset, int bitstream_size)
+{
+ int ret;
+ void *buf = (void *)0xffe00000 + SZ_256K - 256 - SZ_16K;
+ uint32_t count;
+ uint32_t size = bitstream_size / SECTOR_SIZE;
+ uint32_t retryCount;
+
+ if (offset)
+ offset = offset / SECTOR_SIZE;
+
+ /* Up to 4 retries have been seen on the Enclustra Mercury AA1+ board, as
+ * FPGA configuration is mandatory to be able to continue the boot, take
+ * some margin and try up to 10 times
+ */
+ for (retryCount = 0; retryCount < 10; ++retryCount) {
+ count = offset;
+
+ ret = __arria10_load_fpga(buf, count, size);
+ if (!ret)
+ return 0;
+ else if (ret == -EAGAIN)
+ continue;
+ }
+
+ hang();
+ return -EIO;
+}
+
void arria10_start_image(int offset)
{
void *buf = (void *)0x0;