]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/gen860t/fpga.c
Initial revision
[karo-tx-uboot.git] / board / gen860t / fpga.c
1 /*
2  * (C) Copyright 2002
3  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4  * Keith Outwater, keith_outwater@mvis.com.
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  *
24  */
25
26 /*
27  * Virtex2 FPGA configuration support for the GEN860T computer
28  */
29
30 #include <common.h>
31 #include <virtex2.h>
32 #include <command.h>
33 #include "fpga.h"
34
35 #if (CONFIG_FPGA)
36
37 #if 0
38 #define GEN860T_FPGA_DEBUG
39 #endif
40
41 #ifdef GEN860T_FPGA_DEBUG
42 #define PRINTF(fmt,args...)     printf (fmt ,##args)
43 #else
44 #define PRINTF(fmt,args...)
45 #endif
46
47 /*
48  * Port bit numbers for the Selectmap controls
49  */
50 #define FPGA_INIT_BIT_NUM               22      /* PB22 */
51 #define FPGA_RESET_BIT_NUM              11      /* PC11 */
52 #define FPGA_DONE_BIT_NUM               16      /* PB16 */
53 #define FPGA_PROGRAM_BIT_NUM    7       /* PA7  */
54
55 /* Note that these are pointers to code that is in Flash.  They will be
56  * relocated at runtime.
57  */
58 Xilinx_Virtex2_Slave_SelectMap_fns fpga_fns = {
59         fpga_pre_config_fn,
60         fpga_pgm_fn,
61         fpga_init_fn,
62         fpga_err_fn,
63         fpga_done_fn,
64         fpga_clk_fn,
65         fpga_cs_fn,
66         fpga_wr_fn,
67         fpga_read_data_fn,
68         fpga_write_data_fn,
69         fpga_busy_fn,
70         fpga_abort_fn,
71         fpga_post_config_fn
72 };
73
74 Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
75         { Xilinx_Virtex2,
76           slave_selectmap,
77           XILINX_XC2V3000_SIZE,
78           (void *)&fpga_fns,
79           0
80         }
81 };
82
83 /*
84  * Display FPGA revision information
85  */
86 void
87 print_fpga_revision(void)
88 {
89         vu_long *rev_p = (vu_long *)0x60000008;
90
91         printf("FPGA Revision 0x%.8lx"
92                    " (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n",
93                    *rev_p,
94                    ((*rev_p >> 28) & 0xf),
95                    ((*rev_p >> 20) & 0xff),
96                    ((*rev_p >> 12) & 0xff),
97                    ((*rev_p >> 8) & 0xf),
98                    (*rev_p & 0xff));
99 }
100
101
102 /*
103  * Perform a simple test of the FPGA to processor interface using the FPGA's
104  * inverting bus test register.  The great thing about doing a read/write
105  * test on a register that inverts it's contents is that you avoid any
106  * problems with bus charging.
107  * Return 0 on failure, 1 on success.
108  */
109 int
110 test_fpga_ibtr(void)
111 {
112         vu_long *ibtr_p = (vu_long *)0x60000010;
113         vu_long readback;
114         vu_long compare;
115         int i;
116         int j;
117         int k;
118         int pass = 1;
119
120         static const ulong bitpattern[] = {
121                 0xdeadbeef,     /* magic ID pattern for debug   */
122                 0x00000001,     /* single bit                                   */
123                 0x00000003,     /* two adjacent bits                    */
124                 0x00000007,     /* three adjacent bits                  */
125                 0x0000000F,     /* four adjacent bits                   */
126                 0x00000005,     /* two non-adjacent bits                */
127                 0x00000015,     /* three non-adjacent bits              */
128                 0x00000055,     /* four non-adjacent bits               */
129                 0xaaaaaaaa,     /* alternating 1/0                              */
130         };
131
132         for (i = 0; i < 1024; i++) {
133                 for (j = 0; j < 31; j++) {
134                         for (k = 0; k < sizeof(bitpattern)/sizeof(bitpattern[0]); k++) {
135                                 *ibtr_p = compare = (bitpattern[k] << j);
136                                 readback = *ibtr_p;
137                                 if (readback != ~compare) {
138                                         printf("%s:%d: FPGA test fail: expected 0x%.8lx"
139                                                    " actual 0x%.8lx\n",
140                                                    __FUNCTION__, __LINE__, ~compare, readback);
141                                         pass = 0;
142                                         break;
143                                 }
144                         }
145                         if (!pass) break;
146                 }
147                 if (!pass) break;
148         }
149         if (pass) {
150                 printf("FPGA inverting bus test passed\n");
151                 print_fpga_revision();
152         }
153         else {
154                 printf("** FPGA inverting bus test failed\n");
155         }
156         return pass;
157 }
158
159
160 /*
161  * Set the active-low FPGA reset signal.
162  */
163 void
164 fpga_reset(int assert)
165 {
166     volatile immap_t *immap  = (immap_t *)CFG_IMMR;
167
168         PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__);
169         if (assert) {
170                 immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM);
171                 PRINTF("asserted\n");
172         }
173         else {
174                 immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM);
175                 PRINTF("deasserted\n");
176         }
177 }
178
179
180 /*
181  * Initialize the SelectMap interface.  We assume that the mode and the
182  * initial state of all of the port pins have already been set!
183  */
184 void
185 fpga_selectmap_init(void)
186 {
187         PRINTF("%s:%d: Initialize SelectMap interface\n", __FUNCTION__, __LINE__);
188         fpga_pgm_fn(FALSE, FALSE, 0);   /* make sure program pin is inactive */
189 }
190
191
192 /*
193  * Initialize the fpga.  Return 1 on success, 0 on failure.
194  */
195 int
196 gen860t_init_fpga(void)
197 {
198         DECLARE_GLOBAL_DATA_PTR;
199
200         int i;
201
202         PRINTF("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n",
203                         __FUNCTION__, __LINE__, gd->reloc_off);
204         fpga_init(gd->reloc_off);
205         fpga_selectmap_init();
206
207         for(i=0; i < CONFIG_FPGA_COUNT; i++) {
208                 PRINTF("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i);
209                 fpga_add(fpga_xilinx, &fpga[i]);
210         }
211         return 1;
212 }
213
214
215 /*
216  * Set the FPGA's active-low SelectMap program line to the specified level
217  */
218 int
219 fpga_pgm_fn(int assert, int flush, int cookie)
220 {
221     volatile immap_t *immap  = (immap_t *)CFG_IMMR;
222
223         PRINTF("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
224
225         if (assert) {
226                 immap->im_ioport.iop_padat &= ~(0x8000 >> FPGA_PROGRAM_BIT_NUM);
227                 PRINTF("asserted\n");
228         }
229         else {
230                 immap->im_ioport.iop_padat |= (0x8000 >> FPGA_PROGRAM_BIT_NUM);
231                 PRINTF("deasserted\n");
232         }
233         return assert;
234 }
235
236
237 /*
238  * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
239  * asserted (low).
240  */
241 int
242 fpga_init_fn(int cookie)
243 {
244     volatile immap_t *immap  = (immap_t *)CFG_IMMR;
245
246         PRINTF("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
247         if(immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) {
248                 PRINTF("high\n");
249                 return 0;
250         }
251         else {
252                 PRINTF("low\n");
253                 return 1;
254         }
255 }
256
257
258 /*
259  * Test the state of the active-high FPGA DONE pin
260  */
261 int
262 fpga_done_fn(int cookie)
263 {
264     volatile immap_t *immap  = (immap_t *)CFG_IMMR;
265
266         PRINTF("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
267         if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) {
268                 PRINTF("high\n");
269                 return FPGA_SUCCESS;
270         }
271         else {
272                 PRINTF("low\n");
273                 return FPGA_FAIL;
274         }
275 }
276
277
278 /*
279  * Read FPGA SelectMap data.
280  */
281 int
282 fpga_read_data_fn(unsigned char *data, int cookie)
283 {
284         vu_char *p = (vu_char *)SELECTMAP_BASE;
285
286         *data = *p;
287 #if 0
288         PRINTF("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int)data, data);
289 #endif
290         return (int)data;
291 }
292
293
294 /*
295  * Write data to the FPGA SelectMap port
296  */
297 int
298 fpga_write_data_fn(unsigned char data, int flush, int cookie)
299 {
300         vu_char *p = (vu_char *)SELECTMAP_BASE;
301
302 #if 0
303         PRINTF("%s: Write Data 0x%x\n", __FUNCTION__, (int)data);
304 #endif
305         *p = data;
306         return (int)data;
307 }
308
309
310 /*
311  * Abort and FPGA operation
312  */
313 int
314 fpga_abort_fn(int cookie)
315 {
316         PRINTF("%s:%d: FPGA program sequence aborted\n",
317                    __FUNCTION__, __LINE__);
318         return FPGA_FAIL;
319 }
320
321
322 /*
323  * FPGA pre-configuration function. Just make sure that
324  * FPGA reset is asserted to keep the FPGA from starting up after
325  * configuration.
326  */
327 int
328 fpga_pre_config_fn(int cookie)
329 {
330         PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
331         fpga_reset(TRUE);
332         return 0;
333 }
334
335
336 /*
337  * FPGA post configuration function. Blip the FPGA reset line and then see if
338  * the FPGA appears to be running.
339  */
340 int
341 fpga_post_config_fn(int cookie)
342 {
343         int rc;
344
345         PRINTF("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
346         fpga_reset(TRUE);
347         udelay(1000);
348         fpga_reset(FALSE);
349         udelay (1000);
350
351         /*
352          * Use the FPGA,s inverting bus test register to do a simple test of the
353          * processor interface.
354          */
355         rc = test_fpga_ibtr();
356         return rc;
357 }
358
359
360 /*
361  * Clock, chip select and write signal assert functions and error check
362  * and busy functions.  These are only stubs because the GEN860T selectmap
363  * interface handles sequencing of control signals automatically (it uses
364  * a memory-mapped interface to the FPGA SelectMap port).  The design of
365  * the interface guarantees that the SelectMap port cannot be overrun so
366  * no busy check is needed.  A configuration error is signalled by INIT
367  * going low during configuration, so there is no need for a separate error
368  * function.
369  */
370 int
371 fpga_clk_fn(int assert_clk, int flush, int cookie)
372 {
373         return assert_clk;
374 }
375
376 int
377 fpga_cs_fn(int assert_cs, int flush, int cookie)
378 {
379         return assert_cs;
380 }
381
382 int
383 fpga_wr_fn(int assert_write, int flush, int cookie)
384 {
385         return assert_write;
386 }
387
388 int
389 fpga_err_fn(int cookie)
390 {
391         return 0;
392 }
393
394 int
395 fpga_busy_fn(int cookie)
396 {
397         return 0;
398 }
399 #endif
400
401 /* vim: set ts=4 tw=78 sw=4: */