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