diff options
| -rw-r--r-- | drivers/fpga/zynqpl.c | 201 | 
1 files changed, 115 insertions, 86 deletions
| diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 0a134e524c4..ef6d1caca41 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(); | 
