xref: /rk3399_rockchip-uboot/drivers/fpga/spartan2.c (revision 4d16f67e7ba1a69929b55852f1a274c457a0db27)
1c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
2c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
3c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
7c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
8c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <common.h>		/* core U-Boot definitions */
9c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <spartan2.h>		/* Spartan-II device family */
10c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
11c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Define FPGA_DEBUG to get debug printf's */
12c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef	FPGA_DEBUG
13c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...)	printf (fmt ,##args)
14c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #else
15c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...)
16c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
17c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
18c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_CHECK_BUSY
19c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_PROG_FEEDBACK
20c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
21c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Note: The assumption is that we cannot possibly run fast enough to
22c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * overrun the device (the Slave Parallel mode can free run at 50MHz).
23c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
24c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * the board config file to slow things down.
25c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
26c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_FPGA_DELAY
27c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_FPGA_DELAY()
28c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
29c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
30c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_WAIT
31c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
32c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
33c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
34f8c1be98SMichal Simek static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
35f8c1be98SMichal Simek static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
36f8c1be98SMichal Simek /* static int spartan2_sp_info(xilinx_desc *desc ); */
37c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
38f8c1be98SMichal Simek static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
39f8c1be98SMichal Simek static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
40f8c1be98SMichal Simek /* static int spartan2_ss_info(xilinx_desc *desc ); */
41c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
42c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
43c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Generic Implementation */
spartan2_load(xilinx_desc * desc,const void * buf,size_t bsize,bitstream_type bstype)44*7a78bd26SMichal Simek static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
45*7a78bd26SMichal Simek 			 bitstream_type bstype)
46c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
47c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
48c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
49c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
50c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
51c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
52b625b9aeSMichal Simek 		ret_val = spartan2_ss_load(desc, buf, bsize);
53c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
54c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
55c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_parallel:
56c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
57b625b9aeSMichal Simek 		ret_val = spartan2_sp_load(desc, buf, bsize);
58c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
59c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
60c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
61c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
62c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
63c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
64c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
65c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
66c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
67c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_dump(xilinx_desc * desc,const void * buf,size_t bsize)6814cfc4f3SMichal Simek static int spartan2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
69c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
70c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
71c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
72c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
73c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
74c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
75b625b9aeSMichal Simek 		ret_val = spartan2_ss_dump(desc, buf, bsize);
76c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
77c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
78c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_parallel:
79c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
80b625b9aeSMichal Simek 		ret_val = spartan2_sp_dump(desc, buf, bsize);
81c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
82c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
83c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
84c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
85c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
86c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
87c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
88c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
89c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
90c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_info(xilinx_desc * desc)9114cfc4f3SMichal Simek static int spartan2_info(xilinx_desc *desc)
92c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
93c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_SUCCESS;
94c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
95c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
96c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
97c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
98c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Slave Parallel Generic Implementation */
99c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_sp_load(xilinx_desc * desc,const void * buf,size_t bsize)100f8c1be98SMichal Simek static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
101c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
102c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
103b625b9aeSMichal Simek 	xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
104c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
105c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	PRINTF ("%s: start with interface functions @ 0x%p\n",
106c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__, fn);
107c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
108c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
109c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
110c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
111c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
112c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned long ts;		/* timestamp */
113c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
114c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Function Table:\n"
115c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"ptr:\t0x%p\n"
116c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"struct: 0x%p\n"
117c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pre: 0x%p\n"
118c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pgm:\t0x%p\n"
119c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"init:\t0x%p\n"
120c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"err:\t0x%p\n"
121c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"clk:\t0x%p\n"
122c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"cs:\t0x%p\n"
123c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"wr:\t0x%p\n"
124c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"read data:\t0x%p\n"
125c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"write data:\t0x%p\n"
126c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"busy:\t0x%p\n"
127c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"abort:\t0x%p\n",
128c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"post:\t0x%p\n\n",
129c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
130c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
131c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->abort, fn->post);
132c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
133c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
134c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * This code is designed to emulate the "Express Style"
135c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Continuous Data Loading in Slave Parallel Mode for
136c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * the Spartan-II Family.
137c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
138c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
139c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Loading FPGA Device %d...\n", cookie);
140c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
141c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
142c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the pre configuration function if there is one.
143c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
144c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->pre) {
145c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->pre) (cookie);
146c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
147c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
148c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Establish the initial state */
149472d5460SYork Sun 		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
150c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
151c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get ready for the burn */
152c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
153472d5460SYork Sun 		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
154c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
155c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
156c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Now wait for INIT and BUSY to go high */
157c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
158c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
159c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
160c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to clear.\n");
161c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);	/* abort the burn */
162c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
163c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
164c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
165c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
166472d5460SYork Sun 		(*fn->wr) (true, true, cookie); /* Assert write, commit */
167472d5460SYork Sun 		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
168472d5460SYork Sun 		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
169c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
170c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Load the data */
171c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
172c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - do we check for an Ctrl-C press in here ??? */
173c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - Check the error bit? */
174c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
175472d5460SYork Sun 			(*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
176c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
177472d5460SYork Sun 			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
178c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
179472d5460SYork Sun 			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
180c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
181c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_BUSY
182c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			ts = get_timer (0);	/* get current time */
183c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			while ((*fn->busy) (cookie)) {
184c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* XXX - we should have a check in here somewhere to
185c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				 * make sure we aren't busy forever... */
186c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
187c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
188472d5460SYork Sun 				(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
189c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
190472d5460SYork Sun 				(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
191c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
192c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
193c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					puts ("** Timeout waiting for BUSY to clear.\n");
194c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					(*fn->abort) (cookie);	/* abort the burn */
195c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					return FPGA_FAIL;
196c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				}
197c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
198c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
199c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
200c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
201c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
202c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
203c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
204c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
205c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
206c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
207472d5460SYork Sun 		(*fn->cs) (false, true, cookie);	/* Deassert the chip select */
208472d5460SYork Sun 		(*fn->wr) (false, true, cookie);	/* Deassert the write pin */
209c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
210c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
211c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
212c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
213c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
214c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* now check for done signal */
215c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
216c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
217c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while ((*fn->done) (cookie) == FPGA_FAIL) {
218c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
219c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
220472d5460SYork Sun 			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
221c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
222472d5460SYork Sun 			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
223c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
224c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
225c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for DONE to clear.\n");
226c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);	/* abort the burn */
227c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				ret_val = FPGA_FAIL;
228c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				break;
229c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
230c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
231c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
232c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
233c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the post configuration function if there is one.
234c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
2353818b677SMatthias Fuchs 		if (*fn->post)
236c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->post) (cookie);
237c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
238c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
2393818b677SMatthias Fuchs 		if (ret_val == FPGA_SUCCESS)
2403818b677SMatthias Fuchs 			puts ("Done.\n");
2413818b677SMatthias Fuchs 		else
242c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Fail.\n");
243c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
244c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
245c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
246c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
247c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
248c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
249c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
250c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
251c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_sp_dump(xilinx_desc * desc,const void * buf,size_t bsize)252f8c1be98SMichal Simek static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
253c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
254c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
255b625b9aeSMichal Simek 	xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
256c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
257c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
258c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
259c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
260c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
261c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
262c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Starting Dump of FPGA Device %d...\n", cookie);
263c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
264472d5460SYork Sun 		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
265472d5460SYork Sun 		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
266c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
267c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* dump the data */
268c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
269c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - do we check for an Ctrl-C press in here ??? */
270c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
271472d5460SYork Sun 			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
272472d5460SYork Sun 			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
273c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
274c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
275c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
276c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
277c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
278c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
279c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
280472d5460SYork Sun 		(*fn->cs) (false, false, cookie);	/* Deassert the chip select */
281472d5460SYork Sun 		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
282472d5460SYork Sun 		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
283c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
284c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
285c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
286c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
287c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		puts ("Done.\n");
288c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
289c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* XXX - checksum the data? */
290c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
291c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
292c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
293c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
294c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
295c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
296c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
297c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
298c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
299c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_ss_load(xilinx_desc * desc,const void * buf,size_t bsize)300f8c1be98SMichal Simek static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
301c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
302c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
303b625b9aeSMichal Simek 	xilinx_spartan2_slave_serial_fns *fn = desc->iface_fns;
304c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int i;
305c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	unsigned char val;
306c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
307c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	PRINTF ("%s: start with interface functions @ 0x%p\n",
308c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__, fn);
309c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
310c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
311c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
312c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
313c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
314c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned long ts;		/* timestamp */
315c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
316c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Function Table:\n"
317c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"ptr:\t0x%p\n"
318c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"struct: 0x%p\n"
319c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pgm:\t0x%p\n"
320c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"init:\t0x%p\n"
321c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"clk:\t0x%p\n"
322c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"wr:\t0x%p\n"
323c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"done:\t0x%p\n\n",
324c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
325c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->clk, fn->wr, fn->done);
326c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
327c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Loading FPGA Device %d...\n", cookie);
328c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
329c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
330c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
331c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the pre configuration function if there is one.
332c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
333c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->pre) {
334c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->pre) (cookie);
335c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
336c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
337c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Establish the initial state */
338472d5460SYork Sun 		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
339c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
340c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Wait for INIT state (init low)                            */
341c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
342c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
343c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
344c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
345c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to start.\n");
346c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
347c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
348c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while (!(*fn->init) (cookie));
349c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
350c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get ready for the burn */
351c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
352472d5460SYork Sun 		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
353c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
354c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
355c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Now wait for INIT to go high */
356c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
357c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
358c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
359c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to clear.\n");
360c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
361c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
362c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while ((*fn->init) (cookie));
363c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
364c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Load the data */
365c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
366c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
367c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* Xilinx detects an error if INIT goes low (active)
368c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			   while DONE is low (inactive) */
369c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
370c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** CRC error during FPGA load.\n");
371c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return (FPGA_FAIL);
372c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
373c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			val = data [bytecount ++];
374c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			i = 8;
375c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			do {
376c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Deassert the clock */
377472d5460SYork Sun 				(*fn->clk) (false, true, cookie);
378c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
379c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Write data */
380472d5460SYork Sun 				(*fn->wr) ((val & 0x80), true, cookie);
381c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
382c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Assert the clock */
383472d5460SYork Sun 				(*fn->clk) (true, true, cookie);
384c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
385c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				val <<= 1;
386c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				i --;
387c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} while (i > 0);
388c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
389c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
390c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
391c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
392c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
393c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
394c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
395c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
396c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
397c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
398c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
399c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
400c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
401c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* now check for done signal */
402c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
403c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
404472d5460SYork Sun 		(*fn->wr) (true, true, cookie);
405c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
406c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (! (*fn->done) (cookie)) {
407c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
408c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
409472d5460SYork Sun 			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
410c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
411472d5460SYork Sun 			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
412c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
413c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			putc ('*');
414c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
415c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
416c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for DONE to clear.\n");
417c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				ret_val = FPGA_FAIL;
418c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				break;
419c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
420c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
421c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
422c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
423c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
424c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the post configuration function if there is one.
425c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
4263818b677SMatthias Fuchs 		if (*fn->post)
427c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->post) (cookie);
428c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
429c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
4303818b677SMatthias Fuchs 		if (ret_val == FPGA_SUCCESS)
431c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Done.\n");
4323818b677SMatthias Fuchs 		else
433c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Fail.\n");
434c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
435c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
436c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
437c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
438c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
439c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
440c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
441c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
442c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
spartan2_ss_dump(xilinx_desc * desc,const void * buf,size_t bsize)443f8c1be98SMichal Simek static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
444c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
445c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	/* Readback is only available through the Slave Parallel and         */
446c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	/* boundary-scan interfaces.                                         */
447c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	printf ("%s: Slave Serial Dumping is unavailable\n",
448c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__);
449c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_FAIL;
450c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
45114cfc4f3SMichal Simek 
45214cfc4f3SMichal Simek struct xilinx_fpga_op spartan2_op = {
45314cfc4f3SMichal Simek 	.load = spartan2_load,
45414cfc4f3SMichal Simek 	.dump = spartan2_dump,
45514cfc4f3SMichal Simek 	.info = spartan2_info,
45614cfc4f3SMichal Simek };
457