Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
[oweals/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  * SPDX-License-Identifier:     GPL-2.0+
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
50 xilinx_spartan2_slave_serial_fns ngcc_fpga_fns = {
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__);
100         fpga_pgm_fn(false, false, 0);   /* make sure program pin is inactive */
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__);
175         fpga_reset(true);
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
200         fpga_reset(true);
201         udelay (100);
202         fpga_reset(false);
203         udelay (100);
204
205         FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
206
207         /* NGCC/CANDES only: enable ledlink */
208         if ((s = getenv("bd_type")) &&
209             ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
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 */
283         ngcc_fpga_pgm_fn(false, false, 0);
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
369         ngcc_fpga_reset(true);
370         FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
371
372         ngcc_fpga_reset(true);
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);
388         ngcc_fpga_reset(false);
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
429         debug("%s:%d: Initialize FPGA interface\n",
430               __FUNCTION__, __LINE__);
431         fpga_init();
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 */