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