xref: /rk3399_rockchip-uboot/drivers/fpga/xilinx.c (revision 6cd68c811ecb145d4258ce6be99dba3e507b294f)
1c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
2d5dae85fSMichal Simek  * (C) Copyright 2012-2013, Xilinx, Michal Simek
3d5dae85fSMichal Simek  *
4c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
5c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
6c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Keith Outwater, keith_outwater@mvis.com
7c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
9c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
10c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
11c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
12c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *  Xilinx FPGA support
13c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
14c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
15c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
166631db47SMichal Simek #include <fpga.h>
17c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <virtex2.h>
18c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <spartan2.h>
19c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <spartan3.h>
20d5dae85fSMichal Simek #include <zynqpl.h>
21c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
22c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Local Static Functions */
23f8c1be98SMichal Simek static int xilinx_validate(xilinx_desc *desc, char *fn);
24c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
25c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
26c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
277a78bd26SMichal Simek int fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
287a78bd26SMichal Simek 		       bitstream_type bstype)
2952c20644SMichal Simek {
3052c20644SMichal Simek 	unsigned int length;
3152c20644SMichal Simek 	unsigned int swapsize;
3252c20644SMichal Simek 	char buffer[80];
3352c20644SMichal Simek 	unsigned char *dataptr;
3452c20644SMichal Simek 	unsigned int i;
356631db47SMichal Simek 	const fpga_desc *desc;
36f8c1be98SMichal Simek 	xilinx_desc *xdesc;
3752c20644SMichal Simek 
3852c20644SMichal Simek 	dataptr = (unsigned char *)fpgadata;
396631db47SMichal Simek 	/* Find out fpga_description */
406631db47SMichal Simek 	desc = fpga_validate(devnum, dataptr, 0, (char *)__func__);
416631db47SMichal Simek 	/* Assign xilinx device description */
426631db47SMichal Simek 	xdesc = desc->devdesc;
4352c20644SMichal Simek 
4452c20644SMichal Simek 	/* skip the first bytes of the bitsteam, their meaning is unknown */
4552c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
4652c20644SMichal Simek 	dataptr += 2;
4752c20644SMichal Simek 	dataptr += length;
4852c20644SMichal Simek 
4952c20644SMichal Simek 	/* get design name (identifier, length, string) */
5052c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
5152c20644SMichal Simek 	dataptr += 2;
5252c20644SMichal Simek 	if (*dataptr++ != 0x61) {
5352c20644SMichal Simek 		debug("%s: Design name id not recognized in bitstream\n",
5452c20644SMichal Simek 		      __func__);
5552c20644SMichal Simek 		return FPGA_FAIL;
5652c20644SMichal Simek 	}
5752c20644SMichal Simek 
5852c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
5952c20644SMichal Simek 	dataptr += 2;
6052c20644SMichal Simek 	for (i = 0; i < length; i++)
6152c20644SMichal Simek 		buffer[i] = *dataptr++;
6252c20644SMichal Simek 
6352c20644SMichal Simek 	printf("  design filename = \"%s\"\n", buffer);
6452c20644SMichal Simek 
6552c20644SMichal Simek 	/* get part number (identifier, length, string) */
6652c20644SMichal Simek 	if (*dataptr++ != 0x62) {
6752c20644SMichal Simek 		printf("%s: Part number id not recognized in bitstream\n",
6852c20644SMichal Simek 		       __func__);
6952c20644SMichal Simek 		return FPGA_FAIL;
7052c20644SMichal Simek 	}
7152c20644SMichal Simek 
7252c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
7352c20644SMichal Simek 	dataptr += 2;
7452c20644SMichal Simek 	for (i = 0; i < length; i++)
7552c20644SMichal Simek 		buffer[i] = *dataptr++;
766631db47SMichal Simek 
776631db47SMichal Simek 	if (xdesc->name) {
786631db47SMichal Simek 		i = strncmp(buffer, xdesc->name, strlen(xdesc->name));
796631db47SMichal Simek 		if (i) {
806631db47SMichal Simek 			printf("%s: Wrong bitstream ID for this device\n",
816631db47SMichal Simek 			       __func__);
826631db47SMichal Simek 			printf("%s: Bitstream ID %s, current device ID %d/%s\n",
836631db47SMichal Simek 			       __func__, buffer, devnum, xdesc->name);
846631db47SMichal Simek 			return FPGA_FAIL;
856631db47SMichal Simek 		}
866631db47SMichal Simek 	} else {
87f8c1be98SMichal Simek 		printf("%s: Please fill correct device ID to xilinx_desc\n",
886631db47SMichal Simek 		       __func__);
896631db47SMichal Simek 	}
9052c20644SMichal Simek 	printf("  part number = \"%s\"\n", buffer);
9152c20644SMichal Simek 
9252c20644SMichal Simek 	/* get date (identifier, length, string) */
9352c20644SMichal Simek 	if (*dataptr++ != 0x63) {
9452c20644SMichal Simek 		printf("%s: Date identifier not recognized in bitstream\n",
9552c20644SMichal Simek 		       __func__);
9652c20644SMichal Simek 		return FPGA_FAIL;
9752c20644SMichal Simek 	}
9852c20644SMichal Simek 
9952c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr+1);
10052c20644SMichal Simek 	dataptr += 2;
10152c20644SMichal Simek 	for (i = 0; i < length; i++)
10252c20644SMichal Simek 		buffer[i] = *dataptr++;
10352c20644SMichal Simek 	printf("  date = \"%s\"\n", buffer);
10452c20644SMichal Simek 
10552c20644SMichal Simek 	/* get time (identifier, length, string) */
10652c20644SMichal Simek 	if (*dataptr++ != 0x64) {
10752c20644SMichal Simek 		printf("%s: Time identifier not recognized in bitstream\n",
10852c20644SMichal Simek 		       __func__);
10952c20644SMichal Simek 		return FPGA_FAIL;
11052c20644SMichal Simek 	}
11152c20644SMichal Simek 
11252c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr+1);
11352c20644SMichal Simek 	dataptr += 2;
11452c20644SMichal Simek 	for (i = 0; i < length; i++)
11552c20644SMichal Simek 		buffer[i] = *dataptr++;
11652c20644SMichal Simek 	printf("  time = \"%s\"\n", buffer);
11752c20644SMichal Simek 
11852c20644SMichal Simek 	/* get fpga data length (identifier, length) */
11952c20644SMichal Simek 	if (*dataptr++ != 0x65) {
12052c20644SMichal Simek 		printf("%s: Data length id not recognized in bitstream\n",
12152c20644SMichal Simek 		       __func__);
12252c20644SMichal Simek 		return FPGA_FAIL;
12352c20644SMichal Simek 	}
12452c20644SMichal Simek 	swapsize = ((unsigned int) *dataptr << 24) +
12552c20644SMichal Simek 		   ((unsigned int) *(dataptr + 1) << 16) +
12652c20644SMichal Simek 		   ((unsigned int) *(dataptr + 2) << 8) +
12752c20644SMichal Simek 		   ((unsigned int) *(dataptr + 3));
12852c20644SMichal Simek 	dataptr += 4;
12952c20644SMichal Simek 	printf("  bytes in bitstream = %d\n", swapsize);
13052c20644SMichal Simek 
1317a78bd26SMichal Simek 	return fpga_load(devnum, dataptr, swapsize, bstype);
13252c20644SMichal Simek }
13352c20644SMichal Simek 
1347a78bd26SMichal Simek int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize,
1357a78bd26SMichal Simek 		bitstream_type bstype)
136c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
137c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
138c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
13914cfc4f3SMichal Simek 		return FPGA_FAIL;
140c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
141c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
142*6cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->load) {
143*6cd68c81SMichal Simek 		printf("%s: Missing load operation\n", __func__);
144*6cd68c81SMichal Simek 		return FPGA_FAIL;
145*6cd68c81SMichal Simek 	}
146*6cd68c81SMichal Simek 
1477a78bd26SMichal Simek 	return desc->operations->load(desc, buf, bsize, bstype);
148c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
149c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
1501a897668SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOADFS)
1511a897668SSiva Durga Prasad Paladugu int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
1521a897668SSiva Durga Prasad Paladugu 		   fpga_fs_info *fpga_fsinfo)
1531a897668SSiva Durga Prasad Paladugu {
1541a897668SSiva Durga Prasad Paladugu 	if (!xilinx_validate(desc, (char *)__func__)) {
1551a897668SSiva Durga Prasad Paladugu 		printf("%s: Invalid device descriptor\n", __func__);
1561a897668SSiva Durga Prasad Paladugu 		return FPGA_FAIL;
1571a897668SSiva Durga Prasad Paladugu 	}
1581a897668SSiva Durga Prasad Paladugu 
159*6cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->loadfs) {
160*6cd68c81SMichal Simek 		printf("%s: Missing loadfs operation\n", __func__);
1611a897668SSiva Durga Prasad Paladugu 		return FPGA_FAIL;
162*6cd68c81SMichal Simek 	}
1631a897668SSiva Durga Prasad Paladugu 
1641a897668SSiva Durga Prasad Paladugu 	return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo);
1651a897668SSiva Durga Prasad Paladugu }
1661a897668SSiva Durga Prasad Paladugu #endif
1671a897668SSiva Durga Prasad Paladugu 
168f8c1be98SMichal Simek int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize)
169c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
170c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
171c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
17214cfc4f3SMichal Simek 		return FPGA_FAIL;
173c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
174c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
175*6cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->dump) {
176*6cd68c81SMichal Simek 		printf("%s: Missing dump operation\n", __func__);
177*6cd68c81SMichal Simek 		return FPGA_FAIL;
178*6cd68c81SMichal Simek 	}
179*6cd68c81SMichal Simek 
18014cfc4f3SMichal Simek 	return desc->operations->dump(desc, buf, bsize);
181c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
182c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
183f8c1be98SMichal Simek int xilinx_info(xilinx_desc *desc)
184c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
185c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
186c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
187c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (xilinx_validate (desc, (char *)__FUNCTION__)) {
188c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Family:        \t");
189c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		switch (desc->family) {
190b625b9aeSMichal Simek 		case xilinx_spartan2:
191c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Spartan-II\n");
192c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
1932a6e3869SMichal Simek 		case xilinx_spartan3:
194c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Spartan-III\n");
195c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
196d9071ce0SMichal Simek 		case xilinx_virtex2:
197c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Virtex-II\n");
198c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
199d5dae85fSMichal Simek 		case xilinx_zynq:
200d5dae85fSMichal Simek 			printf("Zynq PL\n");
201d5dae85fSMichal Simek 			break;
202c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* Add new family types here */
203c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		default:
204c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Unknown family type, %d\n", desc->family);
205c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
206c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
207c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Interface type:\t");
208c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		switch (desc->iface) {
209c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_serial:
210c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave Serial\n");
211c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
212c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case master_serial:	/* Not used */
213c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Master Serial\n");
214c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
215c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_parallel:
216c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave Parallel\n");
217c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
218c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case jtag_mode:		/* Not used */
219c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("JTAG Mode\n");
220c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
221c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_selectmap:
222c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave SelectMap Mode\n");
223c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
224c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case master_selectmap:
225c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Master SelectMap Mode\n");
226c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
227d5dae85fSMichal Simek 		case devcfg:
228d5dae85fSMichal Simek 			printf("Device configuration interface (Zynq)\n");
229d5dae85fSMichal Simek 			break;
230c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* Add new interface types here */
231c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		default:
232c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Unsupported interface type, %d\n", desc->iface);
233c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
234c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
235ddc94378SSimon Glass 		printf("Device Size:   \t%zd bytes\n"
236c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		       "Cookie:        \t0x%x (%d)\n",
237c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		       desc->size, desc->cookie, desc->cookie);
2386631db47SMichal Simek 		if (desc->name)
2396631db47SMichal Simek 			printf("Device name:   \t%s\n", desc->name);
240c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
241c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (desc->iface_fns) {
242c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
243*6cd68c81SMichal Simek 			if (desc->operations && desc->operations->info)
24414cfc4f3SMichal Simek 				desc->operations->info(desc);
245c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else
246c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("No Device Function Table.\n");
247c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
248c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
249c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
250c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
251c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
252c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
253c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
254c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
255c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
256c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
257c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
258f8c1be98SMichal Simek static int xilinx_validate(xilinx_desc *desc, char *fn)
259c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
260472d5460SYork Sun 	int ret_val = false;
261c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
262c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (desc) {
263c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if ((desc->family > min_xilinx_type) &&
264c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(desc->family < max_xilinx_type)) {
265c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((desc->iface > min_xilinx_iface_type) &&
266c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(desc->iface < max_xilinx_iface_type)) {
267c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				if (desc->size) {
268472d5460SYork Sun 					ret_val = true;
269c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				} else
270c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					printf ("%s: NULL part size\n", fn);
271c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} else
272c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%s: Invalid Interface type, %d\n",
273c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						fn, desc->iface);
274c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else
275c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("%s: Invalid family type, %d\n", fn, desc->family);
276c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else
277c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL descriptor!\n", fn);
278c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
279c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
280c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
281