|
@@ -152,70 +152,52 @@ static void *check_data(u8 *buf, size_t bsize, u32 *swap)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
|
|
|
+static int zynq_dma_transfer(u32 srcbuf, u32 srclen, u32 dstbuf, u32 dstlen)
|
|
|
{
|
|
|
- unsigned long ts; /* Timestamp */
|
|
|
- u32 partialbit = 0;
|
|
|
- u32 i, control, isr_status, status, swap, diff;
|
|
|
- u32 *buf_start;
|
|
|
+ unsigned long ts;
|
|
|
+ u32 isr_status;
|
|
|
|
|
|
- /* 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, bsize, &swap);
|
|
|
- if (!buf_start)
|
|
|
- return FPGA_FAIL;
|
|
|
-
|
|
|
- /* Check if data is postpone from start */
|
|
|
- diff = (u32)buf_start - (u32)buf;
|
|
|
- if (diff) {
|
|
|
- printf("%s: Bitstream is not validated yet (diff %x)\n",
|
|
|
- __func__, diff);
|
|
|
- return FPGA_FAIL;
|
|
|
- }
|
|
|
+ /* Set up the transfer */
|
|
|
+ writel((u32)srcbuf, &devcfg_base->dma_src_addr);
|
|
|
+ writel(dstbuf, &devcfg_base->dma_dst_addr);
|
|
|
+ writel(srclen, &devcfg_base->dma_src_len);
|
|
|
+ writel(dstlen, &devcfg_base->dma_dst_len);
|
|
|
|
|
|
- if ((u32)buf < SZ_1M) {
|
|
|
- printf("%s: Bitstream has to be placed up to 1MB (%x)\n",
|
|
|
- __func__, (u32)buf);
|
|
|
- return FPGA_FAIL;
|
|
|
- }
|
|
|
+ isr_status = readl(&devcfg_base->int_sts);
|
|
|
|
|
|
- if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) {
|
|
|
- u32 *new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN);
|
|
|
+ /* Polling the PCAP_INIT status for Set */
|
|
|
+ ts = get_timer(0);
|
|
|
+ while (!(isr_status & DEVCFG_ISR_DMA_DONE)) {
|
|
|
+ if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) {
|
|
|
+ debug("%s: Error: isr = 0x%08X\n", __func__,
|
|
|
+ isr_status);
|
|
|
+ debug("%s: Write count = 0x%08X\n", __func__,
|
|
|
+ readl(&devcfg_base->write_count));
|
|
|
+ debug("%s: Read count = 0x%08X\n", __func__,
|
|
|
+ readl(&devcfg_base->read_count));
|
|
|
|
|
|
- /*
|
|
|
- * This might be dangerous but permits to flash if
|
|
|
- * ARCH_DMA_MINALIGN is greater than header size
|
|
|
- */
|
|
|
- if (new_buf > buf_start) {
|
|
|
- debug("%s: Aligned buffer is after buffer start\n",
|
|
|
- __func__);
|
|
|
- new_buf -= ARCH_DMA_MINALIGN;
|
|
|
+ return FPGA_FAIL;
|
|
|
}
|
|
|
+ if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
|
|
|
+ printf("%s: Timeout wait for DMA to complete\n",
|
|
|
+ __func__);
|
|
|
+ return FPGA_FAIL;
|
|
|
+ }
|
|
|
+ isr_status = readl(&devcfg_base->int_sts);
|
|
|
+ }
|
|
|
|
|
|
- printf("%s: Align buffer at %x to %x(swap %d)\n", __func__,
|
|
|
- (u32)buf_start, (u32)new_buf, swap);
|
|
|
-
|
|
|
- for (i = 0; i < (bsize/4); i++)
|
|
|
- new_buf[i] = load_word(&buf_start[i], swap);
|
|
|
-
|
|
|
- swap = SWAP_DONE;
|
|
|
- buf = new_buf;
|
|
|
- } else if (swap != SWAP_DONE) {
|
|
|
- /* For bitstream which are aligned */
|
|
|
- u32 *new_buf = (u32 *)buf;
|
|
|
+ debug("%s: DMA transfer is done\n", __func__);
|
|
|
|
|
|
- printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
|
|
|
- swap);
|
|
|
+ /* Clear out the DMA status */
|
|
|
+ writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
|
|
|
|
|
|
- for (i = 0; i < (bsize/4); i++)
|
|
|
- new_buf[i] = load_word(&buf_start[i], swap);
|
|
|
+ return FPGA_SUCCESS;
|
|
|
+}
|
|
|
|
|
|
- swap = SWAP_DONE;
|
|
|
- }
|
|
|
+static int zynq_dma_xfer_init(u32 partialbit)
|
|
|
+{
|
|
|
+ u32 status, control, isr_status;
|
|
|
+ unsigned long ts;
|
|
|
|
|
|
/* Clear loopback bit */
|
|
|
clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
|
|
@@ -297,6 +279,83 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
|
|
|
writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status);
|
|
|
}
|
|
|
|
|
|
+ return FPGA_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static u32 *zynq_align_dma_buffer(u32 *buf, u32 len, u32 swap)
|
|
|
+{
|
|
|
+ u32 *new_buf;
|
|
|
+ u32 i;
|
|
|
+
|
|
|
+ if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) {
|
|
|
+ new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This might be dangerous but permits to flash if
|
|
|
+ * ARCH_DMA_MINALIGN is greater than header size
|
|
|
+ */
|
|
|
+ if (new_buf > buf) {
|
|
|
+ debug("%s: Aligned buffer is after buffer start\n",
|
|
|
+ __func__);
|
|
|
+ new_buf -= ARCH_DMA_MINALIGN;
|
|
|
+ }
|
|
|
+ printf("%s: Align buffer at %x to %x(swap %d)\n", __func__,
|
|
|
+ (u32)buf, (u32)new_buf, swap);
|
|
|
+
|
|
|
+ for (i = 0; i < (len/4); i++)
|
|
|
+ new_buf[i] = load_word(&buf[i], swap);
|
|
|
+
|
|
|
+ buf = new_buf;
|
|
|
+ } else if (swap != SWAP_DONE) {
|
|
|
+ /* For bitstream which are aligned */
|
|
|
+ u32 *new_buf = (u32 *)buf;
|
|
|
+
|
|
|
+ printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
|
|
|
+ swap);
|
|
|
+
|
|
|
+ for (i = 0; i < (len/4); i++)
|
|
|
+ new_buf[i] = load_word(&buf[i], swap);
|
|
|
+ }
|
|
|
+
|
|
|
+ return buf;
|
|
|
+}
|
|
|
+
|
|
|
+static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
|
|
|
+{
|
|
|
+ unsigned long ts; /* Timestamp */
|
|
|
+ u32 partialbit = 0;
|
|
|
+ u32 isr_status, swap, diff;
|
|
|
+ u32 *buf_start;
|
|
|
+
|
|
|
+ /* 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, bsize, &swap);
|
|
|
+ if (!buf_start)
|
|
|
+ return FPGA_FAIL;
|
|
|
+
|
|
|
+ /* Check if data is postpone from start */
|
|
|
+ diff = (u32)buf_start - (u32)buf;
|
|
|
+ if (diff) {
|
|
|
+ printf("%s: Bitstream is not validated yet (diff %x)\n",
|
|
|
+ __func__, diff);
|
|
|
+ return FPGA_FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((u32)buf < SZ_1M) {
|
|
|
+ printf("%s: Bitstream has to be placed up to 1MB (%x)\n",
|
|
|
+ __func__, (u32)buf);
|
|
|
+ return FPGA_FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (zynq_dma_xfer_init(partialbit))
|
|
|
+ return FPGA_FAIL;
|
|
|
+
|
|
|
+ buf = zynq_align_dma_buffer((u32 *)buf, bsize, swap);
|
|
|
+
|
|
|
debug("%s: Source = 0x%08X\n", __func__, (u32)buf);
|
|
|
debug("%s: Size = %zu\n", __func__, bsize);
|
|
|
|
|
@@ -304,37 +363,10 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
|
|
|
flush_dcache_range((u32)buf, (u32)buf +
|
|
|
roundup(bsize, ARCH_DMA_MINALIGN));
|
|
|
|
|
|
- /* Set up the transfer */
|
|
|
- writel((u32)buf | 1, &devcfg_base->dma_src_addr);
|
|
|
- writel(0xFFFFFFFF, &devcfg_base->dma_dst_addr);
|
|
|
- writel(bsize >> 2, &devcfg_base->dma_src_len);
|
|
|
- writel(0, &devcfg_base->dma_dst_len);
|
|
|
+ if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
|
|
|
+ return FPGA_FAIL;
|
|
|
|
|
|
isr_status = readl(&devcfg_base->int_sts);
|
|
|
-
|
|
|
- /* Polling the PCAP_INIT status for Set */
|
|
|
- ts = get_timer(0);
|
|
|
- while (!(isr_status & DEVCFG_ISR_DMA_DONE)) {
|
|
|
- if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) {
|
|
|
- debug("%s: Error: isr = 0x%08X\n", __func__,
|
|
|
- isr_status);
|
|
|
- debug("%s: Write count = 0x%08X\n", __func__,
|
|
|
- readl(&devcfg_base->write_count));
|
|
|
- debug("%s: Read count = 0x%08X\n", __func__,
|
|
|
- readl(&devcfg_base->read_count));
|
|
|
-
|
|
|
- return FPGA_FAIL;
|
|
|
- }
|
|
|
- if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
|
|
|
- printf("%s: Timeout wait for DMA to complete\n",
|
|
|
- __func__);
|
|
|
- return FPGA_FAIL;
|
|
|
- }
|
|
|
- isr_status = readl(&devcfg_base->int_sts);
|
|
|
- }
|
|
|
-
|
|
|
- debug("%s: DMA transfer is done\n", __func__);
|
|
|
-
|
|
|
/* Check FPGA configuration completion */
|
|
|
ts = get_timer(0);
|
|
|
while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
|
|
@@ -348,9 +380,6 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
|
|
|
|
|
|
debug("%s: FPGA config done\n", __func__);
|
|
|
|
|
|
- /* Clear out the DMA status */
|
|
|
- writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
|
|
|
-
|
|
|
if (!partialbit)
|
|
|
zynq_slcr_devcfg_enable();
|
|
|
|