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