]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/pmc440/fpga.c
Merge branch 'u-boot/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / board / esd / pmc440 / fpga.c
1 /*
2  * (C) Copyright 2007
3  * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <asm/io.h>
26 #include <spartan2.h>
27 #include <spartan3.h>
28 #include <command.h>
29 #include "fpga.h"
30 #include "pmc440.h"
31
32 DECLARE_GLOBAL_DATA_PTR;
33
34 #if defined(CONFIG_FPGA)
35
36 #define USE_SP_CODE
37
38 #ifdef USE_SP_CODE
39 Xilinx_Spartan3_Slave_Parallel_fns pmc440_fpga_fns = {
40         fpga_pre_config_fn,
41         fpga_pgm_fn,
42         fpga_init_fn,
43         NULL, /* err */
44         fpga_done_fn,
45         fpga_clk_fn,
46         fpga_cs_fn,
47         fpga_wr_fn,
48         NULL, /* rdata */
49         fpga_wdata_fn,
50         fpga_busy_fn,
51         fpga_abort_fn,
52         fpga_post_config_fn,
53 };
54 #else
55 Xilinx_Spartan3_Slave_Serial_fns pmc440_fpga_fns = {
56         fpga_pre_config_fn,
57         fpga_pgm_fn,
58         fpga_clk_fn,
59         fpga_init_fn,
60         fpga_done_fn,
61         fpga_wr_fn,
62         fpga_post_config_fn,
63 };
64 #endif
65
66 Xilinx_Spartan2_Slave_Serial_fns ngcc_fpga_fns = {
67         ngcc_fpga_pre_config_fn,
68         ngcc_fpga_pgm_fn,
69         ngcc_fpga_clk_fn,
70         ngcc_fpga_init_fn,
71         ngcc_fpga_done_fn,
72         ngcc_fpga_wr_fn,
73         ngcc_fpga_post_config_fn
74 };
75
76 Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
77         XILINX_XC3S1200E_DESC(
78 #ifdef USE_SP_CODE
79                 slave_parallel,
80 #else
81                 slave_serial,
82 #endif
83                 (void *)&pmc440_fpga_fns,
84                 0),
85         XILINX_XC2S200_DESC(
86                 slave_serial,
87                 (void *)&ngcc_fpga_fns,
88                 0)
89 };
90
91
92 /*
93  * Set the active-low FPGA reset signal.
94  */
95 void fpga_reset(int assert)
96 {
97         debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
98         if (assert) {
99                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
100                 debug("asserted\n");
101         } else {
102                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
103                 debug("deasserted\n");
104         }
105 }
106
107
108 /*
109  * Initialize the SelectMap interface.  We assume that the mode and the
110  * initial state of all of the port pins have already been set!
111  */
112 void fpga_serialslave_init(void)
113 {
114         debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
115               __LINE__);
116         fpga_pgm_fn(false, false, 0);   /* make sure program pin is inactive */
117 }
118
119
120 /*
121  * Set the FPGA's active-low SelectMap program line to the specified level
122  */
123 int fpga_pgm_fn(int assert, int flush, int cookie)
124 {
125         debug("%s:%d: FPGA PROGRAM ",
126               __FUNCTION__, __LINE__);
127
128         if (assert) {
129                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
130                 debug("asserted\n");
131         } else {
132                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
133                 debug("deasserted\n");
134         }
135         return assert;
136 }
137
138
139 /*
140  * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
141  * asserted (low).
142  */
143 int fpga_init_fn(int cookie)
144 {
145         if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
146                 return 0;
147         else
148                 return 1;
149 }
150
151 #ifdef USE_SP_CODE
152 int fpga_abort_fn(int cookie)
153 {
154         return 0;
155 }
156
157
158 int fpga_cs_fn(int assert_cs, int flush, int cookie)
159 {
160         return assert_cs;
161 }
162
163
164 int fpga_busy_fn(int cookie)
165 {
166         return 1;
167 }
168 #endif
169
170
171 /*
172  * Test the state of the active-high FPGA DONE pin
173  */
174 int fpga_done_fn(int cookie)
175 {
176         if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
177                 return 1;
178         else
179                 return 0;
180 }
181
182
183 /*
184  * FPGA pre-configuration function. Just make sure that
185  * FPGA reset is asserted to keep the FPGA from starting up after
186  * configuration.
187  */
188 int fpga_pre_config_fn(int cookie)
189 {
190         debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
191         fpga_reset(true);
192
193         /* release init# */
194         out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
195         /* disable PLD IOs */
196         out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
197         return 0;
198 }
199
200
201 /*
202  * FPGA post configuration function. Blip the FPGA reset line and then see if
203  * the FPGA appears to be running.
204  */
205 int fpga_post_config_fn(int cookie)
206 {
207         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
208         int rc=0;
209         char *s;
210
211         debug("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
212
213         /* enable PLD0..7 pins */
214         out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
215
216         fpga_reset(true);
217         udelay (100);
218         fpga_reset(false);
219         udelay (100);
220
221         FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
222
223         /* NGCC/CANDES only: enable ledlink */
224         if ((s = getenv("bd_type")) &&
225             ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
226                 FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
227
228         return rc;
229 }
230
231
232 int fpga_clk_fn(int assert_clk, int flush, int cookie)
233 {
234         if (assert_clk)
235                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
236         else
237                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
238
239         return assert_clk;
240 }
241
242
243 int fpga_wr_fn(int assert_write, int flush, int cookie)
244 {
245         if (assert_write)
246                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
247         else
248                 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
249
250         return assert_write;
251 }
252
253 #ifdef USE_SP_CODE
254 int fpga_wdata_fn(uchar data, int flush, int cookie)
255 {
256         uchar val = data;
257         ulong or = in_be32((void*)GPIO1_OR);
258         int i = 7;
259         do {
260                 /* Write data */
261                 if (val & 0x80)
262                         or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
263                 else
264                         or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
265
266                 out_be32((void*)GPIO1_OR, or);
267
268                 /* Assert the clock */
269                 or |= GPIO1_FPGA_CLK;
270                 out_be32((void*)GPIO1_OR, or);
271                 val <<= 1;
272                 i --;
273         } while (i > 0);
274
275         /* Write last data bit (the 8th clock comes from the sp_load() code */
276         if (val & 0x80)
277                 or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
278         else
279                 or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
280
281         out_be32((void*)GPIO1_OR, or);
282
283         return 0;
284 }
285 #endif
286
287 #define NGCC_FPGA_PRG  CLOCK_EN
288 #define NGCC_FPGA_DATA RESET_OUT
289 #define NGCC_FPGA_DONE CLOCK_IN
290 #define NGCC_FPGA_INIT IRIGB_R_IN
291 #define NGCC_FPGA_CLK  CLOCK_OUT
292
293 void ngcc_fpga_serialslave_init(void)
294 {
295         debug("%s:%d: Initialize serial slave interface\n",
296               __FUNCTION__, __LINE__);
297
298         /* make sure program pin is inactive */
299         ngcc_fpga_pgm_fn(false, false, 0);
300 }
301
302 /*
303  * Set the active-low FPGA reset signal.
304  */
305 void ngcc_fpga_reset(int assert)
306 {
307         debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
308
309         if (assert) {
310                 FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
311                 debug("asserted\n");
312         } else {
313                 FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
314                 debug("deasserted\n");
315         }
316 }
317
318
319 /*
320  * Set the FPGA's active-low SelectMap program line to the specified level
321  */
322 int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
323 {
324         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
325
326         debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
327
328         if (assert) {
329                 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
330                 debug("asserted\n");
331         } else {
332                 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
333                 debug("deasserted\n");
334         }
335
336         return assert;
337 }
338
339
340 /*
341  * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
342  * asserted (low).
343  */
344 int ngcc_fpga_init_fn(int cookie)
345 {
346         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
347
348         debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
349         if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
350                 debug("high\n");
351                 return 0;
352         } else {
353                 debug("low\n");
354                 return 1;
355         }
356 }
357
358
359 /*
360  * Test the state of the active-high FPGA DONE pin
361  */
362 int ngcc_fpga_done_fn(int cookie)
363 {
364         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
365
366         debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
367         if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
368                 debug("DONE high\n");
369                 return 1;
370         } else {
371                 debug("low\n");
372                 return 0;
373         }
374 }
375
376
377 /*
378  * FPGA pre-configuration function.
379  */
380 int ngcc_fpga_pre_config_fn(int cookie)
381 {
382         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
383         debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
384
385         ngcc_fpga_reset(true);
386         FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
387
388         ngcc_fpga_reset(true);
389         return 0;
390 }
391
392
393 /*
394  * FPGA post configuration function. Blip the FPGA reset line and then see if
395  * the FPGA appears to be running.
396  */
397 int ngcc_fpga_post_config_fn(int cookie)
398 {
399         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
400
401         debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
402
403         udelay (100);
404         ngcc_fpga_reset(false);
405
406         FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
407
408         return 0;
409 }
410
411
412 int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
413 {
414         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
415
416         if (assert_clk)
417                 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
418         else
419                 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
420
421         return assert_clk;
422 }
423
424
425 int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
426 {
427         pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
428
429         if (assert_write)
430                 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
431         else
432                 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
433
434         return assert_write;
435 }
436
437
438 /*
439  * Initialize the fpga.  Return 1 on success, 0 on failure.
440  */
441 int pmc440_init_fpga(void)
442 {
443         char *s;
444
445         debug("%s:%d: Initialize FPGA interface\n",
446               __FUNCTION__, __LINE__);
447         fpga_init();
448
449         fpga_serialslave_init ();
450         debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
451         fpga_add (fpga_xilinx, &fpga[0]);
452
453         /* NGCC only */
454         if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
455                 ngcc_fpga_serialslave_init ();
456                 debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
457                 fpga_add (fpga_xilinx, &fpga[1]);
458         }
459
460         return 0;
461 }
462 #endif /* CONFIG_FPGA */