arm64: versal: fpga: Add PL bit stream load support
authorSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Mon, 5 Aug 2019 10:24:59 +0000 (15:54 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 8 Oct 2019 07:11:14 +0000 (09:11 +0200)
This patch adds PL bitstream load support for Versal platform. The PL
bitstream is loaded by making an SMC to ATF which in turn communicates
with platform firmware which configures and loads PL bitstream on to PL.

Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
board/xilinx/versal/board.c
drivers/fpga/Kconfig
drivers/fpga/Makefile
drivers/fpga/versalpl.c [new file with mode: 0644]
drivers/fpga/xilinx.c
include/versalpl.h [new file with mode: 0644]
include/xilinx.h

index b5ddd0c5ad2465096e973a55dea1968464141556..a2b00aa0b66239ee2a1e53c985653732dc044f3a 100644 (file)
 #include <asm/arch/hardware.h>
 #include <dm/device.h>
 #include <dm/uclass.h>
+#include <versalpl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_FPGA_VERSALPL)
+static xilinx_desc versalpl = XILINX_VERSAL_DESC;
+#endif
+
 int board_init(void)
 {
        printf("EL Level:\tEL%d\n", current_el());
 
+#if defined(CONFIG_FPGA_VERSALPL)
+       fpga_init();
+       fpga_add(fpga_xilinx, &versalpl);
+#endif
+
        return 0;
 }
 
index 105a299812f52e2f4ab1f8642e15673f4311490a..fe398a1d4965b33b2ff4e244b61e877c2913ae1f 100644 (file)
@@ -56,6 +56,15 @@ config FPGA_ZYNQMPPL
          Enable FPGA driver for loading bitstream in BIT and BIN format
          on Xilinx Zynq UltraScale+ (ZynqMP) device.
 
+config FPGA_VERSALPL
+       bool "Enable Xilinx FPGA driver for Versal"
+       depends on FPGA_XILINX
+       help
+         Enable FPGA driver for loading bitstream in PDI format on Xilinx
+         Versal device. PDI is a new programmable device image format for
+         Versal. The bitstream will only be generated as PDI for Versal
+         platform.
+
 config FPGA_SPARTAN3
        bool "Enable Spartan3 FPGA driver"
        depends on FPGA_XILINX
index 5a778c10e801aaa6562433eac5b1322fd39e3042..04e6480f202c74c1c937b69383395fe8ed4e1dfa 100644 (file)
@@ -6,6 +6,7 @@
 obj-y += fpga.o
 obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
 obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
+obj-$(CONFIG_FPGA_VERSALPL) += versalpl.o
 obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
 obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
 obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o
diff --git a/drivers/fpga/versalpl.c b/drivers/fpga/versalpl.c
new file mode 100644 (file)
index 0000000..69617a9
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019, Xilinx, Inc,
+ * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+#include <memalign.h>
+#include <versalpl.h>
+
+static ulong versal_align_dma_buffer(ulong *buf, u32 len)
+{
+       ulong *new_buf;
+
+       if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
+               new_buf = (ulong *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
+               memcpy(new_buf, buf, len);
+               buf = new_buf;
+       }
+
+       return (ulong)buf;
+}
+
+static int versal_load(xilinx_desc *desc, const void *buf, size_t bsize,
+                      bitstream_type bstype)
+{
+       ulong bin_buf;
+       int ret;
+       u32 buf_lo, buf_hi;
+       u32 ret_payload[5];
+
+       bin_buf = versal_align_dma_buffer((ulong *)buf, bsize);
+
+       debug("%s called!\n", __func__);
+       flush_dcache_range(bin_buf, bin_buf + bsize);
+
+       buf_lo = lower_32_bits(bin_buf);
+       buf_hi = upper_32_bits(bin_buf);
+
+       ret = versal_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_lo,
+                               buf_hi, 0, ret_payload);
+       if (ret)
+               puts("PL FPGA LOAD fail\n");
+
+       return ret;
+}
+
+struct xilinx_fpga_op versal_op = {
+       .load = versal_load,
+};
index f5135504eeb60748d0e073e678710644fb437489..4b0334b6beb601568212756a808d22f21dd1507d 100644 (file)
@@ -226,7 +226,10 @@ int xilinx_info(xilinx_desc *desc)
                case xilinx_zynqmp:
                        printf("ZynqMP PL\n");
                        break;
-                       /* Add new family types here */
+               case xilinx_versal:
+                       printf("Versal PL\n");
+                       break;
+               /* Add new family types here */
                default:
                        printf ("Unknown family type, %d\n", desc->family);
                }
@@ -257,6 +260,9 @@ int xilinx_info(xilinx_desc *desc)
                case csu_dma:
                        printf("csu_dma configuration interface (ZynqMP)\n");
                        break;
+               case cfi:
+                       printf("CFI configuration interface (Versal)\n");
+                       break;
                        /* Add new interface types here */
                default:
                        printf ("Unsupported interface type, %d\n", desc->iface);
diff --git a/include/versalpl.h b/include/versalpl.h
new file mode 100644 (file)
index 0000000..b94c82e
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2019 Xilinx, Inc,
+ * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
+ */
+
+#ifndef _VERSALPL_H_
+#define _VERSALPL_H_
+
+#include <xilinx.h>
+
+#define VERSAL_PM_LOAD_PDI     0x701
+#define VERSAL_PM_PDI_TYPE     0xF
+
+extern struct xilinx_fpga_op versal_op;
+
+#define XILINX_VERSAL_DESC \
+{ xilinx_versal, csu_dma, 1, &versal_op, 0, &versal_op }
+
+#endif /* _VERSALPL_H_ */
index af40befa52de5999c40913847abb556a42382c82..ab4537becfad10fb5ecaf038619a0c17525f9d58 100644 (file)
@@ -21,6 +21,7 @@ typedef enum {                        /* typedef xilinx_iface */
        slave_selectmap,        /* slave SelectMap (virtex2)            */
        devcfg,                 /* devcfg interface (zynq) */
        csu_dma,                /* csu_dma interface (zynqmp) */
+       cfi,                    /* CFI interface(versal) */
        max_xilinx_iface_type   /* insert all new types before this */
 } xilinx_iface;                        /* end, typedef xilinx_iface */
 
@@ -32,6 +33,7 @@ typedef enum {                        /* typedef xilinx_family */
        xilinx_spartan3,        /* Spartan-III Family */
        xilinx_zynq,            /* Zynq Family */
        xilinx_zynqmp,          /* ZynqMP Family */
+       xilinx_versal,          /* Versal Family */
        max_xilinx_type         /* insert all new types before this */
 } xilinx_family;               /* end, typedef xilinx_family */