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