[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/platform/zynq/fpga.c b/src/bsp/lk/platform/zynq/fpga.c
new file mode 100644
index 0000000..fbdbe8f
--- /dev/null
+++ b/src/bsp/lk/platform/zynq/fpga.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014 Brian Swetland
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <platform/fpga.h>
+#include <trace.h>
+#include <reg.h>
+#include <err.h>
+#include <platform.h>
+#include <kernel/thread.h>
+
+#define LOCAL_TRACE 0
+#define FPGA_TIMEOUT 1000
+
+#define DEVCFG_CTRL         0xF8007000
+#define  PCFG_PROG_B        (1 << 30)
+#define  PCFG_POR_CNT_4K    (1 << 29)
+#define  PCAP_PR            (1 << 27) // 0 = ICAP CFG, 1 = PCAP CFG
+#define  PCAP_MODE          (1 << 26) // 1 = Enable PCAP Interface
+#define DEVCFG_LOCK         0xF8007004
+#define DEVCFG_CFG          0xF8007008
+#define DEVCFG_INT_STS      0xF800700C
+#define  DMA_DONE_INT       (1 << 13)
+#define  PSS_CFG_RESET_B    (1 << 5) // 1 = PL in reset state
+#define  PCFG_DONE_INT      (1 << 2) // 1 = PL successfully programmed
+#define  PCFG_INIT_PE_INT   (1 << 1)
+#define  PCFG_INIT_NE_INT   (1 << 0)
+#define DEVCFG_INT_MASK     0xF8007010
+#define DEVCFG_STATUS       0xF8007014
+#define  PCFG_INIT          (1 << 4) // 1 = ready for bitstream
+#define DEVCFG_DMA_SRC_ADDR 0xF8007018
+#define DEVCFG_DMA_DST_ADDR 0xF800701C
+#define DEVCFG_DMA_SRC_LEN  0xF8007020 // words
+#define DEVCFG_DMA_DST_LEN  0xF8007024 // words
+#define DEVCFG_SW_ID        0xF8007030
+#define DEVCFG_MCTRL        0xF8007080
+#define  PCFG_POR_B         (1 << 8) // 1 = PL is powered on
+#define  INT_PCAP_LPBK      (1 << 4) // 1 = Loopback Enabled
+
+// Per Zynq TRM, 6.4.4
+// 1. wait for PCFG_INIT==1
+// 2. disable loopback
+// 3. set DEVCFG CTRL PCAP_PR and PCAP_MODE
+// 4. set dma src, dst, srclen, dstlen (in that specific order)
+// 5. wait for PCFG_DONE_INT==1
+
+status_t zynq_program_fpga(paddr_t physaddr, size_t length) {
+    LTRACEF("phys 0x%lx, len 0x%zx\n", physaddr, length);
+
+    lk_bigtime_t bt = current_time_hires();
+
+    /* length is in words */
+    length /= 4;
+
+    lk_time_t t;
+
+    t = current_time();
+    while(!(readl(DEVCFG_STATUS) & PCFG_INIT)) {
+        if (current_time() - t > FPGA_TIMEOUT) {
+            TRACEF("timeout waiting for PCFG_INIT\n");
+            return ERR_TIMED_OUT;
+        }
+    }
+    writel(readl(DEVCFG_MCTRL) & (~INT_PCAP_LPBK), DEVCFG_MCTRL);
+    writel(readl(DEVCFG_CTRL) | PCAP_PR | PCAP_MODE, DEVCFG_CTRL);
+    writel(0xffffffff, DEVCFG_INT_STS);
+    writel(physaddr, DEVCFG_DMA_SRC_ADDR);
+    writel(0xFFFFFFFF, DEVCFG_DMA_DST_ADDR);
+    writel(length, DEVCFG_DMA_SRC_LEN);
+    writel(length, DEVCFG_DMA_DST_LEN);
+
+    t = current_time();
+    uint32_t sts = 0;
+    for (;;) {
+        sts = readl(DEVCFG_INT_STS);
+#if LOCAL_TRACE
+        static uint32_t last = 0;
+        if (last != sts) {
+            printf("dsts 0x%x\n", sts);
+        }
+        last = sts;
+#endif
+        if (sts & PCFG_DONE_INT)
+            break;
+
+        if (current_time() - t > FPGA_TIMEOUT) {
+            TRACEF("timeout waiting for PCFG_DONE_INT, DEVCFG_INT_STS is 0x%x\n", sts);
+            return ERR_TIMED_OUT;
+        }
+    }
+
+    bt = current_time_hires() - bt;
+    LTRACEF("fpga program took %llu usecs\n", bt);
+
+    return NO_ERROR;
+}
+
+bool zync_fpga_config_done(void) {
+    return (0 != (readl(DEVCFG_INT_STS) & PCFG_DONE_INT));
+}
+
+void zynq_reset_fpga(void) {
+    writel(readl(DEVCFG_CTRL) & (~PCFG_PROG_B), DEVCFG_CTRL);
+    writel(readl(DEVCFG_CTRL) | PCFG_PROG_B, DEVCFG_CTRL);
+}
+