]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/fpga/zynqpl.c
Merge git://git.denx.de/u-boot-spi
[people/ms/u-boot.git] / drivers / fpga / zynqpl.c
index 572c0784714d8addf0e3ec41e08b36ee44d228b9..2ff716c25228f513fe09fdbc5346caeeed3ff8d2 100644 (file)
@@ -8,7 +8,9 @@
  */
 
 #include <common.h>
+#include <console.h>
 #include <asm/io.h>
+#include <fs.h>
 #include <zynqpl.h>
 #include <linux/sizes.h>
 #include <asm/arch/hardware.h>
 #define CONFIG_SYS_FPGA_PROG_TIME      (CONFIG_SYS_HZ * 4) /* 4 s */
 #endif
 
-static int zynq_info(xilinx_desc *desc)
-{
-       return FPGA_SUCCESS;
-}
-
 #define DUMMY_WORD     0xffffffff
 
 /* Xilinx binary format header */
@@ -194,7 +191,7 @@ static int zynq_dma_transfer(u32 srcbuf, u32 srclen, u32 dstbuf, u32 dstlen)
        return FPGA_SUCCESS;
 }
 
-static int zynq_dma_xfer_init(u32 partialbit)
+static int zynq_dma_xfer_init(bitstream_type bstype)
 {
        u32 status, control, isr_status;
        unsigned long ts;
@@ -202,7 +199,7 @@ static int zynq_dma_xfer_init(u32 partialbit)
        /* Clear loopback bit */
        clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
 
-       if (!partialbit) {
+       if (bstype != BIT_PARTIAL) {
                zynq_slcr_devcfg_disable();
 
                /* Setting PCFG_PROG_B signal to high */
@@ -322,16 +319,11 @@ static u32 *zynq_align_dma_buffer(u32 *buf, u32 len, u32 swap)
 
 static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
                                   size_t bsize, u32 blocksize, u32 *swap,
-                                  u32 *partialbit)
+                                  bitstream_type *bstype)
 {
        u32 *buf_start;
        u32 diff;
 
-       /* Detect if we are going working with partial or full bitstream */
-       if (bsize != desc->size) {
-               printf("%s: Working with partial bitstream\n", __func__);
-               *partialbit = 1;
-       }
        buf_start = check_data((u8 *)buf, blocksize, swap);
 
        if (!buf_start)
@@ -351,7 +343,7 @@ static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
                return FPGA_FAIL;
        }
 
-       if (zynq_dma_xfer_init(*partialbit))
+       if (zynq_dma_xfer_init(*bstype))
                return FPGA_FAIL;
 
        return 0;
@@ -361,7 +353,6 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
                     bitstream_type bstype)
 {
        unsigned long ts; /* Timestamp */
-       u32 partialbit = 0;
        u32 isr_status, swap;
 
        /*
@@ -369,7 +360,7 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
         * in chunks
         */
        if (zynq_validate_bitstream(desc, buf, bsize, bsize, &swap,
-                                   &partialbit))
+                                   &bstype))
                return FPGA_FAIL;
 
        buf = zynq_align_dma_buffer((u32 *)buf, bsize, swap);
@@ -398,19 +389,96 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
 
        debug("%s: FPGA config done\n", __func__);
 
-       if (!partialbit)
+       if (bstype != BIT_PARTIAL)
                zynq_slcr_devcfg_enable();
 
        return FPGA_SUCCESS;
 }
 
-static int zynq_dump(xilinx_desc *desc, const void *buf, size_t bsize)
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+                      fpga_fs_info *fsinfo)
 {
-       return FPGA_FAIL;
+       unsigned long ts; /* Timestamp */
+       u32 isr_status, swap;
+       u32 partialbit = 0;
+       loff_t blocksize, actread;
+       loff_t pos = 0;
+       int fstype;
+       char *interface, *dev_part, *filename;
+
+       blocksize = fsinfo->blocksize;
+       interface = fsinfo->interface;
+       dev_part = fsinfo->dev_part;
+       filename = fsinfo->filename;
+       fstype = fsinfo->fstype;
+
+       if (fs_set_blk_dev(interface, dev_part, fstype))
+               return FPGA_FAIL;
+
+       if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
+               return FPGA_FAIL;
+
+       if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap,
+                                   &partialbit))
+               return FPGA_FAIL;
+
+       dcache_disable();
+
+       do {
+               buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+               if (zynq_dma_transfer((u32)buf | 1, blocksize >> 2,
+                                     0xffffffff, 0))
+                       return FPGA_FAIL;
+
+               bsize -= blocksize;
+               pos   += blocksize;
+
+               if (fs_set_blk_dev(interface, dev_part, fstype))
+                       return FPGA_FAIL;
+
+               if (bsize > blocksize) {
+                       if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
+                               return FPGA_FAIL;
+               } else {
+                       if (fs_read(filename, (u32) buf, pos, bsize, &actread) < 0)
+                               return FPGA_FAIL;
+               }
+       } while (bsize > blocksize);
+
+       buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+       if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
+               return FPGA_FAIL;
+
+       dcache_enable();
+
+       isr_status = readl(&devcfg_base->int_sts);
+
+       /* Check FPGA configuration completion */
+       ts = get_timer(0);
+       while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
+               if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+                       printf("%s: Timeout wait for FPGA to config\n",
+                              __func__);
+                       return FPGA_FAIL;
+               }
+               isr_status = readl(&devcfg_base->int_sts);
+       }
+
+       debug("%s: FPGA config done\n", __func__);
+
+       if (!partialbit)
+               zynq_slcr_devcfg_enable();
+
+       return FPGA_SUCCESS;
 }
+#endif
 
 struct xilinx_fpga_op zynq_op = {
        .load = zynq_load,
-       .dump = zynq_dump,
-       .info = zynq_info,
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+       .loadfs = zynq_loadfs,
+#endif
 };