xref: /rk3399_rockchip-uboot/drivers/fpga/spartan2.c (revision c8aa7dfc18f7cc90d0aea6c7becbb67dfc5bba4b)
1*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /*
2*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
3*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
5*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * See file CREDITS for list of people who contributed to this
6*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * project.
7*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
8*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * This program is free software; you can redistribute it and/or
9*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * modify it under the terms of the GNU General Public License as
10*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * published by the Free Software Foundation; either version 2 of
11*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * the License, or (at your option) any later version.
12*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
13*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * This program is distributed in the hope that it will be useful,
14*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
16*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * GNU General Public License for more details.
17*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
18*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * You should have received a copy of the GNU General Public License
19*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * along with this program; if not, write to the Free Software
20*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * MA 02111-1307 USA
22*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  *
23*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
24*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
25*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <common.h>		/* core U-Boot definitions */
26*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <spartan2.h>		/* Spartan-II device family */
27*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
28*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Define FPGA_DEBUG to get debug printf's */
29*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef	FPGA_DEBUG
30*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...)	printf (fmt ,##args)
31*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #else
32*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...)
33*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
34*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
35*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_CHECK_BUSY
36*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_PROG_FEEDBACK
37*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
38*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Note: The assumption is that we cannot possibly run fast enough to
39*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * overrun the device (the Slave Parallel mode can free run at 50MHz).
40*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
41*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  * the board config file to slow things down.
42*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD  */
43*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_FPGA_DELAY
44*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_FPGA_DELAY()
45*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
46*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
47*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_WAIT
48*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
49*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
50*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
51*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_load( Xilinx_desc *desc, void *buf, size_t bsize );
52*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize );
53*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* static int Spartan2_sp_info( Xilinx_desc *desc ); */
54*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_reloc( Xilinx_desc *desc, ulong reloc_offset );
55*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
56*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_load( Xilinx_desc *desc, void *buf, size_t bsize );
57*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize );
58*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* static int Spartan2_ss_info( Xilinx_desc *desc ); */
59*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_reloc( Xilinx_desc *desc, ulong reloc_offset );
60*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
61*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
62*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Generic Implementation */
63*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_load (Xilinx_desc * desc, void *buf, size_t bsize)
64*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
65*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
66*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
67*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
68*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
69*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
70*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = Spartan2_ss_load (desc, buf, bsize);
71*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
72*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
73*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_parallel:
74*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
75*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = Spartan2_sp_load (desc, buf, bsize);
76*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
77*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
78*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
79*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
80*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
81*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
82*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
83*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
84*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
85*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
86*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
87*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
88*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;
89*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
90*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	switch (desc->iface) {
91*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_serial:
92*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
93*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = Spartan2_ss_dump (desc, buf, bsize);
94*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
95*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
96*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	case slave_parallel:
97*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
98*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = Spartan2_sp_dump (desc, buf, bsize);
99*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		break;
100*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
101*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	default:
102*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported interface type, %d\n",
103*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->iface);
104*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
105*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
106*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
107*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
108*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
109*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_info( Xilinx_desc *desc )
110*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
111*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_SUCCESS;
112*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
113*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
114*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
115*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_reloc (Xilinx_desc * desc, ulong reloc_offset)
116*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
117*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume a failure */
118*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
119*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (desc->family != Xilinx_Spartan2) {
120*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Unsupported family type, %d\n",
121*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, desc->family);
122*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		return FPGA_FAIL;
123*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else
124*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		switch (desc->iface) {
125*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_serial:
126*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			ret_val = Spartan2_ss_reloc (desc, reloc_offset);
127*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
128*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
129*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		case slave_parallel:
130*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			ret_val = Spartan2_sp_reloc (desc, reloc_offset);
131*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			break;
132*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
133*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		default:
134*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			printf ("%s: Unsupported interface type, %d\n",
135*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					__FUNCTION__, desc->iface);
136*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
137*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
138*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
139*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
140*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
141*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
142*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
143*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Slave Parallel Generic Implementation */
144*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
145*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_load (Xilinx_desc * desc, void *buf, size_t bsize)
146*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
147*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
148*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
149*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
150*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	PRINTF ("%s: start with interface functions @ 0x%p\n",
151*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__, fn);
152*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
153*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
154*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
155*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
156*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
157*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned long ts;		/* timestamp */
158*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
159*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Function Table:\n"
160*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"ptr:\t0x%p\n"
161*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"struct: 0x%p\n"
162*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pre: 0x%p\n"
163*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pgm:\t0x%p\n"
164*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"init:\t0x%p\n"
165*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"err:\t0x%p\n"
166*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"clk:\t0x%p\n"
167*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"cs:\t0x%p\n"
168*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"wr:\t0x%p\n"
169*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"read data:\t0x%p\n"
170*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"write data:\t0x%p\n"
171*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"busy:\t0x%p\n"
172*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"abort:\t0x%p\n",
173*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"post:\t0x%p\n\n",
174*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
175*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
176*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->abort, fn->post);
177*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
178*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
179*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * This code is designed to emulate the "Express Style"
180*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Continuous Data Loading in Slave Parallel Mode for
181*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * the Spartan-II Family.
182*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
183*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
184*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Loading FPGA Device %d...\n", cookie);
185*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
186*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
187*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the pre configuration function if there is one.
188*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
189*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->pre) {
190*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->pre) (cookie);
191*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
192*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
193*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Establish the initial state */
194*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->pgm) (TRUE, TRUE, cookie);	/* Assert the program, commit */
195*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
196*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get ready for the burn */
197*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
198*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->pgm) (FALSE, TRUE, cookie);	/* Deassert the program, commit */
199*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
200*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
201*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Now wait for INIT and BUSY to go high */
202*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
203*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
204*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
205*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to clear.\n");
206*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);	/* abort the burn */
207*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
208*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
209*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
210*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
211*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */
212*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
213*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
214*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
215*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Load the data */
216*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
217*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - do we check for an Ctrl-C press in here ??? */
218*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - Check the error bit? */
219*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
220*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */
221*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
222*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
223*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
224*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
225*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
226*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_BUSY
227*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			ts = get_timer (0);	/* get current time */
228*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			while ((*fn->busy) (cookie)) {
229*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* XXX - we should have a check in here somewhere to
230*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				 * make sure we aren't busy forever... */
231*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
232*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
233*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
234*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
235*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
236*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
237*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
238*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					puts ("** Timeout waiting for BUSY to clear.\n");
239*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					(*fn->abort) (cookie);	/* abort the burn */
240*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					return FPGA_FAIL;
241*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				}
242*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
243*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
244*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
245*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
246*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
247*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
248*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
249*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
250*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
251*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
252*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->cs) (FALSE, TRUE, cookie);	/* Deassert the chip select */
253*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->wr) (FALSE, TRUE, cookie);	/* Deassert the write pin */
254*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
255*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
256*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
257*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
258*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
259*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* now check for done signal */
260*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
261*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
262*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while ((*fn->done) (cookie) == FPGA_FAIL) {
263*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - we should have a check in here somewhere to
264*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 * make sure we aren't busy forever... */
265*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
266*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
267*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
268*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
269*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
270*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
271*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
272*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for DONE to clear.\n");
273*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->abort) (cookie);	/* abort the burn */
274*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				ret_val = FPGA_FAIL;
275*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				break;
276*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
277*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
278*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
279*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (ret_val == FPGA_SUCCESS) {
280*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
281*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Done.\n");
282*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
283*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
284*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
285*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the post configuration function if there is one.
286*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
287*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->post) {
288*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->post) (cookie);
289*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
290*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
291*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		else {
292*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
293*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Fail.\n");
294*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
295*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
296*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
297*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
298*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
299*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
300*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
301*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
302*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
303*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
304*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize)
305*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
306*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
307*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
308*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
309*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
310*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
311*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
312*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
313*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
314*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Starting Dump of FPGA Device %d...\n", cookie);
315*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
316*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
317*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
318*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
319*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* dump the data */
320*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
321*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - do we check for an Ctrl-C press in here ??? */
322*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
323*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
324*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
325*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
326*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
327*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
328*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
329*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
330*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
331*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
332*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->cs) (FALSE, FALSE, cookie);	/* Deassert the chip select */
333*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
334*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
335*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
336*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
337*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
338*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
339*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		puts ("Done.\n");
340*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
341*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* XXX - checksum the data? */
342*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
343*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
344*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
345*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
346*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
347*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
348*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
349*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
350*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_reloc (Xilinx_desc * desc, ulong reloc_offset)
351*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
352*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
353*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	Xilinx_Spartan2_Slave_Parallel_fns *fn_r, *fn =
354*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(Xilinx_Spartan2_Slave_Parallel_fns *) (desc->iface_fns);
355*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
356*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
357*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ulong addr;
358*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
359*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get the relocated table address */
360*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		addr = (ulong) fn + reloc_offset;
361*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		fn_r = (Xilinx_Spartan2_Slave_Parallel_fns *) addr;
362*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
363*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (!fn_r->relocated) {
364*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
365*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (memcmp (fn_r, fn,
366*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						sizeof (Xilinx_Spartan2_Slave_Parallel_fns))
367*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				== 0) {
368*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* good copy of the table, fix the descriptor pointer */
369*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				desc->iface_fns = fn_r;
370*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} else {
371*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				PRINTF ("%s: Invalid function table at 0x%p\n",
372*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						__FUNCTION__, fn_r);
373*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
374*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
375*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
376*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
377*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					desc);
378*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
379*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->pre) + reloc_offset;
380*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->pre = (Xilinx_pre_fn) addr;
381*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
382*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->pgm) + reloc_offset;
383*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->pgm = (Xilinx_pgm_fn) addr;
384*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
385*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->init) + reloc_offset;
386*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->init = (Xilinx_init_fn) addr;
387*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
388*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->done) + reloc_offset;
389*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->done = (Xilinx_done_fn) addr;
390*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
391*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->clk) + reloc_offset;
392*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->clk = (Xilinx_clk_fn) addr;
393*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
394*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->err) + reloc_offset;
395*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->err = (Xilinx_err_fn) addr;
396*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
397*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->cs) + reloc_offset;
398*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->cs = (Xilinx_cs_fn) addr;
399*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
400*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->wr) + reloc_offset;
401*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->wr = (Xilinx_wr_fn) addr;
402*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
403*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->rdata) + reloc_offset;
404*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->rdata = (Xilinx_rdata_fn) addr;
405*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
406*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->wdata) + reloc_offset;
407*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->wdata = (Xilinx_wdata_fn) addr;
408*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
409*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->busy) + reloc_offset;
410*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->busy = (Xilinx_busy_fn) addr;
411*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
412*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->abort) + reloc_offset;
413*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->abort = (Xilinx_abort_fn) addr;
414*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
415*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->post) + reloc_offset;
416*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->post = (Xilinx_post_fn) addr;
417*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
418*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->relocated = TRUE;
419*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
420*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else {
421*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* this table has already been moved */
422*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - should check to see if the descriptor is correct */
423*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			desc->iface_fns = fn_r;
424*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
425*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
426*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
427*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
428*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
429*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
430*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
431*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
432*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
433*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
434*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
435*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */
436*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
437*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
438*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
439*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
440*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
441*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int i;
442*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	unsigned char val;
443*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
444*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	PRINTF ("%s: start with interface functions @ 0x%p\n",
445*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__, fn);
446*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
447*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
448*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		size_t bytecount = 0;
449*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned char *data = (unsigned char *) buf;
450*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		int cookie = desc->cookie;	/* make a local copy */
451*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		unsigned long ts;		/* timestamp */
452*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
453*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		PRINTF ("%s: Function Table:\n"
454*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"ptr:\t0x%p\n"
455*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"struct: 0x%p\n"
456*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"pgm:\t0x%p\n"
457*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"init:\t0x%p\n"
458*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"clk:\t0x%p\n"
459*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"wr:\t0x%p\n"
460*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				"done:\t0x%p\n\n",
461*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
462*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn->clk, fn->wr, fn->done);
463*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
464*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("Loading FPGA Device %d...\n", cookie);
465*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
466*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
467*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
468*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the pre configuration function if there is one.
469*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
470*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->pre) {
471*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->pre) (cookie);
472*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
473*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
474*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Establish the initial state */
475*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->pgm) (TRUE, TRUE, cookie);	/* Assert the program, commit */
476*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
477*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Wait for INIT state (init low)                            */
478*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
479*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
480*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
481*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
482*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to start.\n");
483*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
484*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
485*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while (!(*fn->init) (cookie));
486*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
487*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get ready for the burn */
488*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
489*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->pgm) (FALSE, TRUE, cookie);	/* Deassert the program, commit */
490*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
491*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
492*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Now wait for INIT to go high */
493*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		do {
494*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
495*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
496*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for INIT to clear.\n");
497*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
498*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
499*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} while ((*fn->init) (cookie));
500*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
501*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Load the data */
502*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (bytecount < bsize) {
503*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
504*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* Xilinx detects an error if INIT goes low (active)
505*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			   while DONE is low (inactive) */
506*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
507*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** CRC error during FPGA load.\n");
508*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return (FPGA_FAIL);
509*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
510*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			val = data [bytecount ++];
511*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			i = 8;
512*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			do {
513*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Deassert the clock */
514*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->clk) (FALSE, TRUE, cookie);
515*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
516*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Write data */
517*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->wr) ((val & 0x80), TRUE, cookie);
518*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
519*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* Assert the clock */
520*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				(*fn->clk) (TRUE, TRUE, cookie);
521*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				CONFIG_FPGA_DELAY ();
522*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				val <<= 1;
523*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				i --;
524*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} while (i > 0);
525*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
526*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
527*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (bytecount % (bsize / 40) == 0)
528*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				putc ('.');		/* let them know we are alive */
529*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
530*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
531*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
532*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		CONFIG_FPGA_DELAY ();
533*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
534*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
535*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
536*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
537*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
538*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* now check for done signal */
539*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ts = get_timer (0);		/* get current time */
540*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
541*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		(*fn->wr) (TRUE, TRUE, cookie);
542*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
543*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		while (! (*fn->done) (cookie)) {
544*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - we should have a check in here somewhere to
545*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			 * make sure we aren't busy forever... */
546*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
547*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
548*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */
549*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			CONFIG_FPGA_DELAY ();
550*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */
551*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
552*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			putc ('*');
553*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
554*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
555*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				puts ("** Timeout waiting for DONE to clear.\n");
556*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				ret_val = FPGA_FAIL;
557*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				break;
558*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
559*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
560*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		putc ('\n');			/* terminate the dotted line */
561*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
562*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/*
563*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 * Run the post configuration function if there is one.
564*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		 */
565*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (*fn->post) {
566*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(*fn->post) (cookie);
567*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
568*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
569*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
570*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (ret_val == FPGA_SUCCESS) {
571*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Done.\n");
572*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
573*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		else {
574*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			puts ("Fail.\n");
575*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
576*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif
577*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
578*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
579*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
580*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
581*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
582*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
583*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
584*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
585*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
586*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
587*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	/* Readback is only available through the Slave Parallel and         */
588*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	/* boundary-scan interfaces.                                         */
589*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	printf ("%s: Slave Serial Dumping is unavailable\n",
590*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			__FUNCTION__);
591*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return FPGA_FAIL;
592*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
593*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
594*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
595*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD {
596*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	int ret_val = FPGA_FAIL;	/* assume the worst */
597*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	Xilinx_Spartan2_Slave_Serial_fns *fn_r, *fn =
598*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			(Xilinx_Spartan2_Slave_Serial_fns *) (desc->iface_fns);
599*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
600*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	if (fn) {
601*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ulong addr;
602*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
603*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		/* Get the relocated table address */
604*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		addr = (ulong) fn + reloc_offset;
605*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		fn_r = (Xilinx_Spartan2_Slave_Serial_fns *) addr;
606*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
607*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		if (!fn_r->relocated) {
608*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
609*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (memcmp (fn_r, fn,
610*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						sizeof (Xilinx_Spartan2_Slave_Serial_fns))
611*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				== 0) {
612*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				/* good copy of the table, fix the descriptor pointer */
613*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				desc->iface_fns = fn_r;
614*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			} else {
615*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				PRINTF ("%s: Invalid function table at 0x%p\n",
616*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 						__FUNCTION__, fn_r);
617*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				return FPGA_FAIL;
618*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
619*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
620*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
621*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 					desc);
622*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
623*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (fn->pre) {
624*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				addr = (ulong) (fn->pre) + reloc_offset;
625*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn_r->pre = (Xilinx_pre_fn) addr;
626*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
627*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
628*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->pgm) + reloc_offset;
629*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->pgm = (Xilinx_pgm_fn) addr;
630*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
631*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->init) + reloc_offset;
632*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->init = (Xilinx_init_fn) addr;
633*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
634*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->done) + reloc_offset;
635*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->done = (Xilinx_done_fn) addr;
636*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
637*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->clk) + reloc_offset;
638*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->clk = (Xilinx_clk_fn) addr;
639*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
640*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			addr = (ulong) (fn->wr) + reloc_offset;
641*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->wr = (Xilinx_wr_fn) addr;
642*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
643*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			if (fn->post) {
644*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				addr = (ulong) (fn->post) + reloc_offset;
645*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 				fn_r->post = (Xilinx_post_fn) addr;
646*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			}
647*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
648*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			fn_r->relocated = TRUE;
649*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
650*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		} else {
651*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* this table has already been moved */
652*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			/* XXX - should check to see if the descriptor is correct */
653*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 			desc->iface_fns = fn_r;
654*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		}
655*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
656*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		ret_val = FPGA_SUCCESS;
657*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	} else {
658*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
659*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	}
660*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
661*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 	return ret_val;
662*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 
663*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD }
664