]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/ACEX1K.c
* Patch by Steven Scholz, 10 Oct 2003
[karo-tx-uboot.git] / common / ACEX1K.c
1 /*
2  * (C) Copyright 2003
3  * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
4  *
5  * (C) Copyright 2002
6  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  *
26  */
27
28 #include <common.h>             /* core U-Boot definitions */
29 #include <ACEX1K.h>             /* ACEX device family */
30
31 #if (CONFIG_FPGA & (CFG_ALTERA | CFG_ACEX1K))
32
33 /* Define FPGA_DEBUG to get debug printf's */
34 /* #define FPGA_DEBUG */
35
36 #ifdef  FPGA_DEBUG
37 #define PRINTF(fmt,args...)     printf (fmt ,##args)
38 #else
39 #define PRINTF(fmt,args...)
40 #endif
41
42 #undef CFG_FPGA_CHECK_BUSY
43 #define CFG_FPGA_PROG_FEEDBACK
44
45 /* Note: The assumption is that we cannot possibly run fast enough to
46  * overrun the device (the Slave Parallel mode can free run at 50MHz).
47  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
48  * the board config file to slow things down.
49  */
50 #ifndef CONFIG_FPGA_DELAY
51 #define CONFIG_FPGA_DELAY()
52 #endif
53
54 #ifndef CFG_FPGA_WAIT
55 #define CFG_FPGA_WAIT 100
56 #endif
57
58 static int ACEX1K_ps_load( Altera_desc *desc, void *buf, size_t bsize );
59 static int ACEX1K_ps_dump( Altera_desc *desc, void *buf, size_t bsize );
60 /* static int ACEX1K_ps_info( Altera_desc *desc ); */
61 static int ACEX1K_ps_reloc( Altera_desc *desc, ulong reloc_offset );
62
63 /* ------------------------------------------------------------------------- */
64 /* ACEX1K Generic Implementation */
65 int ACEX1K_load (Altera_desc * desc, void *buf, size_t bsize)
66 {
67         int ret_val = FPGA_FAIL;
68
69         switch (desc->iface) {
70         case passive_serial:
71                 PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
72                 ret_val = ACEX1K_ps_load (desc, buf, bsize);
73                 break;
74
75                 /* Add new interface types here */
76
77         default:
78                 printf ("%s: Unsupported interface type, %d\n",
79                                 __FUNCTION__, desc->iface);
80         }
81
82         return ret_val;
83 }
84
85 int ACEX1K_dump (Altera_desc * desc, void *buf, size_t bsize)
86 {
87         int ret_val = FPGA_FAIL;
88
89         switch (desc->iface) {
90         case passive_serial:
91                 PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
92                 ret_val = ACEX1K_ps_dump (desc, buf, bsize);
93                 break;
94
95                 /* Add new interface types here */
96
97         default:
98                 printf ("%s: Unsupported interface type, %d\n",
99                                 __FUNCTION__, desc->iface);
100         }
101
102         return ret_val;
103 }
104
105 int ACEX1K_info( Altera_desc *desc )
106 {
107         return FPGA_SUCCESS;
108 }
109
110
111 int ACEX1K_reloc (Altera_desc * desc, ulong reloc_offset)
112 {
113         int ret_val = FPGA_FAIL;        /* assume a failure */
114
115         if (desc->family != Altera_ACEX1K) {
116                 printf ("%s: Unsupported family type, %d\n",
117                                 __FUNCTION__, desc->family);
118                 return FPGA_FAIL;
119         } else
120                 switch (desc->iface) {
121                 case passive_serial:
122                         ret_val = ACEX1K_ps_reloc (desc, reloc_offset);
123                         break;
124
125                 /* Add new interface types here */
126
127                 default:
128                         printf ("%s: Unsupported interface type, %d\n",
129                                         __FUNCTION__, desc->iface);
130                 }
131
132         return ret_val;
133 }
134
135
136 /* ------------------------------------------------------------------------- */
137 /* ACEX1K Passive Serial Generic Implementation                                  */
138
139 static int ACEX1K_ps_load (Altera_desc * desc, void *buf, size_t bsize)
140 {
141         int ret_val = FPGA_FAIL;        /* assume the worst */
142         Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
143         int i;
144
145         PRINTF ("%s: start with interface functions @ 0x%p\n",
146                         __FUNCTION__, fn);
147
148         if (fn) {
149                 size_t bytecount = 0;
150                 unsigned char *data = (unsigned char *) buf;
151                 int cookie = desc->cookie;      /* make a local copy */
152                 unsigned long ts;               /* timestamp */
153
154                 PRINTF ("%s: Function Table:\n"
155                                 "ptr:\t0x%p\n"
156                                 "struct: 0x%p\n"
157                                 "config:\t0x%p\n"
158                                 "status:\t0x%p\n"
159                                 "clk:\t0x%p\n"
160                                 "data:\t0x%p\n"
161                                 "done:\t0x%p\n\n",
162                                 __FUNCTION__, &fn, fn, fn->config, fn->status,
163                                 fn->clk, fn->data, fn->done);
164 #ifdef CFG_FPGA_PROG_FEEDBACK
165                 printf ("Loading FPGA Device %d (@ %ld)...\n", cookie, ts);
166 #endif
167
168                 /*
169                  * Run the pre configuration function if there is one.
170                  */
171                 if (*fn->pre) {
172                         (*fn->pre) (cookie);
173                 }
174
175                 /* Establish the initial state */
176                 (*fn->config) (TRUE, TRUE, cookie);     /* Assert nCONFIG */
177
178                 udelay(2);              /* T_cfg > 2us  */
179
180                 /* nSTATUS should be asserted now */
181                 (*fn->done) (cookie);
182                 if ( !(*fn->status) (cookie) ) {
183                         puts ("** nSTATUS is not asserted.\n");
184                         (*fn->abort) (cookie);
185                         return FPGA_FAIL;
186                 }
187
188                 (*fn->config) (FALSE, TRUE, cookie);    /* Deassert nCONFIG */
189                 udelay(2);              /* T_cf2st1 < 4us       */
190
191                 /* Wait for nSTATUS to be released (i.e. deasserted) */
192                 ts = get_timer (0);             /* get current time */
193                 do {
194                         CONFIG_FPGA_DELAY ();
195                         if (get_timer (ts) > CFG_FPGA_WAIT) {   /* check the time */
196                                 puts ("** Timeout waiting for STATUS to go high.\n");
197                                 (*fn->abort) (cookie);
198                                 return FPGA_FAIL;
199                         }
200                         (*fn->done) (cookie);
201                 } while ((*fn->status) (cookie));
202
203                 /* Get ready for the burn */
204                 CONFIG_FPGA_DELAY ();
205
206                 /* Load the data */
207                 while (bytecount < bsize) {
208                         unsigned char val=0;
209 #ifdef CFG_FPGA_CHECK_CTRLC
210                         if (ctrlc ()) {
211                                 (*fn->abort) (cookie);
212                                 return FPGA_FAIL;
213                         }
214 #endif
215                         /* Altera detects an error if INIT goes low (active)
216                            while DONE is low (inactive) */
217 #if 0 /* not yet implemented */
218                         if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
219                                 puts ("** CRC error during FPGA load.\n");
220                                 (*fn->abort) (cookie);
221                                 return (FPGA_FAIL);
222                         }
223 #endif
224                         val = data [bytecount ++ ];
225                         i = 8;
226                         do {
227                                 /* Deassert the clock */
228                                 (*fn->clk) (FALSE, TRUE, cookie);
229                                 CONFIG_FPGA_DELAY ();
230                                 /* Write data */
231                                 (*fn->data) ( (val & 0x01), TRUE, cookie);
232                                 CONFIG_FPGA_DELAY ();
233                                 /* Assert the clock */
234                                 (*fn->clk) (TRUE, TRUE, cookie);
235                                 CONFIG_FPGA_DELAY ();
236                                 val >>= 1;
237                                 i --;
238                         } while (i > 0);
239
240 #ifdef CFG_FPGA_PROG_FEEDBACK
241                         if (bytecount % (bsize / 40) == 0)
242                                 putc ('.');             /* let them know we are alive */
243 #endif
244                 }
245
246                 CONFIG_FPGA_DELAY ();
247
248 #ifdef CFG_FPGA_PROG_FEEDBACK
249                 putc ('\n');                    /* terminate the dotted line */
250 #endif
251
252         /*
253          * Checking FPGA's CONF_DONE signal - correctly booted ?
254          */
255
256         if ( ! (*fn->done) (cookie) ) {
257                 puts ("** Booting failed! CONF_DONE is still deasserted.\n");
258                 (*fn->abort) (cookie);
259                 return (FPGA_FAIL);
260         }
261
262         /*
263          * "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
264          */
265
266         for (i = 0; i < 12; i++) {
267                 CONFIG_FPGA_DELAY ();
268                 (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
269                 CONFIG_FPGA_DELAY ();
270                 (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
271         }
272
273         ret_val = FPGA_SUCCESS;
274
275 #ifdef CFG_FPGA_PROG_FEEDBACK
276                 if (ret_val == FPGA_SUCCESS) {
277                         puts ("Done.\n");
278                 }
279                 else {
280                         puts ("Fail.\n");
281                 }
282 #endif
283         (*fn->post) (cookie);
284
285         } else {
286                 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
287         }
288
289         return ret_val;
290 }
291
292 static int ACEX1K_ps_dump (Altera_desc * desc, void *buf, size_t bsize)
293 {
294         /* Readback is only available through the Slave Parallel and         */
295         /* boundary-scan interfaces.                                         */
296         printf ("%s: Passive Serial Dumping is unavailable\n",
297                         __FUNCTION__);
298         return FPGA_FAIL;
299 }
300
301 static int ACEX1K_ps_reloc (Altera_desc * desc, ulong reloc_offset)
302 {
303         int ret_val = FPGA_FAIL;        /* assume the worst */
304         Altera_ACEX1K_Passive_Serial_fns *fn_r, *fn =
305                         (Altera_ACEX1K_Passive_Serial_fns *) (desc->iface_fns);
306
307         if (fn) {
308                 ulong addr;
309
310                 /* Get the relocated table address */
311                 addr = (ulong) fn + reloc_offset;
312                 fn_r = (Altera_ACEX1K_Passive_Serial_fns *) addr;
313
314                 if (!fn_r->relocated) {
315
316                         if (memcmp (fn_r, fn,
317                                                 sizeof (Altera_ACEX1K_Passive_Serial_fns))
318                                 == 0) {
319                                 /* good copy of the table, fix the descriptor pointer */
320                                 desc->iface_fns = fn_r;
321                         } else {
322                                 PRINTF ("%s: Invalid function table at 0x%p\n",
323                                                 __FUNCTION__, fn_r);
324                                 return FPGA_FAIL;
325                         }
326
327                         PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
328                                         desc);
329
330                         addr = (ulong) (fn->pre) + reloc_offset;
331                         fn_r->pre = (Altera_pre_fn) addr;
332
333                         addr = (ulong) (fn->config) + reloc_offset;
334                         fn_r->config = (Altera_config_fn) addr;
335
336                         addr = (ulong) (fn->status) + reloc_offset;
337                         fn_r->status = (Altera_status_fn) addr;
338
339                         addr = (ulong) (fn->done) + reloc_offset;
340                         fn_r->done = (Altera_done_fn) addr;
341
342                         addr = (ulong) (fn->clk) + reloc_offset;
343                         fn_r->clk = (Altera_clk_fn) addr;
344
345                         addr = (ulong) (fn->data) + reloc_offset;
346                         fn_r->data = (Altera_data_fn) addr;
347
348                         addr = (ulong) (fn->abort) + reloc_offset;
349                         fn_r->abort = (Altera_abort_fn) addr;
350
351                         addr = (ulong) (fn->post) + reloc_offset;
352                         fn_r->post = (Altera_post_fn) addr;
353
354                         fn_r->relocated = TRUE;
355
356                 } else {
357                         /* this table has already been moved */
358                         /* XXX - should check to see if the descriptor is correct */
359                         desc->iface_fns = fn_r;
360                 }
361
362                 ret_val = FPGA_SUCCESS;
363         } else {
364                 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
365         }
366
367         return ret_val;
368
369 }
370
371 #endif /* (CONFIG_FPGA & (CFG_ALTERA | CFG_ACEX1K)) */