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