diff options
29 files changed, 1486 insertions, 430 deletions
| diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index 788a8fd14..52048c676 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -28,6 +28,9 @@  #define SLCR_LOCK_MAGIC		0x767B  #define SLCR_UNLOCK_MAGIC	0xDF0D +#define SLCR_IDCODE_MASK	0x1F000 +#define SLCR_IDCODE_SHIFT	12 +  static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */  void zynq_slcr_lock(void) @@ -61,3 +64,61 @@ void zynq_slcr_cpu_reset(void)  	writel(1, &slcr_base->pss_rst_ctrl);  } + +/* Setup clk for network */ +void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk) +{ +	zynq_slcr_unlock(); + +	if (gem_id > 1) { +		printf("Non existing GEM id %d\n", gem_id); +		goto out; +	} + +	if (gem_id) { +		/* Set divisors for appropriate frequency in GEM_CLK_CTRL */ +		writel(clk, &slcr_base->gem1_clk_ctrl); +		/* Configure GEM_RCLK_CTRL */ +		writel(rclk, &slcr_base->gem1_rclk_ctrl); +	} else { +		/* Set divisors for appropriate frequency in GEM_CLK_CTRL */ +		writel(clk, &slcr_base->gem0_clk_ctrl); +		/* Configure GEM_RCLK_CTRL */ +		writel(rclk, &slcr_base->gem0_rclk_ctrl); +	} + +out: +	zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_disable(void) +{ +	zynq_slcr_unlock(); + +	/* Disable AXI interface */ +	writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl); + +	/* Set Level Shifters DT618760 */ +	writel(0xA, &slcr_base->lvl_shftr_en); + +	zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_enable(void) +{ +	zynq_slcr_unlock(); + +	/* Set Level Shifters DT618760 */ +	writel(0xF, &slcr_base->lvl_shftr_en); + +	/* Disable AXI interface */ +	writel(0x0, &slcr_base->fpga_rst_ctrl); + +	zynq_slcr_lock(); +} + +u32 zynq_slcr_get_idcode(void) +{ +	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >> +							SLCR_IDCODE_SHIFT; +} diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c index 45b405a4b..8c4357de4 100644 --- a/arch/arm/cpu/armv7/zynq/timer.c +++ b/arch/arm/cpu/armv7/zynq/timer.c @@ -44,6 +44,7 @@  #include <common.h>  #include <div64.h>  #include <asm/io.h> +#include <asm/arch/hardware.h>  DECLARE_GLOBAL_DATA_PTR; @@ -54,7 +55,7 @@ struct scu_timer {  };  static struct scu_timer *timer_base = -			      (struct scu_timer *) CONFIG_SCUTIMER_BASEADDR; +			      (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;  #define SCUTIMER_CONTROL_PRESCALER_MASK	0x0000FF00 /* Prescaler */  #define SCUTIMER_CONTROL_PRESCALER_SHIFT	8 @@ -114,15 +115,43 @@ ulong get_timer_masked(void)  void __udelay(unsigned long usec)  { -	unsigned long long tmp; -	ulong tmo; +	u32 countticks; +	u32 timeend; +	u32 timediff; +	u32 timenow; -	tmo = usec / (1000000 / CONFIG_SYS_HZ); -	tmp = get_ticks() + tmo; /* Get current timestamp */ +	if (usec == 0) +		return; -	while (get_ticks() < tmp) { /* Loop till event */ -		 /* NOP */; -	} +	countticks = (u32) (((unsigned long long) TIMER_TICK_HZ * usec) / +								1000000); + +	/* decrementing timer */ +	timeend = readl(&timer_base->counter) - countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF +	/* do not manage multiple overflow */ +	if (countticks >= TIMER_LOAD_VAL) +		countticks = TIMER_LOAD_VAL - 1; +#endif + +	do { +		timenow = readl(&timer_base->counter); + +		if (timenow >= timeend) { +			/* normal case */ +			timediff = timenow - timeend; +		} else { +			if ((TIMER_LOAD_VAL - timeend + timenow) <= +								countticks) { +				/* overflow */ +				timediff = TIMER_LOAD_VAL - timeend + timenow; +			} else { +				/* missed the exact match */ +				break; +			} +		} +	} while (timediff > 0);  }  /* Timer without interrupts */ diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index d0c69da97..8b8a91ae6 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -23,16 +23,28 @@  #ifndef _ASM_ARCH_HARDWARE_H  #define _ASM_ARCH_HARDWARE_H -#define XPSS_SYS_CTRL_BASEADDR		0xF8000000 -#define XPSS_DEV_CFG_APB_BASEADDR	0xF8007000 -#define XPSS_SCU_BASEADDR		0xF8F00000 +#define ZYNQ_SYS_CTRL_BASEADDR		0xF8000000 +#define ZYNQ_DEV_CFG_APB_BASEADDR	0xF8007000 +#define ZYNQ_SCU_BASEADDR		0xF8F00000 +#define ZYNQ_SCUTIMER_BASEADDR		0xF8F00600 +#define ZYNQ_GEM_BASEADDR0		0xE000B000 +#define ZYNQ_GEM_BASEADDR1		0xE000C000 +#define ZYNQ_SDHCI_BASEADDR0		0xE0100000 +#define ZYNQ_SDHCI_BASEADDR1		0xE0101000 +#define ZYNQ_I2C_BASEADDR0		0xE0004000 +#define ZYNQ_I2C_BASEADDR1		0xE0005000  /* Reflect slcr offsets */  struct slcr_regs {  	u32 scl; /* 0x0 */  	u32 slcr_lock; /* 0x4 */  	u32 slcr_unlock; /* 0x8 */ -	u32 reserved1[125]; +	u32 reserved0[75]; +	u32 gem0_rclk_ctrl; /* 0x138 */ +	u32 gem1_rclk_ctrl; /* 0x13c */ +	u32 gem0_clk_ctrl; /* 0x140 */ +	u32 gem1_clk_ctrl; /* 0x144 */ +	u32 reserved1[46];  	u32 pss_rst_ctrl; /* 0x200 */  	u32 reserved2[15];  	u32 fpga_rst_ctrl; /* 0x240 */ @@ -41,15 +53,21 @@ struct slcr_regs {  	u32 boot_mode; /* 0x25c */  	u32 reserved4[116];  	u32 trust_zone; /* 0x430 */ /* FIXME */ -	u32 reserved5[115]; +	u32 reserved5_1[63]; +	u32 pss_idcode; /* 0x530 */ +	u32 reserved5_2[51];  	u32 ddr_urgent; /* 0x600 */  	u32 reserved6[6];  	u32 ddr_urgent_sel; /* 0x61c */ -	u32 reserved7[188]; +	u32 reserved7[56]; +	u32 mio_pin[54]; /* 0x700 - 0x7D4 */ +	u32 reserved8[74]; +	u32 lvl_shftr_en; /* 0x900 */ +	u32 reserved9[3];  	u32 ocm_cfg; /* 0x910 */  }; -#define slcr_base ((struct slcr_regs *) XPSS_SYS_CTRL_BASEADDR) +#define slcr_base ((struct slcr_regs *)ZYNQ_SYS_CTRL_BASEADDR)  struct devcfg_regs {  	u32 ctrl; /* 0x0 */ @@ -72,7 +90,7 @@ struct devcfg_regs {  	u32 read_count; /* 0x8c */  }; -#define devcfg_base ((struct devcfg_regs *) XPSS_DEV_CFG_APB_BASEADDR) +#define devcfg_base ((struct devcfg_regs *)ZYNQ_DEV_CFG_APB_BASEADDR)  struct scu_regs {  	u32 reserved1[16]; @@ -80,6 +98,6 @@ struct scu_regs {  	u32 filter_end; /* 0x44 */  }; -#define scu_base ((struct scu_regs *) XPSS_SCU_BASEADDR) +#define scu_base ((struct scu_regs *)ZYNQ_SCU_BASEADDR)  #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h index e78890011..2317121ca 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/include/asm/arch-zynq/sys_proto.h @@ -26,5 +26,12 @@  extern void zynq_slcr_lock(void);  extern void zynq_slcr_unlock(void);  extern void zynq_slcr_cpu_reset(void); +extern void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk); +extern void zynq_slcr_devcfg_disable(void); +extern void zynq_slcr_devcfg_enable(void); +extern u32 zynq_slcr_get_idcode(void); + +/* Driver extern functions */ +extern int zynq_sdhci_init(u32 regbase);  #endif /* _SYS_PROTO_H_ */ diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 8ed75c3d3..b02c364dc 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -22,13 +22,52 @@  #include <common.h>  #include <netdev.h> +#include <zynqpl.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h>  DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_FPGA +Xilinx_desc fpga; + +/* It can be done differently */ +Xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10); +Xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20); +Xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30); +Xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45); +#endif +  int board_init(void)  { +#ifdef CONFIG_FPGA +	u32 idcode; + +	idcode = zynq_slcr_get_idcode(); + +	switch (idcode) { +	case XILINX_ZYNQ_7010: +		fpga = fpga010; +		break; +	case XILINX_ZYNQ_7020: +		fpga = fpga020; +		break; +	case XILINX_ZYNQ_7030: +		fpga = fpga030; +		break; +	case XILINX_ZYNQ_7045: +		fpga = fpga045; +		break; +	} +#endif +  	icache_enable(); +#ifdef CONFIG_FPGA +	fpga_init(); +	fpga_add(fpga_xilinx, &fpga); +#endif +  	return 0;  } @@ -38,10 +77,33 @@ int board_eth_init(bd_t *bis)  {  	u32 ret = 0; -#if defined(CONFIG_ZYNQ_GEM) && defined(CONFIG_ZYNQ_GEM_BASEADDR0) -	ret = zynq_gem_initialize(bis, CONFIG_ZYNQ_GEM_BASEADDR0); +#if defined(CONFIG_ZYNQ_GEM) +# if defined(CONFIG_ZYNQ_GEM0) +	ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR0, +						CONFIG_ZYNQ_GEM_PHY_ADDR0, 0); +# endif +# if defined(CONFIG_ZYNQ_GEM1) +	ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR1, +						CONFIG_ZYNQ_GEM_PHY_ADDR1, 0); +# endif +#endif +	return ret; +}  #endif +#ifdef CONFIG_CMD_MMC +int board_mmc_init(bd_t *bd) +{ +	int ret = 0; + +#if defined(CONFIG_ZYNQ_SDHCI) +# if defined(CONFIG_ZYNQ_SDHCI0) +	ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0); +# endif +# if defined(CONFIG_ZYNQ_SDHCI1) +	ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1); +# endif +#endif  	return ret;  }  #endif diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index 1834246f3..5e1d03785 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -27,14 +27,11 @@   */  #include <common.h>  #include <command.h> -#if defined(CONFIG_CMD_NET) -#include <net.h> -#endif  #include <fpga.h>  #include <malloc.h>  /* Local functions */ -static int fpga_get_op (char *opstr); +static int fpga_get_op(char *opstr);  /* Local defines */  #define FPGA_NONE   -1 @@ -44,102 +41,6 @@ static int fpga_get_op (char *opstr);  #define FPGA_DUMP   3  #define FPGA_LOADMK 4 -/* Convert bitstream data and load into the fpga */ -int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size) -{ -#if defined(CONFIG_FPGA_XILINX) -	unsigned int length; -	unsigned int swapsize; -	char buffer[80]; -	unsigned char *dataptr; -	unsigned int i; -	int rc; - -	dataptr = (unsigned char *)fpgadata; - -	/* 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 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("  design filename = \"%s\"\n", buffer); - -	/* get part number (identifier, length, string) */ -	if (*dataptr++ != 0x62) { -		printf("%s: Part number 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("  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 identifier 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); - -	rc = fpga_load(dev, dataptr, swapsize); -	return rc; -#else -	printf("Bitstream support only for Xilinx devices\n"); -	return FPGA_FAIL; -#endif -} -  /* ------------------------------------------------------------------------- */  /* command form:   *   fpga <op> <device number> <data addr> <datasize> @@ -148,81 +49,81 @@ int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)   * If there is no data addr field, the fpgadata environment variable is used.   * The info command requires no data address field.   */ -int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])  {  	int op, dev = FPGA_INVALID_DEVICE;  	size_t data_size = 0;  	void *fpga_data = NULL; -	char *devstr = getenv ("fpga"); -	char *datastr = getenv ("fpgadata"); +	char *devstr = getenv("fpga"); +	char *datastr = getenv("fpgadata");  	int rc = FPGA_FAIL;  	int wrong_parms = 0; -#if defined (CONFIG_FIT) +#if defined(CONFIG_FIT)  	const char *fit_uname = NULL;  	ulong fit_addr;  #endif  	if (devstr) -		dev = (int) simple_strtoul (devstr, NULL, 16); +		dev = (int) simple_strtoul(devstr, NULL, 16);  	if (datastr) -		fpga_data = (void *) simple_strtoul (datastr, NULL, 16); +		fpga_data = (void *)simple_strtoul(datastr, NULL, 16);  	switch (argc) {  	case 5:		/* fpga <op> <dev> <data> <datasize> */ -		data_size = simple_strtoul (argv[4], NULL, 16); +		data_size = simple_strtoul(argv[4], NULL, 16);  	case 4:		/* fpga <op> <dev> <data> */  #if defined(CONFIG_FIT) -		if (fit_parse_subimage (argv[3], (ulong)fpga_data, -					&fit_addr, &fit_uname)) { +		if (fit_parse_subimage(argv[3], (ulong)fpga_data, +				       &fit_addr, &fit_uname)) {  			fpga_data = (void *)fit_addr; -			debug("*  fpga: subimage '%s' from FIT image " -				"at 0x%08lx\n", -				fit_uname, fit_addr); +			debug("*  fpga: subimage '%s' from FIT image ", +			      fit_uname); +			debug("at 0x%08lx\n", fit_addr);  		} else  #endif  		{ -			fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); +			fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);  			debug("*  fpga: cmdline image address = 0x%08lx\n", -				(ulong)fpga_data); +			      (ulong)fpga_data);  		} -		debug("%s: fpga_data = 0x%x\n", __func__, (uint) fpga_data); +		debug("%s: fpga_data = 0x%x\n", __func__, (uint)fpga_data);  	case 3:		/* fpga <op> <dev | data addr> */ -		dev = (int) simple_strtoul (argv[2], NULL, 16); +		dev = (int)simple_strtoul(argv[2], NULL, 16);  		debug("%s: device = %d\n", __func__, dev);  		/* FIXME - this is a really weak test */ -		if ((argc == 3) && (dev > fpga_count ())) {	/* must be buffer ptr */ +		if ((argc == 3) && (dev > fpga_count())) { +			/* must be buffer ptr */  			debug("%s: Assuming buffer pointer in arg 3\n", -				__func__); +			      __func__);  #if defined(CONFIG_FIT) -			if (fit_parse_subimage (argv[2], (ulong)fpga_data, -						&fit_addr, &fit_uname)) { +			if (fit_parse_subimage(argv[2], (ulong)fpga_data, +					       &fit_addr, &fit_uname)) {  				fpga_data = (void *)fit_addr; -				debug("*  fpga: subimage '%s' from FIT image " -					"at 0x%08lx\n", -					fit_uname, fit_addr); +				debug("*  fpga: subimage '%s' from FIT image ", +				      fit_uname); +				debug("at 0x%08lx\n", fit_addr);  			} else  #endif  			{ -				fpga_data = (void *) dev; -				debug("*  fpga: cmdline image address = " -					"0x%08lx\n", (ulong)fpga_data); +				fpga_data = (void *)dev; +				debug("*  fpga: cmdline image addr = 0x%08lx\n", +				      (ulong)fpga_data);  			}  			debug("%s: fpga_data = 0x%x\n", -				__func__, (uint) fpga_data); +			      __func__, (uint)fpga_data);  			dev = FPGA_INVALID_DEVICE;	/* reset device num */  		}  	case 2:		/* fpga <op> */ -		op = (int) fpga_get_op (argv[1]); +		op = (int)fpga_get_op(argv[1]);  		break;  	default: -		debug("%s: Too many or too few args (%d)\n", -			__func__, argc); +		debug("%s: Too many or too few args (%d)\n", __func__, argc);  		op = FPGA_NONE;	/* force usage display */  		break;  	} @@ -258,11 +159,11 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		return CMD_RET_USAGE;  	case FPGA_INFO: -		rc = fpga_info (dev); +		rc = fpga_info(dev);  		break;  	case FPGA_LOAD: -		rc = fpga_load (dev, fpga_data, data_size); +		rc = fpga_load(dev, fpga_data, data_size);  		break;  	case FPGA_LOADB: @@ -270,15 +171,16 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		break;  	case FPGA_LOADMK: -		switch (genimg_get_format (fpga_data)) { +		switch (genimg_get_format(fpga_data)) {  		case IMAGE_FORMAT_LEGACY:  			{ -				image_header_t *hdr = (image_header_t *)fpga_data; -				ulong	data; +				image_header_t *hdr = +						(image_header_t *)fpga_data; +				ulong data; -				data = (ulong)image_get_data (hdr); -				data_size = image_get_data_size (hdr); -				rc = fpga_load (dev, (void *)data, data_size); +				data = (ulong)image_get_data(hdr); +				data_size = image_get_data_size(hdr); +				rc = fpga_load(dev, (void *)data, data_size);  			}  			break;  #if defined(CONFIG_FIT) @@ -289,95 +191,97 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  				const void *fit_data;  				if (fit_uname == NULL) { -					puts ("No FIT subimage unit name\n"); +					puts("No FIT subimage unit name\n");  					return 1;  				} -				if (!fit_check_format (fit_hdr)) { -					puts ("Bad FIT image format\n"); +				if (!fit_check_format(fit_hdr)) { +					puts("Bad FIT image format\n");  					return 1;  				}  				/* get fpga component image node offset */ -				noffset = fit_image_get_node (fit_hdr, fit_uname); +				noffset = fit_image_get_node(fit_hdr, +							     fit_uname);  				if (noffset < 0) { -					printf ("Can't find '%s' FIT subimage\n", fit_uname); +					printf("Can't find '%s' FIT subimage\n", +					       fit_uname);  					return 1;  				}  				/* verify integrity */ -				if (!fit_image_check_hashes (fit_hdr, noffset)) { -					puts ("Bad Data Hash\n"); +				if (!fit_image_check_hashes(fit_hdr, noffset)) { +					puts("Bad Data Hash\n");  					return 1;  				}  				/* get fpga subimage data address and length */ -				if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { -					puts ("Could not find fpga subimage data\n"); +				if (fit_image_get_data(fit_hdr, noffset, +						       &fit_data, &data_size)) { +					puts("Fpga subimage data not found\n");  					return 1;  				} -				rc = fpga_load (dev, fit_data, data_size); +				rc = fpga_load(dev, fit_data, data_size);  			}  			break;  #endif  		default: -			puts ("** Unknown image type\n"); +			puts("** Unknown image type\n");  			rc = FPGA_FAIL;  			break;  		}  		break;  	case FPGA_DUMP: -		rc = fpga_dump (dev, fpga_data, data_size); +		rc = fpga_dump(dev, fpga_data, data_size);  		break;  	default: -		printf ("Unknown operation\n"); +		printf("Unknown operation\n");  		return CMD_RET_USAGE;  	} -	return (rc); +	return rc;  }  /*   * Map op to supported operations.  We don't use a table since we   * would just have to relocate it from flash anyway.   */ -static int fpga_get_op (char *opstr) +static int fpga_get_op(char *opstr)  {  	int op = FPGA_NONE; -	if (!strcmp ("info", opstr)) { +	if (!strcmp("info", opstr))  		op = FPGA_INFO; -	} else if (!strcmp ("loadb", opstr)) { +	else if (!strcmp("loadb", opstr))  		op = FPGA_LOADB; -	} else if (!strcmp ("load", opstr)) { +	else if (!strcmp("load", opstr))  		op = FPGA_LOAD; -	} else if (!strcmp ("loadmk", opstr)) { +	else if (!strcmp("loadmk", opstr))  		op = FPGA_LOADMK; -	} else if (!strcmp ("dump", opstr)) { +	else if (!strcmp("dump", opstr))  		op = FPGA_DUMP; -	} -	if (op == FPGA_NONE) { -		printf ("Unknown fpga operation \"%s\"\n", opstr); -	} +	if (op == FPGA_NONE) +		printf("Unknown fpga operation \"%s\"\n", opstr); +  	return op;  } -U_BOOT_CMD (fpga, 6, 1, do_fpga, -	"loadable FPGA image support", -	"[operation type] [device number] [image address] [image size]\n" -	"fpga operations:\n" -	"  dump\t[dev]\t\t\tLoad device to memory buffer\n" -	"  info\t[dev]\t\t\tlist known device information\n" -	"  load\t[dev] [address] [size]\tLoad device from memory buffer\n" -	"  loadb\t[dev] [address] [size]\t" -	"Load device from bitstream buffer (Xilinx only)\n" -	"  loadmk [dev] [address]\tLoad device generated with mkimage" +U_BOOT_CMD(fpga, 6, 1, do_fpga, +	   "loadable FPGA image support", +	   "[operation type] [device number] [image address] [image size]\n" +	   "fpga operations:\n" +	   "  dump\t[dev]\t\t\tLoad device to memory buffer\n" +	   "  info\t[dev]\t\t\tlist known device information\n" +	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n" +	   "  loadb\t[dev] [address] [size]\t" +	   "Load device from bitstream buffer (Xilinx only)\n" +	   "  loadmk [dev] [address]\tLoad device generated with mkimage"  #if defined(CONFIG_FIT) -	"\n" -	"\tFor loadmk operating on FIT format uImage address must include\n" -	"\tsubimage unit name in the form of addr:<subimg_uname>" +	   "\n" +	   "\tFor loadmk operating on FIT format uImage address must include\n" +	   "\tsubimage unit name in the form of addr:<subimg_uname>"  #endif  ); 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; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 5dbdbe367..72e85a349 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o  COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o  COBJS-$(CONFIG_SH_I2C) += sh_i2c.o  COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o +COBJS-$(CONFIG_ZYNQ_I2C) += zynq_i2c.o  COBJS	:= $(COBJS-y)  SRCS	:= $(COBJS:.o=.c) diff --git a/drivers/i2c/zynq_i2c.c b/drivers/i2c/zynq_i2c.c new file mode 100644 index 000000000..ec49660cf --- /dev/null +++ b/drivers/i2c/zynq_i2c.c @@ -0,0 +1,306 @@ +/* + * Driver for the Zynq-7000 PS I2C controller + * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2) + * + * Author: Joe Hershberger <joe.hershberger@ni.com> + * Copyright (c) 2012 Joe Hershberger. + * + * Copyright (c) 2012-2013 Xilinx, Michal Simek + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <i2c.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> + +/* i2c register set */ +struct zynq_i2c_registers { +	u32 control; +	u32 status; +	u32 address; +	u32 data; +	u32 interrupt_status; +	u32 transfer_size; +	u32 slave_mon_pause; +	u32 time_out; +	u32 interrupt_mask; +	u32 interrupt_enable; +	u32 interrupt_disable; +}; + +/* Control register fields */ +#define ZYNQ_I2C_CONTROL_RW		0x00000001 +#define ZYNQ_I2C_CONTROL_MS		0x00000002 +#define ZYNQ_I2C_CONTROL_NEA		0x00000004 +#define ZYNQ_I2C_CONTROL_ACKEN		0x00000008 +#define ZYNQ_I2C_CONTROL_HOLD		0x00000010 +#define ZYNQ_I2C_CONTROL_SLVMON		0x00000020 +#define ZYNQ_I2C_CONTROL_CLR_FIFO	0x00000040 +#define ZYNQ_I2C_CONTROL_DIV_B_SHIFT	8 +#define ZYNQ_I2C_CONTROL_DIV_B_MASK	0x00003F00 +#define ZYNQ_I2C_CONTROL_DIV_A_SHIFT	14 +#define ZYNQ_I2C_CONTROL_DIV_A_MASK	0x0000C000 + +/* Status register values */ +#define ZYNQ_I2C_STATUS_RXDV	0x00000020 +#define ZYNQ_I2C_STATUS_TXDV	0x00000040 +#define ZYNQ_I2C_STATUS_RXOVF	0x00000080 +#define ZYNQ_I2C_STATUS_BA	0x00000100 + +/* Interrupt register fields */ +#define ZYNQ_I2C_INTERRUPT_COMP		0x00000001 +#define ZYNQ_I2C_INTERRUPT_DATA		0x00000002 +#define ZYNQ_I2C_INTERRUPT_NACK		0x00000004 +#define ZYNQ_I2C_INTERRUPT_TO		0x00000008 +#define ZYNQ_I2C_INTERRUPT_SLVRDY	0x00000010 +#define ZYNQ_I2C_INTERRUPT_RXOVF	0x00000020 +#define ZYNQ_I2C_INTERRUPT_TXOVF	0x00000040 +#define ZYNQ_I2C_INTERRUPT_RXUNF	0x00000080 +#define ZYNQ_I2C_INTERRUPT_ARBLOST	0x00000200 + +#define ZYNQ_I2C_FIFO_DEPTH		16 +#define ZYNQ_I2C_TRANSFERT_SIZE_MAX	255 /* Controller transfer limit */ + +#if defined(CONFIG_ZYNQ_I2C0) +# define ZYNQ_I2C_BASE	ZYNQ_I2C_BASEADDR0 +#else +# define ZYNQ_I2C_BASE	ZYNQ_I2C_BASEADDR1 +#endif + +static struct zynq_i2c_registers *zynq_i2c = +	(struct zynq_i2c_registers *)ZYNQ_I2C_BASE; + +/* I2C init called by cmd_i2c when doing 'i2c reset'. */ +void i2c_init(int requested_speed, int slaveadd) +{ +	/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ +	writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) | +		(2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control); + +	/* Enable master mode, ack, and 7-bit addressing */ +	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_MS | +		ZYNQ_I2C_CONTROL_ACKEN | ZYNQ_I2C_CONTROL_NEA); +} + +#ifdef DEBUG +static void zynq_i2c_debug_status(void) +{ +	int int_status; +	int status; +	int_status = readl(&zynq_i2c->interrupt_status); + +	status = readl(&zynq_i2c->status); +	if (int_status || status) { +		debug("Status: "); +		if (int_status & ZYNQ_I2C_INTERRUPT_COMP) +			debug("COMP "); +		if (int_status & ZYNQ_I2C_INTERRUPT_DATA) +			debug("DATA "); +		if (int_status & ZYNQ_I2C_INTERRUPT_NACK) +			debug("NACK "); +		if (int_status & ZYNQ_I2C_INTERRUPT_TO) +			debug("TO "); +		if (int_status & ZYNQ_I2C_INTERRUPT_SLVRDY) +			debug("SLVRDY "); +		if (int_status & ZYNQ_I2C_INTERRUPT_RXOVF) +			debug("RXOVF "); +		if (int_status & ZYNQ_I2C_INTERRUPT_TXOVF) +			debug("TXOVF "); +		if (int_status & ZYNQ_I2C_INTERRUPT_RXUNF) +			debug("RXUNF "); +		if (int_status & ZYNQ_I2C_INTERRUPT_ARBLOST) +			debug("ARBLOST "); +		if (status & ZYNQ_I2C_STATUS_RXDV) +			debug("RXDV "); +		if (status & ZYNQ_I2C_STATUS_TXDV) +			debug("TXDV "); +		if (status & ZYNQ_I2C_STATUS_RXOVF) +			debug("RXOVF "); +		if (status & ZYNQ_I2C_STATUS_BA) +			debug("BA "); +		debug("TS%d ", readl(&zynq_i2c->transfer_size)); +		debug("\n"); +	} +} +#endif + +/* Wait for an interrupt */ +static u32 zynq_i2c_wait(u32 mask) +{ +	int timeout, int_status; + +	for (timeout = 0; timeout < 100; timeout++) { +		udelay(100); +		int_status = readl(&zynq_i2c->interrupt_status); +		if (int_status & mask) +			break; +	} +#ifdef DEBUG +	zynq_i2c_debug_status(); +#endif +	/* Clear interrupt status flags */ +	writel(int_status & mask, &zynq_i2c->interrupt_status); + +	return int_status & mask; +} + +/* + * I2C probe called by cmd_i2c when doing 'i2c probe'. + * Begin read, nak data byte, end. + */ +int i2c_probe(u8 dev) +{ +	/* Attempt to read a byte */ +	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | +		ZYNQ_I2C_CONTROL_RW); +	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); +	writel(0xFF, &zynq_i2c->interrupt_status); +	writel(dev, &zynq_i2c->address); +	writel(1, &zynq_i2c->transfer_size); + +	return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | +		ZYNQ_I2C_INTERRUPT_NACK) & +		ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT; +} + +/* + * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c + * Begin write, send address byte(s), begin read, receive data bytes, end. + */ +int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) +{ +	u32 status; +	u32 i = 0; +	u8 *cur_data = data; + +	/* Check the hardware can handle the requested bytes */ +	if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX)) +		return -EINVAL; + +	/* Write the register address */ +	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | +		ZYNQ_I2C_CONTROL_HOLD); +	/* +	 * Temporarily disable restart (by clearing hold) +	 * It doesn't seem to work. +	 */ +	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW | +		ZYNQ_I2C_CONTROL_HOLD); +	writel(0xFF, &zynq_i2c->interrupt_status); +	while (alen--) +		writel(addr >> (8*alen), &zynq_i2c->data); +	writel(dev, &zynq_i2c->address); + +	/* Wait for the address to be sent */ +	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { +		/* Release the bus */ +		clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); +		return -ETIMEDOUT; +	} +	debug("Device acked address\n"); + +	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | +		ZYNQ_I2C_CONTROL_RW); +	/* Start reading data */ +	writel(dev, &zynq_i2c->address); +	writel(length, &zynq_i2c->transfer_size); + +	/* Wait for data */ +	do { +		status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | +			ZYNQ_I2C_INTERRUPT_DATA); +		if (!status) { +			/* Release the bus */ +			clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); +			return -ETIMEDOUT; +		} +		debug("Read %d bytes\n", +		      length - readl(&zynq_i2c->transfer_size)); +		for (; i < length - readl(&zynq_i2c->transfer_size); i++) +			*(cur_data++) = readl(&zynq_i2c->data); +	} while (readl(&zynq_i2c->transfer_size) != 0); +	/* All done... release the bus */ +	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + +#ifdef DEBUG +	zynq_i2c_debug_status(); +#endif +	return 0; +} + +/* + * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c + * Begin write, send address byte(s), send data bytes, end. + */ +int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) +{ +	u8 *cur_data = data; + +	/* Write the register address */ +	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | +		ZYNQ_I2C_CONTROL_HOLD); +	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW); +	writel(0xFF, &zynq_i2c->interrupt_status); +	while (alen--) +		writel(addr >> (8*alen), &zynq_i2c->data); +	/* Start the tranfer */ +	writel(dev, &zynq_i2c->address); +	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { +		/* Release the bus */ +		clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); +		return -ETIMEDOUT; +	} + +	debug("Device acked address\n"); +	while (length--) { +		writel(*(cur_data++), &zynq_i2c->data); +		if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) { +			if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { +				/* Release the bus */ +				clrbits_le32(&zynq_i2c->control, +					     ZYNQ_I2C_CONTROL_HOLD); +				return -ETIMEDOUT; +			} +		} +	} + +	/* All done... release the bus */ +	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); +	/* Wait for the address and data to be sent */ +	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) +		return -ETIMEDOUT; +	return 0; +} + +int i2c_set_bus_num(unsigned int bus) +{ +	/* Only support bus 0 */ +	if (bus > 0) +		return -1; +	return 0; +} + +unsigned int i2c_get_bus_num(void) +{ +	/* Only support bus 0 */ +	return 0; +} diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 1d6faa2a9..7cd428173 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -49,6 +49,7 @@ COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o  COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o  COBJS-$(CONFIG_DWMMC) += dw_mmc.o  COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o +COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o  COBJS	:= $(COBJS-y)  SRCS	:= $(COBJS:.o=.c) diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c new file mode 100644 index 000000000..9e37af45f --- /dev/null +++ b/drivers/mmc/zynq_sdhci.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2013 Inc. + * + * Xilinx Zynq SD Host Controller Interface + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 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 <malloc.h> +#include <sdhci.h> +#include <asm/arch/sys_proto.h> + +int zynq_sdhci_init(u32 regbase) +{ +	struct sdhci_host *host = NULL; + +	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); +	if (!host) { +		printf("zynq_sdhci_init: sdhci_host malloc fail\n"); +		return 1; +	} + +	host->name = "zynq_sdhci"; +	host->ioaddr = (void *)regbase; +	host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD; +	host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + +	host->host_caps = MMC_MODE_HC; + +	add_sdhci(host, 52000000, 52000000 >> 9); +	return 0; +} diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4b271989a..46801c791 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -465,6 +465,16 @@ static struct phy_driver M88E1149S_driver = {  	.shutdown = &genphy_shutdown,  }; +static struct phy_driver M88E1518_driver = { +	.name = "Marvell 88E1518", +	.uid = 0x1410dd1, +	.mask = 0xffffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &m88e1111s_config, +	.startup = &m88e1011s_startup, +	.shutdown = &genphy_shutdown, +}; +  int phy_marvell_init(void)  {  	phy_register(&M88E1149S_driver); @@ -474,6 +484,7 @@ int phy_marvell_init(void)  	phy_register(&M88E1118R_driver);  	phy_register(&M88E1111S_driver);  	phy_register(&M88E1011S_driver); +	phy_register(&M88E1518_driver);  	return 0;  } diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 359606569..eac9b6f45 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -33,6 +33,8 @@  #include <phy.h>  #include <miiphy.h>  #include <watchdog.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h>  #if !defined(CONFIG_PHYLIB)  # error XILINX_GEM_ETHERNET requires PHYLIB @@ -67,13 +69,14 @@  #define ZYNQ_GEM_NWCTRL_MDEN_MASK	0x00000010 /* Enable MDIO port */  #define ZYNQ_GEM_NWCTRL_STARTTX_MASK	0x00000200 /* Start tx (tx_go) */ -#define ZYNQ_GEM_NWCFG_SPEED		0x00000001 /* 100 Mbps operation */ -#define ZYNQ_GEM_NWCFG_FDEN		0x00000002 /* Full Duplex mode */ -#define ZYNQ_GEM_NWCFG_FSREM		0x00020000 /* FCS removal */ +#define ZYNQ_GEM_NWCFG_SPEED100		0x000000001 /* 100 Mbps operation */ +#define ZYNQ_GEM_NWCFG_SPEED1000	0x000000400 /* 1Gbps operation */ +#define ZYNQ_GEM_NWCFG_FDEN		0x000000002 /* Full Duplex mode */ +#define ZYNQ_GEM_NWCFG_FSREM		0x000020000 /* FCS removal */  #define ZYNQ_GEM_NWCFG_MDCCLKDIV	0x000080000 /* Div pclk by 32, 80MHz */ +#define ZYNQ_GEM_NWCFG_MDCCLKDIV2	0x0000c0000 /* Div pclk by 48, 120MHz */ -#define ZYNQ_GEM_NWCFG_INIT		(ZYNQ_GEM_NWCFG_SPEED | \ -					ZYNQ_GEM_NWCFG_FDEN | \ +#define ZYNQ_GEM_NWCFG_INIT		(ZYNQ_GEM_NWCFG_FDEN | \  					ZYNQ_GEM_NWCFG_FSREM | \  					ZYNQ_GEM_NWCFG_MDCCLKDIV) @@ -92,6 +95,17 @@  					ZYNQ_GEM_DMACR_TXSIZE | \  					ZYNQ_GEM_DMACR_RXBUF) +/* Use MII register 1 (MII status register) to detect PHY */ +#define PHY_DETECT_REG  1 + +/* Mask used to verify certain PHY features (or register contents) + * in the register above: + *  0x1000: 10Mbps full duplex support + *  0x0800: 10Mbps half duplex support + *  0x0008: Auto-negotiation support + */ +#define PHY_DETECT_MASK 0x1808 +  /* Device registers */  struct zynq_gem_regs {  	u32 nwctrl; /* Network Control reg */ @@ -134,6 +148,8 @@ struct zynq_gem_priv {  	u32 rxbd_current;  	u32 rx_first_buf;  	int phyaddr; +	u32 emio; +	int init;  	struct phy_device *phydev;  	struct mii_dev *bus;  }; @@ -196,6 +212,44 @@ static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)  				ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);  } +static void phy_detection(struct eth_device *dev) +{ +	int i; +	u16 phyreg; +	struct zynq_gem_priv *priv = dev->priv; + +	if (priv->phyaddr != -1) { +		phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg); +		if ((phyreg != 0xFFFF) && +		    ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { +			/* Found a valid PHY address */ +			debug("Default phy address %d is valid\n", +			      priv->phyaddr); +			return; +		} else { +			debug("PHY address is not setup correctly %d\n", +			      priv->phyaddr); +			priv->phyaddr = -1; +		} +	} + +	debug("detecting phy address\n"); +	if (priv->phyaddr == -1) { +		/* detect the PHY address */ +		for (i = 31; i >= 0; i--) { +			phyread(dev, i, PHY_DETECT_REG, &phyreg); +			if ((phyreg != 0xFFFF) && +			    ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { +				/* Found a valid PHY address */ +				priv->phyaddr = i; +				debug("Found valid phy address, %d\n", i); +				return; +			} +		} +	} +	printf("PHY is not detected\n"); +} +  static int zynq_gem_setup_mac(struct eth_device *dev)  {  	u32 i, macaddrlow, macaddrhigh; @@ -226,7 +280,7 @@ static int zynq_gem_setup_mac(struct eth_device *dev)  static int zynq_gem_init(struct eth_device *dev, bd_t * bis)  { -	u32 i; +	u32 i, rclk, clk = 0;  	struct phy_device *phydev;  	const u32 stat_size = (sizeof(struct zynq_gem_regs) -  				offsetof(struct zynq_gem_regs, stat)) / 4; @@ -239,59 +293,92 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)  			SUPPORTED_1000baseT_Half |  			SUPPORTED_1000baseT_Full; -	/* Disable all interrupts */ -	writel(0xFFFFFFFF, ®s->idr); +	if (!priv->init) { +		/* Disable all interrupts */ +		writel(0xFFFFFFFF, ®s->idr); -	/* Disable the receiver & transmitter */ -	writel(0, ®s->nwctrl); -	writel(0, ®s->txsr); -	writel(0, ®s->rxsr); -	writel(0, ®s->phymntnc); +		/* Disable the receiver & transmitter */ +		writel(0, ®s->nwctrl); +		writel(0, ®s->txsr); +		writel(0, ®s->rxsr); +		writel(0, ®s->phymntnc); -	/* Clear the Hash registers for the mac address pointed by AddressPtr */ -	writel(0x0, ®s->hashl); -	/* Write bits [63:32] in TOP */ -	writel(0x0, ®s->hashh); +		/* Clear the Hash registers for the mac address +		 * pointed by AddressPtr +		 */ +		writel(0x0, ®s->hashl); +		/* Write bits [63:32] in TOP */ +		writel(0x0, ®s->hashh); -	/* Clear all counters */ -	for (i = 0; i <= stat_size; i++) -		readl(®s->stat[i]); +		/* Clear all counters */ +		for (i = 0; i <= stat_size; i++) +			readl(®s->stat[i]); -	/* Setup RxBD space */ -	memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); -	/* Create the RxBD ring */ -	memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); +		/* Setup RxBD space */ +		memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); +		/* Create the RxBD ring */ +		memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); -	for (i = 0; i < RX_BUF; i++) { -		priv->rx_bd[i].status = 0xF0000000; -		priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) + +		for (i = 0; i < RX_BUF; i++) { +			priv->rx_bd[i].status = 0xF0000000; +			priv->rx_bd[i].addr = +					(u32)((char *)&(priv->rxbuffers) +  							(i * PKTSIZE_ALIGN)); -	} -	/* WRAP bit to last BD */ -	priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; -	/* Write RxBDs to IP */ -	writel((u32) &(priv->rx_bd), ®s->rxqbase); +		} +		/* WRAP bit to last BD */ +		priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; +		/* Write RxBDs to IP */ +		writel((u32)&(priv->rx_bd), ®s->rxqbase); -	/* MAC Setup */ -	/* Setup Network Configuration register */ -	writel(ZYNQ_GEM_NWCFG_INIT, ®s->nwcfg); +		/* Setup for DMA Configuration register */ +		writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); -	/* Setup for DMA Configuration register */ -	writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); +		/* Setup for Network Control register, MDIO, Rx and Tx enable */ +		setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK); -	/* Setup for Network Control register, MDIO, Rx and Tx enable */ -	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK | -			ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); +		priv->init++; +	} + +	phy_detection(dev);  	/* interface - look at tsec */  	phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0); -	phydev->supported &= supported; +	phydev->supported = supported | ADVERTISED_Pause | +			    ADVERTISED_Asym_Pause;  	phydev->advertising = phydev->supported;  	priv->phydev = phydev;  	phy_config(phydev);  	phy_startup(phydev); +	switch (phydev->speed) { +	case SPEED_1000: +		writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, +		       ®s->nwcfg); +		rclk = (0 << 4) | (1 << 0); +		clk = (1 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	case SPEED_100: +		clrsetbits_le32(®s->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000, +				ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100); +		rclk = 1 << 0; +		clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	case SPEED_10: +		rclk = 1 << 0; +		/* FIXME untested */ +		clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	} + +	/* Change the rclk and clk only not using EMIO interface */ +	if (!priv->emio) +		zynq_slcr_gem_clk_setup(dev->iobase != +					ZYNQ_GEM_BASEADDR0, rclk, clk); + +	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | +					ZYNQ_GEM_NWCTRL_TXEN_MASK); +  	return 0;  } @@ -307,11 +394,10 @@ static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)  	writel((u32)&(priv->tx_bd), ®s->txqbase);  	/* Setup Tx BD */ -	memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd)); +	memset((void *)&(priv->tx_bd), 0, sizeof(struct emac_bd));  	priv->tx_bd.addr = (u32)ptr; -	priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK | -						ZYNQ_GEM_TXBUF_WRAP_MASK; +	priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK;  	/* Start transmit */  	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK); @@ -364,19 +450,17 @@ static int zynq_gem_recv(struct eth_device *dev)  		if ((++priv->rxbd_current) >= RX_BUF)  			priv->rxbd_current = 0; - -		return frame_len;  	} -	return 0; +	return frame_len;  }  static void zynq_gem_halt(struct eth_device *dev)  {  	struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; -	/* Disable the receiver & transmitter */ -	writel(0, ®s->nwctrl); +	clrsetbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | +						ZYNQ_GEM_NWCTRL_TXEN_MASK, 0);  }  static int zynq_gem_miiphyread(const char *devname, uchar addr, @@ -399,7 +483,7 @@ static int zynq_gem_miiphy_write(const char *devname, uchar addr,  	return phywrite(dev, addr, reg, val);  } -int zynq_gem_initialize(bd_t *bis, int base_addr) +int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio)  {  	struct eth_device *dev;  	struct zynq_gem_priv *priv; @@ -415,11 +499,8 @@ int zynq_gem_initialize(bd_t *bis, int base_addr)  	}  	priv = dev->priv; -#ifdef CONFIG_PHY_ADDR -	priv->phyaddr = CONFIG_PHY_ADDR; -#else -	priv->phyaddr = -1; -#endif +	priv->phyaddr = phy_addr; +	priv->emio = emio;  	sprintf(dev->name, "Gem.%x", base_addr); diff --git a/include/altera.h b/include/altera.h index 7a2bece03..6aad5ee86 100644 --- a/include/altera.h +++ b/include/altera.h @@ -27,23 +27,6 @@  #ifndef _ALTERA_H_  #define _ALTERA_H_ -/* Altera Model definitions - *********************************************************************/ -#define CONFIG_SYS_ACEX1K		CONFIG_SYS_FPGA_DEV( 0x1 ) -#define CONFIG_SYS_CYCLON2		CONFIG_SYS_FPGA_DEV( 0x2 ) -#define CONFIG_SYS_STRATIX_II		CONFIG_SYS_FPGA_DEV( 0x4 ) - -#define CONFIG_SYS_ALTERA_ACEX1K	(CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_ACEX1K) -#define CONFIG_SYS_ALTERA_CYCLON2	(CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_CYCLON2) -#define CONFIG_SYS_ALTERA_STRATIX_II	(CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_STRATIX_II) -/* Add new models here */ - -/* Altera Interface definitions - *********************************************************************/ -#define CONFIG_SYS_ALTERA_IF_PS	CONFIG_SYS_FPGA_IF( 0x1 )	/* passive serial */ -#define CONFIG_SYS_ALTERA_IF_FPP	CONFIG_SYS_FPGA_IF( 0x2 )	/* fast passive parallel */ -/* Add new interfaces here */ -  typedef enum {				/* typedef Altera_iface */  	min_altera_iface_type,		/* insert all new types after this */  	passive_serial,			/* serial data and external clock */ diff --git a/include/configs/M54455EVB.h b/include/configs/M54455EVB.h index 1bc2c5a0a..536b7556f 100644 --- a/include/configs/M54455EVB.h +++ b/include/configs/M54455EVB.h @@ -238,7 +238,7 @@  /* FPGA - Spartan 2 */  /* experiment -#define CONFIG_FPGA		CONFIG_SYS_SPARTAN3 +#define CONFIG_FPGA  #define CONFIG_FPGA_COUNT	1  #define CONFIG_SYS_FPGA_PROG_FEEDBACK  #define CONFIG_SYS_FPGA_CHECK_CTRLC diff --git a/include/configs/MERGERBOX.h b/include/configs/MERGERBOX.h index c296e3cf0..30fb6c2ff 100644 --- a/include/configs/MERGERBOX.h +++ b/include/configs/MERGERBOX.h @@ -606,7 +606,7 @@   * FPGA   */  #define CONFIG_FPGA_COUNT	1 -#define CONFIG_FPGA		CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA  #define CONFIG_FPGA_ALTERA  #define CONFIG_FPGA_CYCLON2 diff --git a/include/configs/MVBC_P.h b/include/configs/MVBC_P.h index 6850965fb..72714688e 100644 --- a/include/configs/MVBC_P.h +++ b/include/configs/MVBC_P.h @@ -310,7 +310,7 @@  #undef FPGA_DEBUG  #undef CONFIG_SYS_FPGA_PROG_FEEDBACK -#define CONFIG_FPGA		CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA  #define CONFIG_FPGA_ALTERA	1  #define CONFIG_FPGA_CYCLON2	1  #define CONFIG_FPGA_COUNT	1 diff --git a/include/configs/MVBLM7.h b/include/configs/MVBLM7.h index a99ad3c44..a9c00acc9 100644 --- a/include/configs/MVBLM7.h +++ b/include/configs/MVBLM7.h @@ -499,7 +499,7 @@  	""  #define CONFIG_FPGA_COUNT	1 -#define CONFIG_FPGA		CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA  #define CONFIG_FPGA_ALTERA  #define CONFIG_FPGA_CYCLON2 diff --git a/include/configs/MVSMR.h b/include/configs/MVSMR.h index bf2f44ec6..5d2ff1480 100644 --- a/include/configs/MVSMR.h +++ b/include/configs/MVSMR.h @@ -280,7 +280,7 @@  #undef FPGA_DEBUG  #undef CONFIG_SYS_FPGA_PROG_FEEDBACK -#define CONFIG_FPGA		CONFIG_SYS_XILINX_SPARTAN2 +#define CONFIG_FPGA  #define CONFIG_FPGA_XILINX	1  #define CONFIG_FPGA_SPARTAN2	1  #define CONFIG_FPGA_COUNT	1 diff --git a/include/configs/omap3_mvblx.h b/include/configs/omap3_mvblx.h index 376a3d031..f9adc0170 100644 --- a/include/configs/omap3_mvblx.h +++ b/include/configs/omap3_mvblx.h @@ -273,7 +273,7 @@  #endif /* (CONFIG_CMD_NET) */  #define CONFIG_FPGA_COUNT	1 -#define CONFIG_FPGA          CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA  #define CONFIG_FPGA_ALTERA  #define CONFIG_FPGA_CYCLON2  #define CONFIG_SYS_FPGA_PROG_FEEDBACK diff --git a/include/configs/zynq.h b/include/configs/zynq.h index 2989e723e..38f04f642 100644 --- a/include/configs/zynq.h +++ b/include/configs/zynq.h @@ -50,19 +50,50 @@  #define CONFIG_ZYNQ_SERIAL_BAUDRATE0	CONFIG_BAUDRATE  #define CONFIG_ZYNQ_SERIAL_CLOCK0	50000000 -/* SCU timer address is hardcoded */ -#define CONFIG_SCUTIMER_BASEADDR	0xF8F00600 -  /* Ethernet driver */  #define CONFIG_NET_MULTI  #define CONFIG_ZYNQ_GEM -#define CONFIG_ZYNQ_GEM_BASEADDR0	0xE000B000 +#define CONFIG_ZYNQ_GEM0 +#define CONFIG_ZYNQ_GEM_PHY_ADDR0	7 + +#define CONFIG_ZYNQ_SDHCI +#define CONFIG_ZYNQ_SDHCI0 + +/* MMC */ +#if defined(CONFIG_ZYNQ_SDHCI0) || defined(CONFIG_ZYNQ_SDHCI1) +# define CONFIG_MMC +# define CONFIG_GENERIC_MMC +# define CONFIG_SDHCI +# define CONFIG_ZYNQ_SDHCI +# define CONFIG_CMD_MMC +# define CONFIG_CMD_FAT +# define CONFIG_SUPPORT_VFAT +# define CONFIG_CMD_EXT2 +# define CONFIG_DOS_PARTITION +#endif + +#define CONFIG_ZYNQ_I2C0 + +/* I2C */ +#if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1) +# define CONFIG_CMD_I2C +# define CONFIG_ZYNQ_I2C +# define CONFIG_HARD_I2C +# define CONFIG_SYS_I2C_SPEED		100000 +# define CONFIG_SYS_I2C_SLAVE		1 +#endif  #if defined(CONFIG_ZYNQ_DCC)  # define CONFIG_ARM_DCC  # define CONFIG_CPU_V6 /* Required by CONFIG_ARM_DCC */  #endif +/* Enable the PL to be downloaded */ +#define CONFIG_FPGA +#define CONFIG_FPGA_XILINX +#define CONFIG_FPGA_ZYNQPL +#define CONFIG_CMD_FPGA +  #define CONFIG_BOOTP_SERVERIP  #define CONFIG_BOOTP_BOOTPATH  #define CONFIG_BOOTP_GATEWAY diff --git a/include/fpga.h b/include/fpga.h index 30a4e6a2e..38e9018c9 100644 --- a/include/fpga.h +++ b/include/fpga.h @@ -31,16 +31,6 @@  #define CONFIG_MAX_FPGA_DEVICES		5  #endif -/* CONFIG_FPGA bit assignments */ -#define CONFIG_SYS_FPGA_MAN(x)		(x) -#define CONFIG_SYS_FPGA_DEV(x)		((x) << 8 ) -#define CONFIG_SYS_FPGA_IF(x)		((x) << 16 ) - -/* FPGA Manufacturer bits in CONFIG_FPGA */ -#define CONFIG_SYS_FPGA_XILINX		CONFIG_SYS_FPGA_MAN( 0x1 ) -#define CONFIG_SYS_FPGA_ALTERA		CONFIG_SYS_FPGA_MAN( 0x2 ) - -  /* fpga_xxxx function return value definitions */  #define FPGA_SUCCESS		0  #define FPGA_FAIL		-1 @@ -68,7 +58,10 @@ extern void fpga_init(void);  extern int fpga_add(fpga_type devtype, void *desc);  extern int fpga_count(void);  extern int fpga_load(int devnum, const void *buf, size_t bsize); +extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size);  extern int fpga_dump(int devnum, const void *buf, size_t bsize);  extern int fpga_info(int devnum); +extern const fpga_desc *const fpga_validate(int devnum, const void *buf, +					    size_t bsize, char *fn);  #endif	/* _FPGA_H_ */ diff --git a/include/lattice.h b/include/lattice.h index 6a2cf93db..49871da22 100644 --- a/include/lattice.h +++ b/include/lattice.h @@ -278,9 +278,6 @@ typedef struct {  	char		*desc;	/* description string */  } Lattice_desc;			/* end, typedef Altera_desc */ -/* Lattice Model Type */ -#define CONFIG_SYS_XP2		CONFIG_SYS_FPGA_DEV(0x1) -  /* Board specific implementation specific function types */  typedef void (*Lattice_jtag_init)(void);  typedef void (*Lattice_jtag_set_tdi)(int v); diff --git a/include/netdev.h b/include/netdev.h index fd3e243c7..516b351eb 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -104,7 +104,7 @@ int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,  							int txpp, int rxpp);  int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,  						unsigned long ctrl_addr); -int zynq_gem_initialize(bd_t *bis, int base_addr); +int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio);  /*   * As long as the Xilinx xps_ll_temac ethernet driver has not its own interface   * exported by a public hader file, we need a global definition at this point. diff --git a/include/xilinx.h b/include/xilinx.h index 5f25b7a8a..9a64771c6 100644 --- a/include/xilinx.h +++ b/include/xilinx.h @@ -27,28 +27,6 @@  #ifndef _XILINX_H_  #define _XILINX_H_ -/* Xilinx Model definitions - *********************************************************************/ -#define CONFIG_SYS_SPARTAN2			CONFIG_SYS_FPGA_DEV( 0x1 ) -#define CONFIG_SYS_VIRTEX_E			CONFIG_SYS_FPGA_DEV( 0x2 ) -#define CONFIG_SYS_VIRTEX2			CONFIG_SYS_FPGA_DEV( 0x4 ) -#define CONFIG_SYS_SPARTAN3			CONFIG_SYS_FPGA_DEV( 0x8 ) -#define CONFIG_SYS_XILINX_SPARTAN2	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN2) -#define CONFIG_SYS_XILINX_VIRTEX_E	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX_E) -#define CONFIG_SYS_XILINX_VIRTEX2	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX2) -#define CONFIG_SYS_XILINX_SPARTAN3	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN3) -/* XXX - Add new models here */ - - -/* Xilinx Interface definitions - *********************************************************************/ -#define CONFIG_SYS_XILINX_IF_SS	CONFIG_SYS_FPGA_IF( 0x1 )	/* slave serial		*/ -#define CONFIG_SYS_XILINX_IF_MS	CONFIG_SYS_FPGA_IF( 0x2 )	/* master serial	*/ -#define CONFIG_SYS_XILINX_IF_SP	CONFIG_SYS_FPGA_IF( 0x4 )	/* slave parallel	*/ -#define CONFIG_SYS_XILINX_IF_JTAG	CONFIG_SYS_FPGA_IF( 0x8 )	/* jtag			*/ -#define CONFIG_SYS_XILINX_IF_MSM	CONFIG_SYS_FPGA_IF( 0x10 )	/* master selectmap	*/ -#define CONFIG_SYS_XILINX_IF_SSM	CONFIG_SYS_FPGA_IF( 0x20 )	/* slave selectmap	*/ -  /* Xilinx types   *********************************************************************/  typedef enum {			/* typedef Xilinx_iface */ @@ -59,6 +37,7 @@ typedef enum {			/* typedef Xilinx_iface */  	jtag_mode,		/* jtag/tap serial (not used ) */  	master_selectmap,	/* master SelectMap (virtex2)           */  	slave_selectmap,	/* slave SelectMap (virtex2)            */ +	devcfg,			/* devcfg interface (zynq) */  	max_xilinx_iface_type	/* insert all new types before this */  } Xilinx_iface;			/* end, typedef Xilinx_iface */ @@ -68,6 +47,7 @@ typedef enum {			/* typedef Xilinx_Family */  	Xilinx_VirtexE,		/* Virtex-E Family */  	Xilinx_Virtex2,		/* Virtex2 Family */  	Xilinx_Spartan3,	/* Spartan-III Family */ +	xilinx_zynq,		/* Zynq Family */  	max_xilinx_type		/* insert all new types before this */  } Xilinx_Family;		/* end, typedef Xilinx_Family */ @@ -77,6 +57,7 @@ typedef struct {		/* typedef Xilinx_desc */  	size_t size;		/* bytes of data part can accept */  	void *iface_fns;	/* interface function table */  	int cookie;		/* implementation specific cookie */ +	char *name;		/* device name in bitstream */  } Xilinx_desc;			/* end, typedef Xilinx_desc */  /* Generic Xilinx Functions diff --git a/include/zynqpl.h b/include/zynqpl.h new file mode 100644 index 000000000..0247ef61c --- /dev/null +++ b/include/zynqpl.h @@ -0,0 +1,59 @@ +/* + * (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 + */ + +#ifndef _ZYNQPL_H_ +#define _ZYNQPL_H_ + +#include <xilinx.h> + +extern int zynq_load(Xilinx_desc *desc, const void *image, size_t size); +extern int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize); +extern int zynq_info(Xilinx_desc *desc); + +#define XILINX_ZYNQ_7010	0x2 +#define XILINX_ZYNQ_7020	0x7 +#define XILINX_ZYNQ_7030	0xc +#define XILINX_ZYNQ_7045	0x11 + +/* Device Image Sizes */ +#define XILINX_XC7Z010_SIZE	16669920/8 +#define XILINX_XC7Z020_SIZE	32364512/8 +#define XILINX_XC7Z030_SIZE	47839328/8 +#define XILINX_XC7Z045_SIZE	106571232/8 + +/* Descriptor Macros */ +#define XILINX_XC7Z010_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z010_SIZE, NULL, cookie, "7z010" } + +#define XILINX_XC7Z020_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z020_SIZE, NULL, cookie, "7z020" } + +#define XILINX_XC7Z030_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z030_SIZE, NULL, cookie, "7z030" } + +#define XILINX_XC7Z045_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z045_SIZE, NULL, cookie, "7z045" } + +#endif /* _ZYNQPL_H_ */ |