blob: cef205088270460e299542ced20788991a199bcc [file] [log] [blame]
Matthias Fuchs0586e9f22007-12-28 17:07:18 +01001/*
2 * (C) Copyright 2007
3 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Matthias Fuchs0586e9f22007-12-28 17:07:18 +01006 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <spartan2.h>
11#include <spartan3.h>
12#include <command.h>
13#include "fpga.h"
14#include "pmc440.h"
15
16DECLARE_GLOBAL_DATA_PTR;
17
18#if defined(CONFIG_FPGA)
19
20#define USE_SP_CODE
21
22#ifdef USE_SP_CODE
23Xilinx_Spartan3_Slave_Parallel_fns pmc440_fpga_fns = {
24 fpga_pre_config_fn,
25 fpga_pgm_fn,
26 fpga_init_fn,
27 NULL, /* err */
28 fpga_done_fn,
29 fpga_clk_fn,
30 fpga_cs_fn,
31 fpga_wr_fn,
32 NULL, /* rdata */
33 fpga_wdata_fn,
34 fpga_busy_fn,
35 fpga_abort_fn,
36 fpga_post_config_fn,
37};
38#else
39Xilinx_Spartan3_Slave_Serial_fns pmc440_fpga_fns = {
40 fpga_pre_config_fn,
41 fpga_pgm_fn,
42 fpga_clk_fn,
43 fpga_init_fn,
44 fpga_done_fn,
45 fpga_wr_fn,
46 fpga_post_config_fn,
47};
48#endif
49
Michal Simek5206cca2014-03-13 11:23:43 +010050xilinx_spartan2_slave_serial_fns ngcc_fpga_fns = {
Matthias Fuchs0586e9f22007-12-28 17:07:18 +010051 ngcc_fpga_pre_config_fn,
52 ngcc_fpga_pgm_fn,
53 ngcc_fpga_clk_fn,
54 ngcc_fpga_init_fn,
55 ngcc_fpga_done_fn,
56 ngcc_fpga_wr_fn,
57 ngcc_fpga_post_config_fn
58};
59
60Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
61 XILINX_XC3S1200E_DESC(
62#ifdef USE_SP_CODE
63 slave_parallel,
64#else
65 slave_serial,
66#endif
67 (void *)&pmc440_fpga_fns,
68 0),
69 XILINX_XC2S200_DESC(
70 slave_serial,
71 (void *)&ngcc_fpga_fns,
72 0)
73};
74
75
76/*
77 * Set the active-low FPGA reset signal.
78 */
79void fpga_reset(int assert)
80{
81 debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
82 if (assert) {
83 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
84 debug("asserted\n");
85 } else {
86 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
87 debug("deasserted\n");
88 }
89}
90
91
92/*
93 * Initialize the SelectMap interface. We assume that the mode and the
94 * initial state of all of the port pins have already been set!
95 */
96void fpga_serialslave_init(void)
97{
98 debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
99 __LINE__);
York Sun4a598092013-04-01 11:29:11 -0700100 fpga_pgm_fn(false, false, 0); /* make sure program pin is inactive */
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100101}
102
103
104/*
105 * Set the FPGA's active-low SelectMap program line to the specified level
106 */
107int fpga_pgm_fn(int assert, int flush, int cookie)
108{
109 debug("%s:%d: FPGA PROGRAM ",
110 __FUNCTION__, __LINE__);
111
112 if (assert) {
113 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
114 debug("asserted\n");
115 } else {
116 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
117 debug("deasserted\n");
118 }
119 return assert;
120}
121
122
123/*
124 * Test the state of the active-low FPGA INIT line. Return 1 on INIT
125 * asserted (low).
126 */
127int fpga_init_fn(int cookie)
128{
129 if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
130 return 0;
131 else
132 return 1;
133}
134
135#ifdef USE_SP_CODE
136int fpga_abort_fn(int cookie)
137{
138 return 0;
139}
140
141
142int fpga_cs_fn(int assert_cs, int flush, int cookie)
143{
144 return assert_cs;
145}
146
147
148int fpga_busy_fn(int cookie)
149{
150 return 1;
151}
152#endif
153
154
155/*
156 * Test the state of the active-high FPGA DONE pin
157 */
158int fpga_done_fn(int cookie)
159{
160 if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
161 return 1;
162 else
163 return 0;
164}
165
166
167/*
168 * FPGA pre-configuration function. Just make sure that
169 * FPGA reset is asserted to keep the FPGA from starting up after
170 * configuration.
171 */
172int fpga_pre_config_fn(int cookie)
173{
174 debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
York Sun4a598092013-04-01 11:29:11 -0700175 fpga_reset(true);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100176
177 /* release init# */
178 out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
179 /* disable PLD IOs */
180 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
181 return 0;
182}
183
184
185/*
186 * FPGA post configuration function. Blip the FPGA reset line and then see if
187 * the FPGA appears to be running.
188 */
189int fpga_post_config_fn(int cookie)
190{
191 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
192 int rc=0;
193 char *s;
194
195 debug("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
196
197 /* enable PLD0..7 pins */
198 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
199
York Sun4a598092013-04-01 11:29:11 -0700200 fpga_reset(true);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100201 udelay (100);
York Sun4a598092013-04-01 11:29:11 -0700202 fpga_reset(false);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100203 udelay (100);
204
205 FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
206
Matthias Fuchs9f1a7672008-10-28 13:36:55 +0100207 /* NGCC/CANDES only: enable ledlink */
208 if ((s = getenv("bd_type")) &&
209 ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100210 FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
211
212 return rc;
213}
214
215
216int fpga_clk_fn(int assert_clk, int flush, int cookie)
217{
218 if (assert_clk)
219 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
220 else
221 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
222
223 return assert_clk;
224}
225
226
227int fpga_wr_fn(int assert_write, int flush, int cookie)
228{
229 if (assert_write)
230 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
231 else
232 out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
233
234 return assert_write;
235}
236
237#ifdef USE_SP_CODE
238int fpga_wdata_fn(uchar data, int flush, int cookie)
239{
240 uchar val = data;
241 ulong or = in_be32((void*)GPIO1_OR);
242 int i = 7;
243 do {
244 /* Write data */
245 if (val & 0x80)
246 or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
247 else
248 or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
249
250 out_be32((void*)GPIO1_OR, or);
251
252 /* Assert the clock */
253 or |= GPIO1_FPGA_CLK;
254 out_be32((void*)GPIO1_OR, or);
255 val <<= 1;
256 i --;
257 } while (i > 0);
258
259 /* Write last data bit (the 8th clock comes from the sp_load() code */
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 return 0;
268}
269#endif
270
271#define NGCC_FPGA_PRG CLOCK_EN
272#define NGCC_FPGA_DATA RESET_OUT
273#define NGCC_FPGA_DONE CLOCK_IN
274#define NGCC_FPGA_INIT IRIGB_R_IN
275#define NGCC_FPGA_CLK CLOCK_OUT
276
277void ngcc_fpga_serialslave_init(void)
278{
279 debug("%s:%d: Initialize serial slave interface\n",
280 __FUNCTION__, __LINE__);
281
282 /* make sure program pin is inactive */
York Sun4a598092013-04-01 11:29:11 -0700283 ngcc_fpga_pgm_fn(false, false, 0);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100284}
285
286/*
287 * Set the active-low FPGA reset signal.
288 */
289void ngcc_fpga_reset(int assert)
290{
291 debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
292
293 if (assert) {
294 FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
295 debug("asserted\n");
296 } else {
297 FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
298 debug("deasserted\n");
299 }
300}
301
302
303/*
304 * Set the FPGA's active-low SelectMap program line to the specified level
305 */
306int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
307{
308 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
309
310 debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
311
312 if (assert) {
313 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
314 debug("asserted\n");
315 } else {
316 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
317 debug("deasserted\n");
318 }
319
320 return assert;
321}
322
323
324/*
325 * Test the state of the active-low FPGA INIT line. Return 1 on INIT
326 * asserted (low).
327 */
328int ngcc_fpga_init_fn(int cookie)
329{
330 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
331
332 debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
333 if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
334 debug("high\n");
335 return 0;
336 } else {
337 debug("low\n");
338 return 1;
339 }
340}
341
342
343/*
344 * Test the state of the active-high FPGA DONE pin
345 */
346int ngcc_fpga_done_fn(int cookie)
347{
348 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
349
350 debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
351 if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
352 debug("DONE high\n");
353 return 1;
354 } else {
355 debug("low\n");
356 return 0;
357 }
358}
359
360
361/*
362 * FPGA pre-configuration function.
363 */
364int ngcc_fpga_pre_config_fn(int cookie)
365{
366 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
367 debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
368
York Sun4a598092013-04-01 11:29:11 -0700369 ngcc_fpga_reset(true);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100370 FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
371
York Sun4a598092013-04-01 11:29:11 -0700372 ngcc_fpga_reset(true);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100373 return 0;
374}
375
376
377/*
378 * FPGA post configuration function. Blip the FPGA reset line and then see if
379 * the FPGA appears to be running.
380 */
381int ngcc_fpga_post_config_fn(int cookie)
382{
383 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
384
385 debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
386
387 udelay (100);
York Sun4a598092013-04-01 11:29:11 -0700388 ngcc_fpga_reset(false);
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100389
390 FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
391
392 return 0;
393}
394
395
396int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
397{
398 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
399
400 if (assert_clk)
401 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
402 else
403 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
404
405 return assert_clk;
406}
407
408
409int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
410{
411 pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
412
413 if (assert_write)
414 FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
415 else
416 FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
417
418 return assert_write;
419}
420
421
422/*
423 * Initialize the fpga. Return 1 on success, 0 on failure.
424 */
425int pmc440_init_fpga(void)
426{
427 char *s;
428
Peter Tysercf8582c2009-09-21 11:20:32 -0500429 debug("%s:%d: Initialize FPGA interface\n",
430 __FUNCTION__, __LINE__);
431 fpga_init();
Matthias Fuchs0586e9f22007-12-28 17:07:18 +0100432
433 fpga_serialslave_init ();
434 debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
435 fpga_add (fpga_xilinx, &fpga[0]);
436
437 /* NGCC only */
438 if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
439 ngcc_fpga_serialslave_init ();
440 debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
441 fpga_add (fpga_xilinx, &fpga[1]);
442 }
443
444 return 0;
445}
446#endif /* CONFIG_FPGA */