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