]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/astro/mcf5373l/fpga.c
socfpga: Move board/socfpga_cyclone5 to board/socfpga
[karo-tx-uboot.git] / board / astro / mcf5373l / fpga.c
1 /*
2  * (C) Copyright 2006
3  * Wolfgang Wegner, ASTRO Strobel Kommunikationssysteme GmbH,
4  * w.wegner@astro-kom.de
5  *
6  * based on the files by
7  * Heiko Schocher, DENX Software Engineering, hs@denx.de
8  * and
9  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
10  * Keith Outwater, keith_outwater@mvis.com.
11  *
12  * See file CREDITS for list of people who contributed to this
13  * project.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  *
30  */
31
32 /* Altera/Xilinx FPGA configuration support for the ASTRO "URMEL" board */
33
34 #include <common.h>
35 #include <watchdog.h>
36 #include <altera.h>
37 #include <ACEX1K.h>
38 #include <spartan3.h>
39 #include <command.h>
40 #include <asm/immap_5329.h>
41 #include <asm/io.h>
42 #include "fpga.h"
43
44 DECLARE_GLOBAL_DATA_PTR;
45
46 int altera_pre_fn(int cookie)
47 {
48         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
49         unsigned char tmp_char;
50         unsigned short tmp_short;
51
52         /* first, set the required pins to GPIO function */
53         /* PAR_T0IN -> GPIO */
54         tmp_char = readb(&gpiop->par_timer);
55         tmp_char &= 0xfc;
56         writeb(tmp_char, &gpiop->par_timer);
57         /* all QSPI pins -> GPIO */
58         writew(0x0000, &gpiop->par_qspi);
59         /* U0RTS, U0CTS -> GPIO */
60         tmp_short = __raw_readw(&gpiop->par_uart);
61         tmp_short &= 0xfff3;
62         __raw_writew(tmp_short, &gpiop->par_uart);
63         /* all PWM pins -> GPIO */
64         writeb(0x00, &gpiop->par_pwm);
65         /* next, set data direction registers */
66         writeb(0x01, &gpiop->pddr_timer);
67         writeb(0x25, &gpiop->pddr_qspi);
68         writeb(0x0c, &gpiop->pddr_uart);
69         writeb(0x04, &gpiop->pddr_pwm);
70
71         /* ensure other SPI peripherals are deselected */
72         writeb(0x08, &gpiop->ppd_uart);
73         writeb(0x38, &gpiop->ppd_qspi);
74
75         /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */
76         writeb(0xFB, &gpiop->pclrr_uart);
77         /* enable Altera configuration by clearing QSPI_CS2 and DT0IN */
78         writeb(0xFE, &gpiop->pclrr_timer);
79         writeb(0xDF, &gpiop->pclrr_qspi);
80         return FPGA_SUCCESS;
81 }
82
83 /* Set the state of CONFIG Pin */
84 int altera_config_fn(int assert_config, int flush, int cookie)
85 {
86         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
87
88         if (assert_config)
89                 writeb(0x04, &gpiop->ppd_uart);
90         else
91                 writeb(0xFB, &gpiop->pclrr_uart);
92         return FPGA_SUCCESS;
93 }
94
95 /* Returns the state of STATUS Pin */
96 int altera_status_fn(int cookie)
97 {
98         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
99
100         if (readb(&gpiop->ppd_pwm) & 0x08)
101                 return FPGA_FAIL;
102         return FPGA_SUCCESS;
103 }
104
105 /* Returns the state of CONF_DONE Pin */
106 int altera_done_fn(int cookie)
107 {
108         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
109
110         if (readb(&gpiop->ppd_pwm) & 0x20)
111                 return FPGA_FAIL;
112         return FPGA_SUCCESS;
113 }
114
115 /*
116  * writes the complete buffer to the FPGA
117  * writing the complete buffer in one function is much faster,
118  * then calling it for every bit
119  */
120 int altera_write_fn(void *buf, size_t len, int flush, int cookie)
121 {
122         size_t bytecount = 0;
123         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
124         unsigned char *data = (unsigned char *)buf;
125         unsigned char val = 0;
126         int i;
127         int len_40 = len / 40;
128
129         while (bytecount < len) {
130                 val = data[bytecount++];
131                 i = 8;
132                 do {
133                         writeb(0xFB, &gpiop->pclrr_qspi);
134                         if (val & 0x01)
135                                 writeb(0x01, &gpiop->ppd_qspi);
136                         else
137                                 writeb(0xFE, &gpiop->pclrr_qspi);
138                         writeb(0x04, &gpiop->ppd_qspi);
139                         val >>= 1;
140                         i--;
141                 } while (i > 0);
142
143                 if (bytecount % len_40 == 0) {
144 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
145                         WATCHDOG_RESET();
146 #endif
147 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
148                         putc('.');      /* let them know we are alive */
149 #endif
150 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
151                         if (ctrlc())
152                                 return FPGA_FAIL;
153 #endif
154                 }
155         }
156         return FPGA_SUCCESS;
157 }
158
159 /* called, when programming is aborted */
160 int altera_abort_fn(int cookie)
161 {
162         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
163
164         writeb(0x20, &gpiop->ppd_qspi);
165         writeb(0x08, &gpiop->ppd_uart);
166         return FPGA_SUCCESS;
167 }
168
169 /* called, when programming was succesful */
170 int altera_post_fn(int cookie)
171 {
172         return altera_abort_fn(cookie);
173 }
174
175 /*
176  * Note that these are pointers to code that is in Flash. They will be
177  * relocated at runtime.
178  * FIXME: relocation not yet working for coldfire, see below!
179  */
180 Altera_CYC2_Passive_Serial_fns altera_fns = {
181         altera_pre_fn,
182         altera_config_fn,
183         altera_status_fn,
184         altera_done_fn,
185         altera_write_fn,
186         altera_abort_fn,
187         altera_post_fn
188 };
189
190 Altera_desc altera_fpga[CONFIG_FPGA_COUNT] = {
191         {Altera_CYC2,
192          passive_serial,
193          85903,
194          (void *)&altera_fns,
195          NULL,
196          0}
197 };
198
199 /* Initialize the fpga.  Return 1 on success, 0 on failure. */
200 int astro5373l_altera_load(void)
201 {
202         int i;
203
204         for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
205                 /*
206                  * I did not yet manage to get relocation work properly,
207                  * so set stuff here instead of static initialisation:
208                  */
209                 altera_fns.pre = altera_pre_fn;
210                 altera_fns.config = altera_config_fn;
211                 altera_fns.status = altera_status_fn;
212                 altera_fns.done = altera_done_fn;
213                 altera_fns.write = altera_write_fn;
214                 altera_fns.abort = altera_abort_fn;
215                 altera_fns.post = altera_post_fn;
216                 altera_fpga[i].iface_fns = (void *)&altera_fns;
217                 fpga_add(fpga_altera, &altera_fpga[i]);
218         }
219         return 1;
220 }
221
222 /* Set the FPGA's PROG_B line to the specified level */
223 int xilinx_pgm_fn(int assert, int flush, int cookie)
224 {
225         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
226
227         if (assert)
228                 writeb(0xFB, &gpiop->pclrr_uart);
229         else
230                 writeb(0x04, &gpiop->ppd_uart);
231         return assert;
232 }
233
234 /*
235  * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
236  * asserted (low).
237  */
238 int xilinx_init_fn(int cookie)
239 {
240         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
241
242         return (readb(&gpiop->ppd_pwm) & 0x08) == 0;
243 }
244
245 /* Test the state of the active-high FPGA DONE pin */
246 int xilinx_done_fn(int cookie)
247 {
248         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
249
250         return (readb(&gpiop->ppd_pwm) & 0x20) >> 5;
251 }
252
253 /* Abort an FPGA operation */
254 int xilinx_abort_fn(int cookie)
255 {
256         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
257         /* ensure all SPI peripherals and FPGAs are deselected */
258         writeb(0x08, &gpiop->ppd_uart);
259         writeb(0x01, &gpiop->ppd_timer);
260         writeb(0x38, &gpiop->ppd_qspi);
261         return FPGA_FAIL;
262 }
263
264 /*
265  * FPGA pre-configuration function. Just make sure that
266  * FPGA reset is asserted to keep the FPGA from starting up after
267  * configuration.
268  */
269 int xilinx_pre_config_fn(int cookie)
270 {
271         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
272         unsigned char tmp_char;
273         unsigned short tmp_short;
274
275         /* first, set the required pins to GPIO function */
276         /* PAR_T0IN -> GPIO */
277         tmp_char = readb(&gpiop->par_timer);
278         tmp_char &= 0xfc;
279         writeb(tmp_char, &gpiop->par_timer);
280         /* all QSPI pins -> GPIO */
281         writew(0x0000, &gpiop->par_qspi);
282         /* U0RTS, U0CTS -> GPIO */
283         tmp_short = __raw_readw(&gpiop->par_uart);
284         tmp_short &= 0xfff3;
285         __raw_writew(tmp_short, &gpiop->par_uart);
286         /* all PWM pins -> GPIO */
287         writeb(0x00, &gpiop->par_pwm);
288         /* next, set data direction registers */
289         writeb(0x01, &gpiop->pddr_timer);
290         writeb(0x25, &gpiop->pddr_qspi);
291         writeb(0x0c, &gpiop->pddr_uart);
292         writeb(0x04, &gpiop->pddr_pwm);
293
294         /* ensure other SPI peripherals are deselected */
295         writeb(0x08, &gpiop->ppd_uart);
296         writeb(0x38, &gpiop->ppd_qspi);
297         writeb(0x01, &gpiop->ppd_timer);
298
299         /* CONFIG = 0, STATUS = 0 -> FPGA in reset state */
300         writeb(0xFB, &gpiop->pclrr_uart);
301         /* enable Xilinx configuration by clearing QSPI_CS2 and U0CTS */
302         writeb(0xF7, &gpiop->pclrr_uart);
303         writeb(0xDF, &gpiop->pclrr_qspi);
304         return 0;
305 }
306
307 /*
308  * FPGA post configuration function. Should perform a test if FPGA is running.
309  */
310 int xilinx_post_config_fn(int cookie)
311 {
312         int rc = 0;
313
314         /*
315          * no test yet
316          */
317         return rc;
318 }
319
320 int xilinx_clk_fn(int assert_clk, int flush, int cookie)
321 {
322         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
323
324         if (assert_clk)
325                 writeb(0x04, &gpiop->ppd_qspi);
326         else
327                 writeb(0xFB, &gpiop->pclrr_qspi);
328         return assert_clk;
329 }
330
331 int xilinx_wr_fn(int assert_write, int flush, int cookie)
332 {
333         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
334
335         if (assert_write)
336                 writeb(0x01, &gpiop->ppd_qspi);
337         else
338                 writeb(0xFE, &gpiop->pclrr_qspi);
339         return assert_write;
340 }
341
342 int xilinx_fastwr_fn(void *buf, size_t len, int flush, int cookie)
343 {
344         size_t bytecount = 0;
345         gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
346         unsigned char *data = (unsigned char *)buf;
347         unsigned char val = 0;
348         int i;
349         int len_40 = len / 40;
350
351         for (bytecount = 0; bytecount < len; bytecount++) {
352                 val = *(data++);
353                 for (i = 8; i > 0; i--) {
354                         writeb(0xFB, &gpiop->pclrr_qspi);
355                         if (val & 0x80)
356                                 writeb(0x01, &gpiop->ppd_qspi);
357                         else
358                                 writeb(0xFE, &gpiop->pclrr_qspi);
359                         writeb(0x04, &gpiop->ppd_qspi);
360                         val <<= 1;
361                 }
362                 if (bytecount % len_40 == 0) {
363 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
364                         WATCHDOG_RESET();
365 #endif
366 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
367                         putc('.');      /* let them know we are alive */
368 #endif
369 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
370                         if (ctrlc())
371                                 return FPGA_FAIL;
372 #endif
373                 }
374         }
375         return FPGA_SUCCESS;
376 }
377
378 /*
379  * Note that these are pointers to code that is in Flash.  They will be
380  * relocated at runtime.
381  * FIXME: relocation not yet working for coldfire, see below!
382  */
383 Xilinx_Spartan3_Slave_Serial_fns xilinx_fns = {
384         xilinx_pre_config_fn,
385         xilinx_pgm_fn,
386         xilinx_clk_fn,
387         xilinx_init_fn,
388         xilinx_done_fn,
389         xilinx_wr_fn,
390         0,
391         xilinx_fastwr_fn
392 };
393
394 Xilinx_desc xilinx_fpga[CONFIG_FPGA_COUNT] = {
395         {Xilinx_Spartan3,
396          slave_serial,
397          XILINX_XC3S4000_SIZE,
398          (void *)&xilinx_fns,
399          0}
400 };
401
402 /* Initialize the fpga.  Return 1 on success, 0 on failure. */
403 int astro5373l_xilinx_load(void)
404 {
405         int i;
406
407         fpga_init();
408
409         for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
410                 /*
411                  * I did not yet manage to get relocation work properly,
412                  * so set stuff here instead of static initialisation:
413                  */
414                 xilinx_fns.pre = xilinx_pre_config_fn;
415                 xilinx_fns.pgm = xilinx_pgm_fn;
416                 xilinx_fns.clk = xilinx_clk_fn;
417                 xilinx_fns.init = xilinx_init_fn;
418                 xilinx_fns.done = xilinx_done_fn;
419                 xilinx_fns.wr = xilinx_wr_fn;
420                 xilinx_fns.bwr = xilinx_fastwr_fn;
421                 xilinx_fpga[i].iface_fns = (void *)&xilinx_fns;
422                 fpga_add(fpga_xilinx, &xilinx_fpga[i]);
423         }
424         return 1;
425 }