xref: /rk3399_rockchip-uboot/drivers/fpga/xilinx.c (revision fe84c48eeb8e9cb0b8b80a4c0a53bb089adff9af)
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 
fpga_loadbitstream(int devnum,char * fpgadata,size_t size,bitstream_type bstype)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 	unsigned char *dataptr;
3352c20644SMichal Simek 	unsigned int i;
346631db47SMichal Simek 	const fpga_desc *desc;
35f8c1be98SMichal Simek 	xilinx_desc *xdesc;
3652c20644SMichal Simek 
3752c20644SMichal Simek 	dataptr = (unsigned char *)fpgadata;
386631db47SMichal Simek 	/* Find out fpga_description */
396631db47SMichal Simek 	desc = fpga_validate(devnum, dataptr, 0, (char *)__func__);
406631db47SMichal Simek 	/* Assign xilinx device description */
416631db47SMichal Simek 	xdesc = desc->devdesc;
4252c20644SMichal Simek 
4352c20644SMichal Simek 	/* skip the first bytes of the bitsteam, their meaning is unknown */
4452c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
4552c20644SMichal Simek 	dataptr += 2;
4652c20644SMichal Simek 	dataptr += length;
4752c20644SMichal Simek 
4852c20644SMichal Simek 	/* get design name (identifier, length, string) */
4952c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
5052c20644SMichal Simek 	dataptr += 2;
5152c20644SMichal Simek 	if (*dataptr++ != 0x61) {
5252c20644SMichal Simek 		debug("%s: Design name id not recognized in bitstream\n",
5352c20644SMichal Simek 		      __func__);
5452c20644SMichal Simek 		return FPGA_FAIL;
5552c20644SMichal Simek 	}
5652c20644SMichal Simek 
5752c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
5852c20644SMichal Simek 	dataptr += 2;
59*d863909fSSiva Durga Prasad Paladugu 	printf("  design filename = \"%s\"\n", dataptr);
60*d863909fSSiva Durga Prasad Paladugu 	dataptr += length;
6152c20644SMichal Simek 
6252c20644SMichal Simek 	/* get part number (identifier, length, string) */
6352c20644SMichal Simek 	if (*dataptr++ != 0x62) {
6452c20644SMichal Simek 		printf("%s: Part number id not recognized in bitstream\n",
6552c20644SMichal Simek 		       __func__);
6652c20644SMichal Simek 		return FPGA_FAIL;
6752c20644SMichal Simek 	}
6852c20644SMichal Simek 
6952c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr + 1);
7052c20644SMichal Simek 	dataptr += 2;
716631db47SMichal Simek 
726631db47SMichal Simek 	if (xdesc->name) {
73*d863909fSSiva Durga Prasad Paladugu 		i = (ulong)strstr((char *)dataptr, xdesc->name);
74f7213267SSiva Durga Prasad Paladugu 		if (!i) {
756631db47SMichal Simek 			printf("%s: Wrong bitstream ID for this device\n",
766631db47SMichal Simek 			       __func__);
776631db47SMichal Simek 			printf("%s: Bitstream ID %s, current device ID %d/%s\n",
78*d863909fSSiva Durga Prasad Paladugu 			       __func__, dataptr, devnum, xdesc->name);
796631db47SMichal Simek 			return FPGA_FAIL;
806631db47SMichal Simek 		}
816631db47SMichal Simek 	} else {
82f8c1be98SMichal Simek 		printf("%s: Please fill correct device ID to xilinx_desc\n",
836631db47SMichal Simek 		       __func__);
846631db47SMichal Simek 	}
85*d863909fSSiva Durga Prasad Paladugu 	printf("  part number = \"%s\"\n", dataptr);
86*d863909fSSiva Durga Prasad Paladugu 	dataptr += length;
8752c20644SMichal Simek 
8852c20644SMichal Simek 	/* get date (identifier, length, string) */
8952c20644SMichal Simek 	if (*dataptr++ != 0x63) {
9052c20644SMichal Simek 		printf("%s: Date identifier not recognized in bitstream\n",
9152c20644SMichal Simek 		       __func__);
9252c20644SMichal Simek 		return FPGA_FAIL;
9352c20644SMichal Simek 	}
9452c20644SMichal Simek 
9552c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr+1);
9652c20644SMichal Simek 	dataptr += 2;
97*d863909fSSiva Durga Prasad Paladugu 	printf("  date = \"%s\"\n", dataptr);
98*d863909fSSiva Durga Prasad Paladugu 	dataptr += length;
9952c20644SMichal Simek 
10052c20644SMichal Simek 	/* get time (identifier, length, string) */
10152c20644SMichal Simek 	if (*dataptr++ != 0x64) {
10252c20644SMichal Simek 		printf("%s: Time identifier not recognized in bitstream\n",
10352c20644SMichal Simek 		       __func__);
10452c20644SMichal Simek 		return FPGA_FAIL;
10552c20644SMichal Simek 	}
10652c20644SMichal Simek 
10752c20644SMichal Simek 	length = (*dataptr << 8) + *(dataptr+1);
10852c20644SMichal Simek 	dataptr += 2;
109*d863909fSSiva Durga Prasad Paladugu 	printf("  time = \"%s\"\n", dataptr);
110*d863909fSSiva Durga Prasad Paladugu 	dataptr += length;
11152c20644SMichal Simek 
11252c20644SMichal Simek 	/* get fpga data length (identifier, length) */
11352c20644SMichal Simek 	if (*dataptr++ != 0x65) {
11452c20644SMichal Simek 		printf("%s: Data length id not recognized in bitstream\n",
11552c20644SMichal Simek 		       __func__);
11652c20644SMichal Simek 		return FPGA_FAIL;
11752c20644SMichal Simek 	}
11852c20644SMichal Simek 	swapsize = ((unsigned int) *dataptr << 24) +
11952c20644SMichal Simek 		   ((unsigned int) *(dataptr + 1) << 16) +
12052c20644SMichal Simek 		   ((unsigned int) *(dataptr + 2) << 8) +
12152c20644SMichal Simek 		   ((unsigned int) *(dataptr + 3));
12252c20644SMichal Simek 	dataptr += 4;
12352c20644SMichal Simek 	printf("  bytes in bitstream = %d\n", swapsize);
12452c20644SMichal Simek 
1257a78bd26SMichal Simek 	return fpga_load(devnum, dataptr, swapsize, bstype);
12652c20644SMichal Simek }
12752c20644SMichal Simek 
xilinx_load(xilinx_desc * desc,const void * buf,size_t bsize,bitstream_type bstype)1287a78bd26SMichal Simek int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize,
1297a78bd26SMichal Simek 		bitstream_type bstype)
130c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
131c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
132c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
13314cfc4f3SMichal Simek 		return FPGA_FAIL;
134c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
135c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
1366cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->load) {
1376cd68c81SMichal Simek 		printf("%s: Missing load operation\n", __func__);
1386cd68c81SMichal Simek 		return FPGA_FAIL;
1396cd68c81SMichal Simek 	}
1406cd68c81SMichal Simek 
1417a78bd26SMichal Simek 	return desc->operations->load(desc, buf, bsize, bstype);
142c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
143c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
1441a897668SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOADFS)
xilinx_loadfs(xilinx_desc * desc,const void * buf,size_t bsize,fpga_fs_info * fpga_fsinfo)1451a897668SSiva Durga Prasad Paladugu int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
1461a897668SSiva Durga Prasad Paladugu 		   fpga_fs_info *fpga_fsinfo)
1471a897668SSiva Durga Prasad Paladugu {
1481a897668SSiva Durga Prasad Paladugu 	if (!xilinx_validate(desc, (char *)__func__)) {
1491a897668SSiva Durga Prasad Paladugu 		printf("%s: Invalid device descriptor\n", __func__);
1501a897668SSiva Durga Prasad Paladugu 		return FPGA_FAIL;
1511a897668SSiva Durga Prasad Paladugu 	}
1521a897668SSiva Durga Prasad Paladugu 
1536cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->loadfs) {
1546cd68c81SMichal Simek 		printf("%s: Missing loadfs operation\n", __func__);
1551a897668SSiva Durga Prasad Paladugu 		return FPGA_FAIL;
1566cd68c81SMichal Simek 	}
1571a897668SSiva Durga Prasad Paladugu 
1581a897668SSiva Durga Prasad Paladugu 	return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo);
1591a897668SSiva Durga Prasad Paladugu }
1601a897668SSiva Durga Prasad Paladugu #endif
1611a897668SSiva Durga Prasad Paladugu 
xilinx_dump(xilinx_desc * desc,const void * buf,size_t bsize)162f8c1be98SMichal Simek int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize)
163c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
164c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
165c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
16614cfc4f3SMichal Simek 		return FPGA_FAIL;
167c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
168c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
1696cd68c81SMichal Simek 	if (!desc->operations || !desc->operations->dump) {
1706cd68c81SMichal Simek 		printf("%s: Missing dump operation\n", __func__);
1716cd68c81SMichal Simek 		return FPGA_FAIL;
1726cd68c81SMichal Simek 	}
1736cd68c81SMichal Simek 
17414cfc4f3SMichal Simek 	return desc->operations->dump(desc, buf, bsize);
175c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
176c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
xilinx_info(xilinx_desc * desc)177f8c1be98SMichal Simek int xilinx_info(xilinx_desc *desc)
178c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
179c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
180c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
181c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (xilinx_validate (desc, (char *)__FUNCTION__)) {
182c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Family:        \t");
183c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		switch (desc->family) {
184b625b9aeSMichal Simek 		case xilinx_spartan2:
185c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Spartan-II\n");
186c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
1872a6e3869SMichal Simek 		case xilinx_spartan3:
188c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Spartan-III\n");
189c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
190d9071ce0SMichal Simek 		case xilinx_virtex2:
191c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Virtex-II\n");
192c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
193d5dae85fSMichal Simek 		case xilinx_zynq:
194d5dae85fSMichal Simek 			printf("Zynq PL\n");
195d5dae85fSMichal Simek 			break;
1966b245014SSiva Durga Prasad Paladugu 		case xilinx_zynqmp:
1976b245014SSiva Durga Prasad Paladugu 			printf("ZynqMP PL\n");
1986b245014SSiva Durga Prasad Paladugu 			break;
199c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* Add new family types here */
200c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		default:
201c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Unknown family type, %d\n", desc->family);
202c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
203c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
204c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Interface type:\t");
205c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		switch (desc->iface) {
206c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_serial:
207c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave Serial\n");
208c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
209c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case master_serial:	/* Not used */
210c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Master Serial\n");
211c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
212c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_parallel:
213c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave Parallel\n");
214c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
215c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case jtag_mode:		/* Not used */
216c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("JTAG Mode\n");
217c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
218c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_selectmap:
219c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Slave SelectMap Mode\n");
220c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
221c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case master_selectmap:
222c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Master SelectMap Mode\n");
223c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
224d5dae85fSMichal Simek 		case devcfg:
225d5dae85fSMichal Simek 			printf("Device configuration interface (Zynq)\n");
226d5dae85fSMichal Simek 			break;
2276b245014SSiva Durga Prasad Paladugu 		case csu_dma:
2286b245014SSiva Durga Prasad Paladugu 			printf("csu_dma configuration interface (ZynqMP)\n");
2296b245014SSiva Durga Prasad Paladugu 			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 
241e136eaebSMichal Simek 		if (desc->iface_fns)
242c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
243e136eaebSMichal Simek 		else
244e136eaebSMichal Simek 			printf ("No Device Function Table.\n");
245e136eaebSMichal Simek 
2466cd68c81SMichal Simek 		if (desc->operations && desc->operations->info)
24714cfc4f3SMichal Simek 			desc->operations->info(desc);
248c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
249c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
250c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
251c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
252c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
253c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
254c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
255c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
256c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
257c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
258c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
xilinx_validate(xilinx_desc * desc,char * fn)259f8c1be98SMichal Simek static int xilinx_validate(xilinx_desc *desc, char *fn)
260c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
261472d5460SYork Sun 	int ret_val = false;
262c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
263c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (desc) {
264c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if ((desc->family > min_xilinx_type) &&
265c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(desc->family < max_xilinx_type)) {
266c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((desc->iface > min_xilinx_iface_type) &&
267c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(desc->iface < max_xilinx_iface_type)) {
268c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				if (desc->size) {
269472d5460SYork Sun 					ret_val = true;
270c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				} else
271c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					printf ("%s: NULL part size\n", fn);
272c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} else
273c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%s: Invalid Interface type, %d\n",
274c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						fn, desc->iface);
275c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else
276c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("%s: Invalid family type, %d\n", fn, desc->family);
277c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else
278c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL descriptor!\n", fn);
279c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
280c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
281c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
282