[U-Boot] [PATCH v2 8/9] fpga: zynq: Use helper functions for zynq dma

Michal Simek michal.simek at xilinx.com
Wed May 7 15:03:32 CEST 2014


From: Siva Durga Prasad Paladugu <siva.durga.paladugu at xilinx.com>

Use zynq_dma_xfer_init, zynq_align_dma_buffer,
zynq_dma_transfer helper function performing dma
transfers so that the code can be reused easily for
different cases of dma transfer.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

Changes in v2: None

 drivers/fpga/zynqpl.c | 201 +++++++++++++++++++++++++++++---------------------
 1 file changed, 115 insertions(+), 86 deletions(-)

diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index 0a134e524c44..ef6d1caca410 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -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();

--
1.8.2.3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140507/f92ed2cc/attachment.pgp>


More information about the U-Boot mailing list