diff options
Diffstat (limited to 'drivers/fpga')
| -rw-r--r-- | drivers/fpga/Makefile | 1 | ||||
| -rw-r--r-- | drivers/fpga/fpga.c | 225 | ||||
| -rw-r--r-- | drivers/fpga/xilinx.c | 146 | ||||
| -rw-r--r-- | drivers/fpga/zynqpl.c | 355 | 
4 files changed, 609 insertions, 118 deletions
| diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index b48f623c1..0b51dcdef 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -30,6 +30,7 @@ COBJS-y += fpga.o  COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o  COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o  COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o +COBJS-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o  COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o  COBJS-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o  ifdef CONFIG_FPGA_ALTERA diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 26d244354..f70bff6ed 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -22,122 +22,99 @@   *   */ -/* - *  Generic FPGA support - */ +/* Generic FPGA support */  #include <common.h>             /* core U-Boot definitions */  #include <xilinx.h>             /* xilinx specific definitions */  #include <altera.h>             /* altera specific definitions */  #include <lattice.h> -#if 0 -#define FPGA_DEBUG              /* define FPGA_DEBUG to get debug messages */ -#endif -  /* Local definitions */  #ifndef CONFIG_MAX_FPGA_DEVICES  #define CONFIG_MAX_FPGA_DEVICES		5  #endif -/* Enable/Disable debug console messages */ -#ifdef FPGA_DEBUG -#define	PRINTF(fmt,args...)	printf (fmt ,##args) -#else -#define	PRINTF(fmt,args...) -#endif -  /* Local static data */  static int next_desc = FPGA_INVALID_DEVICE;  static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES]; -/* Local static functions */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum ); -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate(int devnum, const void *buf, -					 size_t bsize, char *fn ); -static int fpga_dev_info( int devnum ); - - -/* ------------------------------------------------------------------------- */ - -/* fpga_no_sup +/* + * fpga_no_sup   * 'no support' message function   */ -static void fpga_no_sup( char *fn, char *msg ) +static void fpga_no_sup(char *fn, char *msg)  { -	if ( fn && msg ) { -		printf( "%s: No support for %s.\n", fn, msg); -	} else if ( msg ) { -		printf( "No support for %s.\n", msg); -	} else { -		printf( "No FPGA suport!\n"); -	} +	if (fn && msg) +		printf("%s: No support for %s.\n", fn, msg); +	else if (msg) +		printf("No support for %s.\n", msg); +	else +		printf("No FPGA suport!\n");  }  /* fpga_get_desc   *	map a device number to a descriptor   */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum ) +static const fpga_desc *const fpga_get_desc(int devnum)  { -	fpga_desc *desc = (fpga_desc * )NULL; +	fpga_desc *desc = (fpga_desc *)NULL; -	if (( devnum >= 0 ) && (devnum < next_desc )) { +	if ((devnum >= 0) && (devnum < next_desc)) {  		desc = &desc_table[devnum]; -		PRINTF( "%s: found fpga descriptor #%d @ 0x%p\n", -				__FUNCTION__, devnum, desc ); +		debug("%s: found fpga descriptor #%d @ 0x%p\n", +		      __func__, devnum, desc);  	}  	return desc;  } - -/* fpga_validate +/* + * fpga_validate   *	generic parameter checking code   */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate(int devnum, const void *buf, -					 size_t bsize, char *fn ) +const fpga_desc *const fpga_validate(int devnum, const void *buf, +				     size_t bsize, char *fn)  { -	fpga_desc * desc = fpga_get_desc( devnum ); +	const fpga_desc *desc = fpga_get_desc(devnum); -	if ( !desc ) { -		printf( "%s: Invalid device number %d\n", fn, devnum ); -	} +	if (!desc) +		printf("%s: Invalid device number %d\n", fn, devnum); -	if ( !buf ) { -		printf( "%s: Null buffer.\n", fn ); +	if (!buf) { +		printf("%s: Null buffer.\n", fn);  		return (fpga_desc * const)NULL;  	}  	return desc;  } - -/* fpga_dev_info +/* + * fpga_dev_info   *	generic multiplexing code   */ -static int fpga_dev_info( int devnum ) +static int fpga_dev_info(int devnum)  { -	int ret_val = FPGA_FAIL;           /* assume failure */ -	const fpga_desc * const desc = fpga_get_desc( devnum ); +	int ret_val = FPGA_FAIL; /* assume failure */ +	const fpga_desc * const desc = fpga_get_desc(devnum); -	if ( desc ) { -		PRINTF( "%s: Device Descriptor @ 0x%p\n", -				__FUNCTION__, desc->devdesc ); +	if (desc) { +		debug("%s: Device Descriptor @ 0x%p\n", +		      __func__, desc->devdesc); -		switch ( desc->devtype ) { +		switch (desc->devtype) {  		case fpga_xilinx:  #if defined(CONFIG_FPGA_XILINX) -			printf( "Xilinx Device\nDescriptor @ 0x%p\n", desc ); -			ret_val = xilinx_info( desc->devdesc ); +			printf("Xilinx Device\nDescriptor @ 0x%p\n", desc); +			ret_val = xilinx_info(desc->devdesc);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); +			fpga_no_sup((char *)__func__, "Xilinx devices");  #endif  			break;  		case fpga_altera:  #if defined(CONFIG_FPGA_ALTERA) -			printf( "Altera Device\nDescriptor @ 0x%p\n", desc ); -			ret_val = altera_info( desc->devdesc ); +			printf("Altera Device\nDescriptor @ 0x%p\n", desc); +			ret_val = altera_info(desc->devdesc);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); +			fpga_no_sup((char *)__func__, "Altera devices");  #endif  			break;  		case fpga_lattice: @@ -145,171 +122,183 @@ static int fpga_dev_info( int devnum )  			printf("Lattice Device\nDescriptor @ 0x%p\n", desc);  			ret_val = lattice_info(desc->devdesc);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); +			fpga_no_sup((char *)__func__, "Lattice devices");  #endif  			break;  		default: -			printf( "%s: Invalid or unsupported device type %d\n", -					__FUNCTION__, desc->devtype ); +			printf("%s: Invalid or unsupported device type %d\n", +			       __func__, desc->devtype);  		}  	} else { -		printf( "%s: Invalid device number %d\n", -			__FUNCTION__, devnum ); +		printf("%s: Invalid device number %d\n", __func__, devnum);  	}  	return ret_val;  } - -/* ------------------------------------------------------------------------- */ -/* fgpa_init is usually called from misc_init_r() and MUST be called +/* + * fgpa_init is usually called from misc_init_r() and MUST be called   * before any of the other fpga functions are used.   */  void fpga_init(void)  {  	next_desc = 0; -	memset( desc_table, 0, sizeof(desc_table)); +	memset(desc_table, 0, sizeof(desc_table)); -	PRINTF( "%s: CONFIG_FPGA = 0x%x\n", __FUNCTION__, CONFIG_FPGA ); +	debug("%s\n", __func__);  } -/* fpga_count +/* + * fpga_count   * Basic interface function to get the current number of devices available.   */ -int fpga_count( void ) +int fpga_count(void)  {  	return next_desc;  } -/* fpga_add +/* + * fpga_add   *	Add the device descriptor to the device table.   */ -int fpga_add( fpga_type devtype, void *desc ) +int fpga_add(fpga_type devtype, void *desc)  {  	int devnum = FPGA_INVALID_DEVICE; -	if ( next_desc  < 0 ) { -		printf( "%s: FPGA support not initialized!\n", __FUNCTION__ ); -	} else if (( devtype > fpga_min_type ) && ( devtype < fpga_undefined )) { -		if ( desc ) { -			if ( next_desc < CONFIG_MAX_FPGA_DEVICES ) { +	if (next_desc < 0) { +		printf("%s: FPGA support not initialized!\n", __func__); +	} else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) { +		if (desc) { +			if (next_desc < CONFIG_MAX_FPGA_DEVICES) {  				devnum = next_desc;  				desc_table[next_desc].devtype = devtype;  				desc_table[next_desc++].devdesc = desc;  			} else { -				printf( "%s: Exceeded Max FPGA device count\n", __FUNCTION__ ); +				printf("%s: Exceeded Max FPGA device count\n", +				       __func__);  			}  		} else { -			printf( "%s: NULL device descriptor\n", __FUNCTION__ ); +			printf("%s: NULL device descriptor\n", __func__);  		}  	} else { -		printf( "%s: Unsupported FPGA type %d\n", __FUNCTION__, devtype ); +		printf("%s: Unsupported FPGA type %d\n", __func__, devtype);  	}  	return devnum;  }  /* - *	Generic multiplexing code + * Convert bitstream data and load into the fpga + */ +int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size) +{ +	printf("Bitstream support not implemented for this FPGA device\n"); +	return FPGA_FAIL; +} + +/* + * Generic multiplexing code   */  int fpga_load(int devnum, const void *buf, size_t bsize)  {  	int ret_val = FPGA_FAIL;           /* assume failure */ -	fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ ); +	const fpga_desc *desc = fpga_validate(devnum, buf, bsize, +					      (char *)__func__); -	if ( desc ) { -		switch ( desc->devtype ) { +	if (desc) { +		switch (desc->devtype) {  		case fpga_xilinx:  #if defined(CONFIG_FPGA_XILINX) -			ret_val = xilinx_load( desc->devdesc, buf, bsize ); +			ret_val = xilinx_load(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); +			fpga_no_sup((char *)__func__, "Xilinx devices");  #endif  			break;  		case fpga_altera:  #if defined(CONFIG_FPGA_ALTERA) -			ret_val = altera_load( desc->devdesc, buf, bsize ); +			ret_val = altera_load(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); +			fpga_no_sup((char *)__func__, "Altera devices");  #endif  			break;  		case fpga_lattice:  #if defined(CONFIG_FPGA_LATTICE)  			ret_val = lattice_load(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); +			fpga_no_sup((char *)__func__, "Lattice devices");  #endif  			break;  		default: -			printf( "%s: Invalid or unsupported device type %d\n", -				__FUNCTION__, desc->devtype ); +			printf("%s: Invalid or unsupported device type %d\n", +			       __func__, desc->devtype);  		}  	}  	return ret_val;  } -/* fpga_dump +/* + * fpga_dump   *	generic multiplexing code   */  int fpga_dump(int devnum, const void *buf, size_t bsize)  {  	int ret_val = FPGA_FAIL;           /* assume failure */ -	fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ ); +	const fpga_desc *desc = fpga_validate(devnum, buf, bsize, +					      (char *)__func__); -	if ( desc ) { -		switch ( desc->devtype ) { +	if (desc) { +		switch (desc->devtype) {  		case fpga_xilinx:  #if defined(CONFIG_FPGA_XILINX) -			ret_val = xilinx_dump( desc->devdesc, buf, bsize ); +			ret_val = xilinx_dump(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); +			fpga_no_sup((char *)__func__, "Xilinx devices");  #endif  			break;  		case fpga_altera:  #if defined(CONFIG_FPGA_ALTERA) -			ret_val = altera_dump( desc->devdesc, buf, bsize ); +			ret_val = altera_dump(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); +			fpga_no_sup((char *)__func__, "Altera devices");  #endif  			break;  		case fpga_lattice:  #if defined(CONFIG_FPGA_LATTICE)  			ret_val = lattice_dump(desc->devdesc, buf, bsize);  #else -			fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); +			fpga_no_sup((char *)__func__, "Lattice devices");  #endif  			break;  		default: -			printf( "%s: Invalid or unsupported device type %d\n", -				__FUNCTION__, desc->devtype ); +			printf("%s: Invalid or unsupported device type %d\n", +			       __func__, desc->devtype);  		}  	}  	return ret_val;  } - -/* fpga_info +/* + * fpga_info   *	front end to fpga_dev_info.  If devnum is invalid, report on all   *	available devices.   */ -int fpga_info( int devnum ) +int fpga_info(int devnum)  { -	if ( devnum == FPGA_INVALID_DEVICE ) { -		if ( next_desc > 0 ) { +	if (devnum == FPGA_INVALID_DEVICE) { +		if (next_desc > 0) {  			int dev; -			for ( dev = 0; dev < next_desc; dev++ ) { -				fpga_dev_info( dev ); -			} +			for (dev = 0; dev < next_desc; dev++) +				fpga_dev_info(dev); +  			return FPGA_SUCCESS;  		} else { -			printf( "%s: No FPGA devices available.\n", __FUNCTION__ ); +			printf("%s: No FPGA devices available.\n", __func__);  			return FPGA_FAIL;  		}  	} -	else return fpga_dev_info( devnum ); -} -/* ------------------------------------------------------------------------- */ +	return fpga_dev_info(devnum); +} diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 32787b236..49e943718 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -1,4 +1,6 @@  /* + * (C) Copyright 2012-2013, Xilinx, Michal Simek + *   * (C) Copyright 2002   * Rich Ireland, Enterasys Networks, rireland@enterasys.com.   * Keith Outwater, keith_outwater@mvis.com @@ -28,9 +30,11 @@   */  #include <common.h> +#include <fpga.h>  #include <virtex2.h>  #include <spartan2.h>  #include <spartan3.h> +#include <zynqpl.h>  #if 0  #define FPGA_DEBUG @@ -48,6 +52,112 @@ static int xilinx_validate (Xilinx_desc * desc, char *fn);  /* ------------------------------------------------------------------------- */ +int fpga_loadbitstream(int devnum, char *fpgadata, size_t size) +{ +	unsigned int length; +	unsigned int swapsize; +	char buffer[80]; +	unsigned char *dataptr; +	unsigned int i; +	const fpga_desc *desc; +	Xilinx_desc *xdesc; + +	dataptr = (unsigned char *)fpgadata; +	/* Find out fpga_description */ +	desc = fpga_validate(devnum, dataptr, 0, (char *)__func__); +	/* Assign xilinx device description */ +	xdesc = desc->devdesc; + +	/* skip the first bytes of the bitsteam, their meaning is unknown */ +	length = (*dataptr << 8) + *(dataptr + 1); +	dataptr += 2; +	dataptr += length; + +	/* get design name (identifier, length, string) */ +	length = (*dataptr << 8) + *(dataptr + 1); +	dataptr += 2; +	if (*dataptr++ != 0x61) { +		debug("%s: Design name id not recognized in bitstream\n", +		      __func__); +		return FPGA_FAIL; +	} + +	length = (*dataptr << 8) + *(dataptr + 1); +	dataptr += 2; +	for (i = 0; i < length; i++) +		buffer[i] = *dataptr++; + +	printf("  design filename = \"%s\"\n", buffer); + +	/* get part number (identifier, length, string) */ +	if (*dataptr++ != 0x62) { +		printf("%s: Part number id not recognized in bitstream\n", +		       __func__); +		return FPGA_FAIL; +	} + +	length = (*dataptr << 8) + *(dataptr + 1); +	dataptr += 2; +	for (i = 0; i < length; i++) +		buffer[i] = *dataptr++; + +	if (xdesc->name) { +		i = strncmp(buffer, xdesc->name, strlen(xdesc->name)); +		if (i) { +			printf("%s: Wrong bitstream ID for this device\n", +			       __func__); +			printf("%s: Bitstream ID %s, current device ID %d/%s\n", +			       __func__, buffer, devnum, xdesc->name); +			return FPGA_FAIL; +		} +	} else { +		printf("%s: Please fill correct device ID to Xilinx_desc\n", +		       __func__); +	} +	printf("  part number = \"%s\"\n", buffer); + +	/* get date (identifier, length, string) */ +	if (*dataptr++ != 0x63) { +		printf("%s: Date identifier not recognized in bitstream\n", +		       __func__); +		return FPGA_FAIL; +	} + +	length = (*dataptr << 8) + *(dataptr+1); +	dataptr += 2; +	for (i = 0; i < length; i++) +		buffer[i] = *dataptr++; +	printf("  date = \"%s\"\n", buffer); + +	/* get time (identifier, length, string) */ +	if (*dataptr++ != 0x64) { +		printf("%s: Time identifier not recognized in bitstream\n", +		       __func__); +		return FPGA_FAIL; +	} + +	length = (*dataptr << 8) + *(dataptr+1); +	dataptr += 2; +	for (i = 0; i < length; i++) +		buffer[i] = *dataptr++; +	printf("  time = \"%s\"\n", buffer); + +	/* get fpga data length (identifier, length) */ +	if (*dataptr++ != 0x65) { +		printf("%s: Data length id not recognized in bitstream\n", +		       __func__); +		return FPGA_FAIL; +	} +	swapsize = ((unsigned int) *dataptr << 24) + +		   ((unsigned int) *(dataptr + 1) << 16) + +		   ((unsigned int) *(dataptr + 2) << 8) + +		   ((unsigned int) *(dataptr + 3)); +	dataptr += 4; +	printf("  bytes in bitstream = %d\n", swapsize); + +	return fpga_load(devnum, dataptr, swapsize); +} +  int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize)  {  	int ret_val = FPGA_FAIL;	/* assume a failure */ @@ -86,6 +196,16 @@ int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize)  					__FUNCTION__);  #endif  			break; +		case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) +			PRINTF("%s: Launching the Zynq PL Loader...\n", +			       __func__); +			ret_val = zynq_load(desc, buf, bsize); +#else +			printf("%s: No support for Zynq devices.\n", +			       __func__); +#endif +			break;  		default:  			printf ("%s: Unsupported family type, %d\n", @@ -133,6 +253,16 @@ int xilinx_dump(Xilinx_desc *desc, const void *buf, size_t bsize)  					__FUNCTION__);  #endif  			break; +		case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) +			PRINTF("%s: Launching the Zynq PL Reader...\n", +			       __func__); +			ret_val = zynq_dump(desc, buf, bsize); +#else +			printf("%s: No support for Zynq devices.\n", +			       __func__); +#endif +			break;  		default:  			printf ("%s: Unsupported family type, %d\n", @@ -158,6 +288,9 @@ int xilinx_info (Xilinx_desc * desc)  		case Xilinx_Virtex2:  			printf ("Virtex-II\n");  			break; +		case xilinx_zynq: +			printf("Zynq PL\n"); +			break;  			/* Add new family types here */  		default:  			printf ("Unknown family type, %d\n", desc->family); @@ -183,6 +316,9 @@ int xilinx_info (Xilinx_desc * desc)  		case master_selectmap:  			printf ("Master SelectMap Mode\n");  			break; +		case devcfg: +			printf("Device configuration interface (Zynq)\n"); +			break;  			/* Add new interface types here */  		default:  			printf ("Unsupported interface type, %d\n", desc->iface); @@ -191,6 +327,8 @@ int xilinx_info (Xilinx_desc * desc)  		printf ("Device Size:   \t%d bytes\n"  				"Cookie:        \t0x%x (%d)\n",  				desc->size, desc->cookie, desc->cookie); +		if (desc->name) +			printf("Device name:   \t%s\n", desc->name);  		if (desc->iface_fns) {  			printf ("Device Function Table @ 0x%p\n", desc->iface_fns); @@ -222,6 +360,14 @@ int xilinx_info (Xilinx_desc * desc)  						__FUNCTION__);  #endif  				break; +			case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) +				zynq_info(desc); +#else +				/* just in case */ +				printf("%s: No support for Zynq devices.\n", +				       __func__); +#endif  				/* Add new family types here */  			default:  				/* we don't need a message here - we give one up above */ diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c new file mode 100644 index 000000000..8feccdea4 --- /dev/null +++ b/drivers/fpga/zynqpl.c @@ -0,0 +1,355 @@ +/* + * (C) Copyright 2012-2013, Xilinx, Michal Simek + * + * (C) Copyright 2012 + * Joe Hershberger <joe.hershberger@ni.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <zynqpl.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> + +#define DEVCFG_CTRL_PCFG_PROG_B		0x40000000 +#define DEVCFG_ISR_FATAL_ERROR_MASK	0x00740040 +#define DEVCFG_ISR_ERROR_FLAGS_MASK	0x00340840 +#define DEVCFG_ISR_RX_FIFO_OV		0x00040000 +#define DEVCFG_ISR_DMA_DONE		0x00002000 +#define DEVCFG_ISR_PCFG_DONE		0x00000004 +#define DEVCFG_STATUS_DMA_CMD_Q_F	0x80000000 +#define DEVCFG_STATUS_DMA_CMD_Q_E	0x40000000 +#define DEVCFG_STATUS_DMA_DONE_CNT_MASK	0x30000000 +#define DEVCFG_STATUS_PCFG_INIT		0x00000010 +#define DEVCFG_MCTRL_RFIFO_FLUSH	0x00000002 +#define DEVCFG_MCTRL_WFIFO_FLUSH	0x00000001 + +#ifndef CONFIG_SYS_FPGA_WAIT +#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */ +#endif + +#ifndef CONFIG_SYS_FPGA_PROG_TIME +#define CONFIG_SYS_FPGA_PROG_TIME CONFIG_SYS_HZ	/* 1 s */ +#endif + +int zynq_info(Xilinx_desc *desc) +{ +	return FPGA_SUCCESS; +} + +#define DUMMY_WORD	0xffffffff + +/* Xilinx binary format header */ +static const u32 bin_format[] = { +	DUMMY_WORD, /* Dummy words */ +	DUMMY_WORD, +	DUMMY_WORD, +	DUMMY_WORD, +	DUMMY_WORD, +	DUMMY_WORD, +	DUMMY_WORD, +	DUMMY_WORD, +	0x000000bb, /* Sync word */ +	0x11220044, /* Sync word */ +	DUMMY_WORD, +	DUMMY_WORD, +	0xaa995566, /* Sync word */ +}; + +#define SWAP_NO		1 +#define SWAP_DONE	2 + +/* + * Load the whole word from unaligned buffer + * Keep in your mind that it is byte loading on little-endian system + */ +static u32 load_word(const void *buf, u32 swap) +{ +	u32 word = 0; +	u8 *bitc = (u8 *)buf; +	int p; + +	if (swap == SWAP_NO) { +		for (p = 0; p < 4; p++) { +			word <<= 8; +			word |= bitc[p]; +		} +	} else { +		for (p = 3; p >= 0; p--) { +			word <<= 8; +			word |= bitc[p]; +		} +	} + +	return word; +} + +static u32 check_header(const void *buf) +{ +	u32 i, pattern; +	int swap = SWAP_NO; +	u32 *test = (u32 *)buf; + +	debug("%s: Let's check bitstream header\n", __func__); + +	/* Checking that passing bin is not a bitstream */ +	for (i = 0; i < ARRAY_SIZE(bin_format); i++) { +		pattern = load_word(&test[i], swap); + +		/* +		 * Bitstreams in binary format are swapped +		 * compare to regular bistream. +		 * Do not swap dummy word but if swap is done assume +		 * that parsing buffer is binary format +		 */ +		if ((__swab32(pattern) != DUMMY_WORD) && +		    (__swab32(pattern) == bin_format[i])) { +			pattern = __swab32(pattern); +			swap = SWAP_DONE; +			debug("%s: data swapped - let's swap\n", __func__); +		} + +		debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i, +		      (u32)&test[i], pattern, bin_format[i]); +		if (pattern != bin_format[i]) { +			debug("%s: Bitstream is not recognized\n", __func__); +			return 0; +		} +	} +	debug("%s: Found bitstream header at %x %s swapinng\n", __func__, +	      (u32)buf, swap == SWAP_NO ? "without" : "with"); + +	return swap; +} + +static void *check_data(u8 *buf, size_t bsize, u32 *swap) +{ +	u32 word, p = 0; /* possition */ + +	/* Because buf doesn't need to be aligned let's read it by chars */ +	for (p = 0; p < bsize; p++) { +		word = load_word(&buf[p], SWAP_NO); +		debug("%s: word %x %x/%x\n", __func__, word, p, (u32)&buf[p]); + +		/* Find the first bitstream dummy word */ +		if (word == DUMMY_WORD) { +			debug("%s: Found dummy word at position %x/%x\n", +			      __func__, p, (u32)&buf[p]); +			*swap = check_header(&buf[p]); +			if (*swap) { +				/* FIXME add full bitstream checking here */ +				return &buf[p]; +			} +		} +		/* Loop can be huge - support CTRL + C */ +		if (ctrlc()) +			return 0; +	} +	return 0; +} + + +int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize) +{ +	unsigned long ts; /* Timestamp */ +	u32 partialbit = 0; +	u32 i, control, isr_status, 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_start & 0x3) { +		u32 *new_buf = (u32 *)((u32)buf & ~0x3); + +		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; + +		printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__, +		       swap); + +		for (i = 0; i < (bsize/4); i++) +			new_buf[i] = load_word(&buf_start[i], swap); + +		swap = SWAP_DONE; +	} + +	if (!partialbit) { +		zynq_slcr_devcfg_disable(); + +		/* Setting PCFG_PROG_B signal to high */ +		control = readl(&devcfg_base->ctrl); +		writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); +		/* Setting PCFG_PROG_B signal to low */ +		writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); + +		/* Polling the PCAP_INIT status for Reset */ +		ts = get_timer(0); +		while (readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT) { +			if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { +				printf("%s: Timeout wait for INIT to clear\n", +				       __func__); +				return FPGA_FAIL; +			} +		} + +		/* Setting PCFG_PROG_B signal to high */ +		writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); + +		/* Polling the PCAP_INIT status for Set */ +		ts = get_timer(0); +		while (!(readl(&devcfg_base->status) & +			DEVCFG_STATUS_PCFG_INIT)) { +			if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { +				printf("%s: Timeout wait for INIT to set\n", +				       __func__); +				return FPGA_FAIL; +			} +		} +	} + +	isr_status = readl(&devcfg_base->int_sts); + +	/* Clear it all, so if Boot ROM comes back, it can proceed */ +	writel(0xFFFFFFFF, &devcfg_base->int_sts); + +	if (isr_status & DEVCFG_ISR_FATAL_ERROR_MASK) { +		debug("%s: Fatal errors in PCAP 0x%X\n", __func__, isr_status); + +		/* If RX FIFO overflow, need to flush RX FIFO first */ +		if (isr_status & DEVCFG_ISR_RX_FIFO_OV) { +			writel(DEVCFG_MCTRL_RFIFO_FLUSH, &devcfg_base->mctrl); +			writel(0xFFFFFFFF, &devcfg_base->int_sts); +		} +		return FPGA_FAIL; +	} + +	status = readl(&devcfg_base->status); + +	debug("%s: Status = 0x%08X\n", __func__, status); + +	if (status & DEVCFG_STATUS_DMA_CMD_Q_F) { +		debug("%s: Error: device busy\n", __func__); +		return FPGA_FAIL; +	} + +	debug("%s: Device ready\n", __func__); + +	if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) { +		if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) { +			/* Error state, transfer cannot occur */ +			debug("%s: ISR indicates error\n", __func__); +			return FPGA_FAIL; +		} else { +			/* Clear out the status */ +			writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts); +		} +	} + +	if (status & DEVCFG_STATUS_DMA_DONE_CNT_MASK) { +		/* Clear the count of completed DMA transfers */ +		writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status); +	} + +	debug("%s: Source = 0x%08X\n", __func__, (u32)buf); +	debug("%s: Size = %zu\n", __func__, bsize); + +	/* 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); + +	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)) { +		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { +			printf("%s: Timeout wait for FPGA to config\n", +			       __func__); +			return FPGA_FAIL; +		} +		isr_status = readl(&devcfg_base->int_sts); +	} + +	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(); + +	return FPGA_SUCCESS; +} + +int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize) +{ +	return FPGA_FAIL; +} |