Merge git://www.denx.de/git/u-boot
[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  * 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 */