]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/esd/pmc440/fpga.c
Merge branch 'inka4x0-ng' of /home/m8/git/u-boot/
[people/ms/u-boot.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 only: enable ledlink */
224 if ((s = getenv("bd_type")) && !strcmp(s, "ngcc"))
225 FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
226
227 return rc;
228 }
229
230
231 int fpga_clk_fn(int assert_clk, int flush, int cookie)
232 {
233 if (assert_clk)
234 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
235 else
236 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
237
238 return assert_clk;
239 }
240
241
242 int fpga_wr_fn(int assert_write, int flush, int cookie)
243 {
244 if (assert_write)
245 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
246 else
247 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
248
249 return assert_write;
250 }
251
252 #ifdef USE_SP_CODE
253 int fpga_wdata_fn(uchar data, int flush, int cookie)
254 {
255 uchar val = data;
256 ulong or = in_be32((void*)GPIO1_OR);
257 int i = 7;
258 do {
259 /* Write data */
260 if (val & 0x80)
261 or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
262 else
263 or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
264
265 out_be32((void*)GPIO1_OR, or);
266
267 /* Assert the clock */
268 or |= GPIO1_FPGA_CLK;
269 out_be32((void*)GPIO1_OR, or);
270 val <<= 1;
271 i --;
272 } while (i > 0);
273
274 /* Write last data bit (the 8th clock comes from the sp_load() code */
275 if (val & 0x80)
276 or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
277 else
278 or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
279
280 out_be32((void*)GPIO1_OR, or);
281
282 return 0;
283 }
284 #endif
285
286 #define NGCC_FPGA_PRG CLOCK_EN
287 #define NGCC_FPGA_DATA RESET_OUT
288 #define NGCC_FPGA_DONE CLOCK_IN
289 #define NGCC_FPGA_INIT IRIGB_R_IN
290 #define NGCC_FPGA_CLK CLOCK_OUT
291
292 void ngcc_fpga_serialslave_init(void)
293 {
294 debug("%s:%d: Initialize serial slave interface\n",
295 __FUNCTION__, __LINE__);
296
297 /* make sure program pin is inactive */
298 ngcc_fpga_pgm_fn (FALSE, FALSE, 0);
299 }
300
301 /*
302 * Set the active-low FPGA reset signal.
303 */
304 void ngcc_fpga_reset(int assert)
305 {
306 debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
307
308 if (assert) {
309 FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
310 debug("asserted\n");
311 } else {
312 FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
313 debug("deasserted\n");
314 }
315 }
316
317
318 /*
319 * Set the FPGA's active-low SelectMap program line to the specified level
320 */
321 int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
322 {
323 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
324
325 debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
326
327 if (assert) {
328 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
329 debug("asserted\n");
330 } else {
331 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
332 debug("deasserted\n");
333 }
334
335 return assert;
336 }
337
338
339 /*
340 * Test the state of the active-low FPGA INIT line. Return 1 on INIT
341 * asserted (low).
342 */
343 int ngcc_fpga_init_fn(int cookie)
344 {
345 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
346
347 debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
348 if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
349 debug("high\n");
350 return 0;
351 } else {
352 debug("low\n");
353 return 1;
354 }
355 }
356
357
358 /*
359 * Test the state of the active-high FPGA DONE pin
360 */
361 int ngcc_fpga_done_fn(int cookie)
362 {
363 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
364
365 debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
366 if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
367 debug("DONE high\n");
368 return 1;
369 } else {
370 debug("low\n");
371 return 0;
372 }
373 }
374
375
376 /*
377 * FPGA pre-configuration function.
378 */
379 int ngcc_fpga_pre_config_fn(int cookie)
380 {
381 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
382 debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
383
384 ngcc_fpga_reset(TRUE);
385 FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
386
387 ngcc_fpga_reset(TRUE);
388 return 0;
389 }
390
391
392 /*
393 * FPGA post configuration function. Blip the FPGA reset line and then see if
394 * the FPGA appears to be running.
395 */
396 int ngcc_fpga_post_config_fn(int cookie)
397 {
398 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
399
400 debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
401
402 udelay (100);
403 ngcc_fpga_reset(FALSE);
404
405 FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
406
407 return 0;
408 }
409
410
411 int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
412 {
413 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
414
415 if (assert_clk)
416 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
417 else
418 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
419
420 return assert_clk;
421 }
422
423
424 int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
425 {
426 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
427
428 if (assert_write)
429 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
430 else
431 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
432
433 return assert_write;
434 }
435
436
437 /*
438 * Initialize the fpga. Return 1 on success, 0 on failure.
439 */
440 int pmc440_init_fpga(void)
441 {
442 char *s;
443
444 debug("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n",
445 __FUNCTION__, __LINE__, gd->reloc_off);
446 fpga_init(gd->reloc_off);
447
448 fpga_serialslave_init ();
449 debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
450 fpga_add (fpga_xilinx, &fpga[0]);
451
452 /* NGCC only */
453 if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
454 ngcc_fpga_serialslave_init ();
455 debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
456 fpga_add (fpga_xilinx, &fpga[1]);
457 }
458
459 return 0;
460 }
461 #endif /* CONFIG_FPGA */