]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/common/fpga.c
Merge git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / board / esd / common / fpga.c
1 /*
2  * (C) Copyright 2001-2004
3  * Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd-electronics.com
4  * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <asm/processor.h>
11 #include <asm/io.h>
12 #include <command.h>
13
14 /* ------------------------------------------------------------------------- */
15
16 #ifdef FPGA_DEBUG
17 #define DBG(x...) printf(x)
18 #else
19 #define DBG(x...)
20 #endif /* DEBUG */
21
22 #define MAX_ONES               226
23
24 #ifdef CONFIG_SYS_FPGA_PRG
25 # define FPGA_PRG              CONFIG_SYS_FPGA_PRG      /* FPGA program pin (ppc output) */
26 # define FPGA_CLK              CONFIG_SYS_FPGA_CLK      /* FPGA clk pin (ppc output)    */
27 # define FPGA_DATA             CONFIG_SYS_FPGA_DATA     /* FPGA data pin (ppc output)  */
28 # define FPGA_DONE             CONFIG_SYS_FPGA_DONE     /* FPGA done pin (ppc input)   */
29 # define FPGA_INIT             CONFIG_SYS_FPGA_INIT     /* FPGA init pin (ppc input)   */
30 #else
31 # define FPGA_PRG              0x04000000       /* FPGA program pin (ppc output) */
32 # define FPGA_CLK              0x02000000       /* FPGA clk pin (ppc output)     */
33 # define FPGA_DATA             0x01000000       /* FPGA data pin (ppc output)    */
34 # define FPGA_DONE             0x00800000       /* FPGA done pin (ppc input)     */
35 # define FPGA_INIT             0x00400000       /* FPGA init pin (ppc input)     */
36 #endif
37
38 #define ERROR_FPGA_PRG_INIT_LOW  -1     /* Timeout after PRG* asserted   */
39 #define ERROR_FPGA_PRG_INIT_HIGH -2     /* Timeout after PRG* deasserted */
40 #define ERROR_FPGA_PRG_DONE      -3     /* Timeout after programming     */
41
42 #ifndef SET_FPGA
43 # define SET_FPGA(data)         out_be32((void *)GPIO0_OR, data)
44 #endif
45
46 #ifdef FPGA_PROG_ACTIVE_HIGH
47 # define FPGA_PRG_LOW           FPGA_PRG
48 # define FPGA_PRG_HIGH          0
49 #else
50 # define FPGA_PRG_LOW           0
51 # define FPGA_PRG_HIGH          FPGA_PRG
52 #endif
53
54 #define FPGA_CLK_LOW            0
55 #define FPGA_CLK_HIGH           FPGA_CLK
56
57 #define FPGA_DATA_LOW           0
58 #define FPGA_DATA_HIGH          FPGA_DATA
59
60 #define FPGA_WRITE_1 {                                                                   \
61         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set clock to 0 */  \
62         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set data to 1  */  \
63         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);  /* set clock to 1 */  \
64         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);}      /* set data to 1  */
65
66 #define FPGA_WRITE_0 {                                                    \
67         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set clock to 0 */  \
68         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_LOW);   /* set data to 0  */  \
69         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_LOW);   /* set clock to 1 */  \
70         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);}      /* set data to 1  */
71
72 #ifndef FPGA_DONE_STATE
73 # define FPGA_DONE_STATE (in_be32((void *)GPIO0_IR) & FPGA_DONE)
74 #endif
75 #ifndef FPGA_INIT_STATE
76 # define FPGA_INIT_STATE (in_be32((void *)GPIO0_IR) & FPGA_INIT)
77 #endif
78
79
80 static int fpga_boot (const unsigned char *fpgadata, int size)
81 {
82         int i, index, len;
83         int count;
84         unsigned char b;
85
86 #ifdef CONFIG_SYS_FPGA_SPARTAN2
87         int j;
88 #else
89         int bit;
90 #endif
91
92         /* display infos on fpgaimage */
93         index = 15;
94         for (i = 0; i < 4; i++) {
95                 len = fpgadata[index];
96                 DBG ("FPGA: %s\n", &(fpgadata[index + 1]));
97                 index += len + 3;
98         }
99
100 #ifdef CONFIG_SYS_FPGA_SPARTAN2
101         /* search for preamble 0xFFFFFFFF */
102         while (1) {
103                 if ((fpgadata[index] == 0xff) && (fpgadata[index + 1] == 0xff)
104                     && (fpgadata[index + 2] == 0xff)
105                     && (fpgadata[index + 3] == 0xff))
106                         break;  /* preamble found */
107                 else
108                         index++;
109         }
110 #else
111         /* search for preamble 0xFF2X */
112         for (index = 0; index < size - 1; index++) {
113                 if ((fpgadata[index] == 0xff)
114                     && ((fpgadata[index + 1] & 0xf0) == 0x30))
115                         break;
116         }
117         index += 2;
118 #endif
119
120         DBG ("FPGA: configdata starts at position 0x%x\n", index);
121         DBG ("FPGA: length of fpga-data %d\n", size - index);
122
123         /*
124          * Setup port pins for fpga programming
125          */
126 #ifndef CONFIG_M5249
127         out_be32 ((void *)GPIO0_ODR, 0x00000000); /* no open drain pins */
128         /* setup for output */
129         out_be32 ((void *)GPIO0_TCR,
130                   in_be32 ((void *)GPIO0_TCR) |
131                   FPGA_PRG | FPGA_CLK | FPGA_DATA);
132 #endif
133         SET_FPGA (FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);      /* set pins to high */
134
135         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
136         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
137
138         /*
139          * Init fpga by asserting and deasserting PROGRAM*
140          */
141         SET_FPGA (FPGA_PRG_LOW | FPGA_CLK_HIGH | FPGA_DATA_HIGH);       /* set prog active */
142
143         /* Wait for FPGA init line low */
144         count = 0;
145         while (FPGA_INIT_STATE) {
146                 udelay (1000);  /* wait 1ms */
147                 /* Check for timeout - 100us max, so use 3ms */
148                 if (count++ > 3) {
149                         DBG ("FPGA: Booting failed!\n");
150                         return ERROR_FPGA_PRG_INIT_LOW;
151                 }
152         }
153
154         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
155         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
156
157         /* deassert PROGRAM* */
158         SET_FPGA (FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);      /* set prog inactive */
159
160         /* Wait for FPGA end of init period .  */
161         count = 0;
162         while (!(FPGA_INIT_STATE)) {
163                 udelay (1000);  /* wait 1ms */
164                 /* Check for timeout */
165                 if (count++ > 3) {
166                         DBG ("FPGA: Booting failed!\n");
167                         return ERROR_FPGA_PRG_INIT_HIGH;
168                 }
169         }
170
171         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
172         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
173
174         DBG ("write configuration data into fpga\n");
175         /* write configuration-data into fpga... */
176
177 #ifdef CONFIG_SYS_FPGA_SPARTAN2
178         /*
179          * Load uncompressed image into fpga
180          */
181         for (i = index; i < size; i++) {
182                 b = fpgadata[i];
183                 for (j = 0; j < 8; j++) {
184                         if ((b & 0x80) == 0x80) {
185                                 FPGA_WRITE_1;
186                         } else {
187                                 FPGA_WRITE_0;
188                         }
189                         b <<= 1;
190                 }
191         }
192 #else
193         /* send 0xff 0x20 */
194         FPGA_WRITE_1;
195         FPGA_WRITE_1;
196         FPGA_WRITE_1;
197         FPGA_WRITE_1;
198         FPGA_WRITE_1;
199         FPGA_WRITE_1;
200         FPGA_WRITE_1;
201         FPGA_WRITE_1;
202         FPGA_WRITE_0;
203         FPGA_WRITE_0;
204         FPGA_WRITE_1;
205         FPGA_WRITE_0;
206         FPGA_WRITE_0;
207         FPGA_WRITE_0;
208         FPGA_WRITE_0;
209         FPGA_WRITE_0;
210
211         /*
212          ** Bit_DeCompression
213          **   Code 1           .. maxOnes     : n                 '1's followed by '0'
214          **        maxOnes + 1 .. maxOnes + 1 : n - 1             '1's no '0'
215          **        maxOnes + 2 .. 254         : n - (maxOnes + 2) '0's followed by '1'
216          **        255                        :                   '1'
217          */
218
219         for (i = index; i < size; i++) {
220                 b = fpgadata[i];
221                 if ((b >= 1) && (b <= MAX_ONES)) {
222                         for (bit = 0; bit < b; bit++) {
223                                 FPGA_WRITE_1;
224                         }
225                         FPGA_WRITE_0;
226                 } else if (b == (MAX_ONES + 1)) {
227                         for (bit = 1; bit < b; bit++) {
228                                 FPGA_WRITE_1;
229                         }
230                 } else if ((b >= (MAX_ONES + 2)) && (b <= 254)) {
231                         for (bit = 0; bit < (b - (MAX_ONES + 2)); bit++) {
232                                 FPGA_WRITE_0;
233                         }
234                         FPGA_WRITE_1;
235                 } else if (b == 255) {
236                         FPGA_WRITE_1;
237                 }
238         }
239 #endif
240
241         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
242         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
243
244         /*
245          * Check if fpga's DONE signal - correctly booted ?
246          */
247
248         /* Wait for FPGA end of programming period .  */
249         count = 0;
250         while (!(FPGA_DONE_STATE)) {
251                 udelay (1000);  /* wait 1ms */
252                 /* Check for timeout */
253                 if (count++ > 3) {
254                         DBG ("FPGA: Booting failed!\n");
255                         return ERROR_FPGA_PRG_DONE;
256                 }
257         }
258
259         DBG ("FPGA: Booting successful!\n");
260         return 0;
261 }