]>
Commit | Line | Data |
---|---|---|
407843a5 MF |
1 | /* |
2 | * (C) Copyright 2007 | |
3 | * Matthias Fuchs, esd gmbh, [email protected]. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
407843a5 MF |
6 | */ |
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 | ||
16 | DECLARE_GLOBAL_DATA_PTR; | |
17 | ||
18 | #if defined(CONFIG_FPGA) | |
19 | ||
20 | #define USE_SP_CODE | |
21 | ||
22 | #ifdef USE_SP_CODE | |
23 | Xilinx_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 | |
39 | Xilinx_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 | ||
b625b9ae | 50 | xilinx_spartan2_slave_serial_fns ngcc_fpga_fns = { |
407843a5 MF |
51 | 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 | ||
60 | Xilinx_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 | */ | |
79 | void 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 | */ | |
96 | void fpga_serialslave_init(void) | |
97 | { | |
98 | debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__, | |
99 | __LINE__); | |
472d5460 | 100 | fpga_pgm_fn(false, false, 0); /* make sure program pin is inactive */ |
407843a5 MF |
101 | } |
102 | ||
103 | ||
104 | /* | |
105 | * Set the FPGA's active-low SelectMap program line to the specified level | |
106 | */ | |
107 | int 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 | */ | |
127 | int 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 | |
136 | int fpga_abort_fn(int cookie) | |
137 | { | |
138 | return 0; | |
139 | } | |
140 | ||
141 | ||
142 | int fpga_cs_fn(int assert_cs, int flush, int cookie) | |
143 | { | |
144 | return assert_cs; | |
145 | } | |
146 | ||
147 | ||
148 | int 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 | */ | |
158 | int 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 | */ | |
172 | int fpga_pre_config_fn(int cookie) | |
173 | { | |
174 | debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__); | |
472d5460 | 175 | fpga_reset(true); |
407843a5 MF |
176 | |
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 | */ | |
189 | int 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 | ||
472d5460 | 200 | fpga_reset(true); |
407843a5 | 201 | udelay (100); |
472d5460 | 202 | fpga_reset(false); |
407843a5 MF |
203 | udelay (100); |
204 | ||
205 | FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK); | |
206 | ||
29513325 MF |
207 | /* NGCC/CANDES only: enable ledlink */ |
208 | if ((s = getenv("bd_type")) && | |
209 | ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes")))) | |
407843a5 MF |
210 | FPGA_SETBITS(&fpga->ctrla, 0x29f8c000); |
211 | ||
212 | return rc; | |
213 | } | |
214 | ||
215 | ||
216 | int 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 | ||
227 | int 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 | |
238 | int 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 | ||
277 | void 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 */ | |
472d5460 | 283 | ngcc_fpga_pgm_fn(false, false, 0); |
407843a5 MF |
284 | } |
285 | ||
286 | /* | |
287 | * Set the active-low FPGA reset signal. | |
288 | */ | |
289 | void 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 | */ | |
306 | int 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 | */ | |
328 | int 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 | */ | |
346 | int 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 | */ | |
364 | int 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 | ||
472d5460 | 369 | ngcc_fpga_reset(true); |
407843a5 MF |
370 | FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00); |
371 | ||
472d5460 | 372 | ngcc_fpga_reset(true); |
407843a5 MF |
373 | 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 | */ | |
381 | int 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); | |
472d5460 | 388 | ngcc_fpga_reset(false); |
407843a5 MF |
389 | |
390 | FPGA_SETBITS(&fpga->ctrla, 0x29f8c000); | |
391 | ||
392 | return 0; | |
393 | } | |
394 | ||
395 | ||
396 | int 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 | ||
409 | int 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 | */ | |
425 | int pmc440_init_fpga(void) | |
426 | { | |
427 | char *s; | |
428 | ||
6385b281 PT |
429 | debug("%s:%d: Initialize FPGA interface\n", |
430 | __FUNCTION__, __LINE__); | |
431 | fpga_init(); | |
407843a5 MF |
432 | |
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 */ |