xref: /openbmc/u-boot/drivers/fpga/virtex2.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
3c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
4c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
5c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Keith Outwater, keith_outwater@mvis.com
6c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
7c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
8c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
9c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Configuration support for Xilinx Virtex2 devices.  Based
10c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * on spartan2.c (Rich Ireland, rireland@enterasys.com).
11c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
12c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
13c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
1424b852a7SSimon Glass #include <console.h>
15c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <virtex2.h>
16c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
17c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #if 0
18c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define FPGA_DEBUG
19c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
20c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
21c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef	FPGA_DEBUG
22c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define	PRINTF(fmt,args...)	printf (fmt ,##args)
23c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #else
24c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...)
25c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
26c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
27c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
28c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * If the SelectMap interface can be overrun by the processor, define
29c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
30c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * file and add board-specific support for checking BUSY status. By default,
31c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * assume that the SelectMap interface cannot be overrun.
32c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
33c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_CHECK_BUSY
34c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_CHECK_BUSY
35c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
36c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
37c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_FPGA_DELAY
38c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_FPGA_DELAY()
39c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
40c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
41c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
42c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_PROG_FEEDBACK
43c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
44c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
45c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
46c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Don't allow config cycle to be interrupted
47c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
48c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
49c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_CHECK_CTRLC
50c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
51c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
52c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
53c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Check for errors during configuration by default
54c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
55c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_CHECK_ERROR
56c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_CHECK_ERROR
57c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
58c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
59c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
60c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * The default timeout in mS for INIT_B to deassert after PROG_B has
61c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * been deasserted. Per the latest Virtex II Handbook (page 347), the
62c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
63c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * data frame for the XC2V8000.  The XC2V8000 has 2860 data frames
64c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * which yields 11.44 mS.  So let's make it bigger in order to handle
65c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * an XC2V1000, if anyone can ever get ahold of one.
66c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
67c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_WAIT_INIT
68c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT_INIT	CONFIG_SYS_HZ/2	/* 500 ms */
69c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
70c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
71c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
72c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * The default timeout for waiting for BUSY to deassert during configuration.
73c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * This is normally not necessary since for most reasonable configuration
74c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
75c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
76c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_WAIT_BUSY
77c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT_BUSY	CONFIG_SYS_HZ/200	/* 5 ms*/
78c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
79c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
80c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Default timeout for waiting for FPGA to enter operational mode after
81c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * configuration data has been written.
82c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
83c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef	CONFIG_SYS_FPGA_WAIT_CONFIG
84c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT_CONFIG	CONFIG_SYS_HZ/5	/* 200 ms */
85c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
86c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
87f8c1be98SMichal Simek static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
88f8c1be98SMichal Simek static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
89c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
90f8c1be98SMichal Simek static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
91f8c1be98SMichal Simek static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
92c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
virtex2_load(xilinx_desc * desc,const void * buf,size_t bsize,bitstream_type bstype)937a78bd26SMichal Simek static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
947a78bd26SMichal Simek 			bitstream_type bstype)
95c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
96c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
97c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
98c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
99c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
100c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
101d9071ce0SMichal Simek 		ret_val = virtex2_ss_load(desc, buf, bsize);
102c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
103c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
104c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_selectmap:
105c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
106d9071ce0SMichal Simek 		ret_val = virtex2_ssm_load(desc, buf, bsize);
107c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
108c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
109c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
110c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
111c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
112c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
113c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
114c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
115c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
virtex2_dump(xilinx_desc * desc,const void * buf,size_t bsize)11614cfc4f3SMichal Simek static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
117c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
118c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
119c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
120c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
121c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
122c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
123d9071ce0SMichal Simek 		ret_val = virtex2_ss_dump(desc, buf, bsize);
124c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
125c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
126c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_parallel:
127c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
128d9071ce0SMichal Simek 		ret_val = virtex2_ssm_dump(desc, buf, bsize);
129c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
130c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
131c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
132c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
133c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
134c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
135c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
136c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
137c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
virtex2_info(xilinx_desc * desc)13814cfc4f3SMichal Simek static int virtex2_info(xilinx_desc *desc)
139c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
140c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_SUCCESS;
141c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
142c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
143c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
144c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Virtex-II Slave SelectMap configuration loader. Configuration via
145c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * SelectMap is as follows:
146c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * 1. Set the FPGA's PROG_B line low.
147c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * 2. Set the FPGA's PROG_B line high.  Wait for INIT_B to go high.
148c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * 3. Write data to the SelectMap port.  If INIT_B goes low at any time
149c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    this process, a configuration error (most likely CRC failure) has
150c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    ocurred.  At this point a status word may be read from the
151c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    SelectMap interface to determine the source of the problem (You
152c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    could, for instance, put this in your 'abort' function handler).
153c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * 4. After all data has been written, test the state of the FPGA
154c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    INIT_B and DONE lines.  If both are high, configuration has
155c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *    succeeded. Congratulations!
156c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
virtex2_ssm_load(xilinx_desc * desc,const void * buf,size_t bsize)157f8c1be98SMichal Simek static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
158c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
159c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
160d9071ce0SMichal Simek 	xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
161c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
162c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
163c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__, __LINE__, fn);
164c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
165c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
166c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
167c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
168c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;
169c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned long ts;
170c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
171c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Gotta split this one up (so the stack won't blow??) */
172c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s:%d: Function Table:\n"
173c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  base   0x%p\n"
174c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  struct 0x%p\n"
175c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  pre    0x%p\n"
176c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  prog   0x%p\n"
177c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  init   0x%p\n"
178c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  error  0x%p\n",
179c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, __LINE__,
180c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				&fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
181c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("  clock  0x%p\n"
182c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  cs     0x%p\n"
183c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  write  0x%p\n"
184c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  rdata  0x%p\n"
185c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  wdata  0x%p\n"
186c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  busy   0x%p\n"
187c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  abort  0x%p\n"
188c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"  post   0x%p\n\n",
189c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
190c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->busy, fn->abort, fn->post);
191c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
192c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
193c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Initializing FPGA Device %d...\n", cookie);
194c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
195c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
196c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the pre configuration function if there is one.
197c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
198c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->pre) {
199c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->pre) (cookie);
200c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
201c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
202c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
203c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Assert the program line.  The minimum pulse width for
204c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
205c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * There is no maximum value for the pulse width.  Check to make
206c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * sure that INIT_B goes low after assertion of PROG_B
207c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
208472d5460SYork Sun 		(*fn->pgm) (true, true, cookie);
209c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		udelay (10);
210c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);
211c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
212c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
213c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
214c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						" to assert.\n", __FUNCTION__, __LINE__,
215c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						CONFIG_SYS_FPGA_WAIT_INIT);
216c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
217c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
218c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
219c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while (!(*fn->init) (cookie));
220c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
221472d5460SYork Sun 		(*fn->pgm) (false, true, cookie);
222c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
223472d5460SYork Sun 		(*fn->clk) (true, true, cookie);
224c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
225c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
226c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Start a timer and wait for INIT_B to go high
227c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
228c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);
229c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
230c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
231c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
232c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
233c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						" to deassert.\n", __FUNCTION__, __LINE__,
234c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						CONFIG_SYS_FPGA_WAIT_INIT);
235c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
236c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
237c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
238c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
239c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
240472d5460SYork Sun 		(*fn->wr) (true, true, cookie);
241472d5460SYork Sun 		(*fn->cs) (true, true, cookie);
242c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
243c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		udelay (10000);
244c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
245c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
246c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Load the data byte by byte
247c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
248c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
249c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
250c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (ctrlc ()) {
251c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
252c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
253c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
254c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
255c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
256c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((*fn->done) (cookie) == FPGA_SUCCESS) {
257c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			    PRINTF ("%s:%d:done went active early, bytecount = %d\n",
258c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				    __FUNCTION__, __LINE__, bytecount);
259c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			    break;
260c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
261c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
262c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_ERROR
263c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((*fn->init) (cookie)) {
264c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("\n%s:%d:  ** Error: INIT asserted during"
265c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						" configuration\n", __FUNCTION__, __LINE__);
266c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%d = buffer offset, %d = buffer size\n",
267c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					bytecount, bsize);
268c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
269c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
270c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
271c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
272c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
273472d5460SYork Sun 			(*fn->wdata) (data[bytecount++], true, cookie);
274c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
275c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
276c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/*
277c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 * Cycle the clock pin
278c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 */
279472d5460SYork Sun 			(*fn->clk) (false, true, cookie);
280c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
281472d5460SYork Sun 			(*fn->clk) (true, true, cookie);
282c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
283c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_BUSY
284c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			ts = get_timer (0);
285c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			while ((*fn->busy) (cookie)) {
286c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
287c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					printf ("%s:%d: ** Timeout after %d ticks waiting for"
288c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 							" BUSY to deassert\n",
289c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 							__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
290c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					(*fn->abort) (cookie);
291c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					return FPGA_FAIL;
292c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				}
293c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
294c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
295c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
296c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
297c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
298c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');
299c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
300c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
301c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
302c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
303c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
304c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
305c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
306472d5460SYork Sun 		(*fn->cs) (false, true, cookie);
307472d5460SYork Sun 		(*fn->wr) (false, true, cookie);
308c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
309c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
310c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');
311c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
312c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
313c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
314c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Check for successful configuration.  FPGA INIT_B and DONE should
315c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * both be high upon successful configuration.
316c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
317c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);
318c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
319c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
320c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
321c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
322c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						"assert and INIT to deassert\n",
323c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
324c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
325c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				ret_val = FPGA_FAIL;
326c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				break;
327c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
328c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
329c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
330c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (ret_val == FPGA_SUCCESS) {
331c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
332c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("Initialization of FPGA device %d complete\n", cookie);
333c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
334c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/*
335c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 * Run the post configuration function if there is one.
336c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 */
337c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (*fn->post) {
338c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->post) (cookie);
339c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
340c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else {
341c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
342c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("** Initialization of FPGA device %d FAILED\n",
343c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					cookie);
344c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
345c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
346c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
347c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s:%d: NULL Interface function table!\n",
348c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, __LINE__);
349c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
350c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
351c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
352c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
353c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
354c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Read the FPGA configuration data
355c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
virtex2_ssm_dump(xilinx_desc * desc,const void * buf,size_t bsize)356f8c1be98SMichal Simek static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
357c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
358c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
359d9071ce0SMichal Simek 	xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
360c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
361c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
362c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
363c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
364c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;
365c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
366c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Starting Dump of FPGA Device %d...\n", cookie);
367c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
368472d5460SYork Sun 		(*fn->cs) (true, true, cookie);
369472d5460SYork Sun 		(*fn->clk) (true, true, cookie);
370c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
371c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
372c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
373c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (ctrlc ()) {
374c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);
375c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
376c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
377c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
378c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/*
379c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 * Cycle the clock and read the data
380c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 */
381472d5460SYork Sun 			(*fn->clk) (false, true, cookie);
382472d5460SYork Sun 			(*fn->clk) (true, true, cookie);
383c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->rdata) (&(data[bytecount++]), cookie);
384c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
385c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
386c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');
387c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
388c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
389c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
390c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
391c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Deassert CS_B and cycle the clock to deselect the device.
392c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
393472d5460SYork Sun 		(*fn->cs) (false, false, cookie);
394472d5460SYork Sun 		(*fn->clk) (false, true, cookie);
395472d5460SYork Sun 		(*fn->clk) (true, true, cookie);
396c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
397c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
398c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');
399c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
400c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		puts ("Done.\n");
401c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
402c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s:%d: NULL Interface function table!\n",
403c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, __LINE__);
404c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
405c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
406c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
407c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
virtex2_ss_load(xilinx_desc * desc,const void * buf,size_t bsize)408f8c1be98SMichal Simek static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
409c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
410c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
411c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_FAIL;
412c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
413c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
virtex2_ss_dump(xilinx_desc * desc,const void * buf,size_t bsize)414f8c1be98SMichal Simek static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
415c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
416c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
417c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_FAIL;
418c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
419c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
420c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* vim: set ts=4 tw=78: */
42114cfc4f3SMichal Simek 
42214cfc4f3SMichal Simek struct xilinx_fpga_op virtex2_op = {
42314cfc4f3SMichal Simek 	.load = virtex2_load,
42414cfc4f3SMichal Simek 	.dump = virtex2_dump,
42514cfc4f3SMichal Simek 	.info = virtex2_info,
42614cfc4f3SMichal Simek };
427