]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/common/fpga.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[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  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26 #include <asm/processor.h>
27 #include <asm/io.h>
28 #include <command.h>
29
30 /* ------------------------------------------------------------------------- */
31
32 #ifdef FPGA_DEBUG
33 #define DBG(x...) printf(x)
34 #else
35 #define DBG(x...)
36 #endif /* DEBUG */
37
38 #define MAX_ONES               226
39
40 #ifdef CONFIG_SYS_FPGA_PRG
41 # define FPGA_PRG              CONFIG_SYS_FPGA_PRG      /* FPGA program pin (ppc output) */
42 # define FPGA_CLK              CONFIG_SYS_FPGA_CLK      /* FPGA clk pin (ppc output)    */
43 # define FPGA_DATA             CONFIG_SYS_FPGA_DATA     /* FPGA data pin (ppc output)  */
44 # define FPGA_DONE             CONFIG_SYS_FPGA_DONE     /* FPGA done pin (ppc input)   */
45 # define FPGA_INIT             CONFIG_SYS_FPGA_INIT     /* FPGA init pin (ppc input)   */
46 #else
47 # define FPGA_PRG              0x04000000       /* FPGA program pin (ppc output) */
48 # define FPGA_CLK              0x02000000       /* FPGA clk pin (ppc output)     */
49 # define FPGA_DATA             0x01000000       /* FPGA data pin (ppc output)    */
50 # define FPGA_DONE             0x00800000       /* FPGA done pin (ppc input)     */
51 # define FPGA_INIT             0x00400000       /* FPGA init pin (ppc input)     */
52 #endif
53
54 #define ERROR_FPGA_PRG_INIT_LOW  -1     /* Timeout after PRG* asserted   */
55 #define ERROR_FPGA_PRG_INIT_HIGH -2     /* Timeout after PRG* deasserted */
56 #define ERROR_FPGA_PRG_DONE      -3     /* Timeout after programming     */
57
58 #ifndef SET_FPGA
59 # define SET_FPGA(data)         out_be32((void *)GPIO0_OR, data)
60 #endif
61
62 #ifdef FPGA_PROG_ACTIVE_HIGH
63 # define FPGA_PRG_LOW           FPGA_PRG
64 # define FPGA_PRG_HIGH          0
65 #else
66 # define FPGA_PRG_LOW           0
67 # define FPGA_PRG_HIGH          FPGA_PRG
68 #endif
69
70 #define FPGA_CLK_LOW            0
71 #define FPGA_CLK_HIGH           FPGA_CLK
72
73 #define FPGA_DATA_LOW           0
74 #define FPGA_DATA_HIGH          FPGA_DATA
75
76 #define FPGA_WRITE_1 {                                                                   \
77         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set clock to 0 */  \
78         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set data to 1  */  \
79         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);  /* set clock to 1 */  \
80         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);}      /* set data to 1  */
81
82 #define FPGA_WRITE_0 {                                                    \
83         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_HIGH);  /* set clock to 0 */  \
84         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_LOW  | FPGA_DATA_LOW);   /* set data to 0  */  \
85         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_LOW);   /* set clock to 1 */  \
86         SET_FPGA(FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);}      /* set data to 1  */
87
88 #ifndef FPGA_DONE_STATE
89 # define FPGA_DONE_STATE (in_be32((void *)GPIO0_IR) & FPGA_DONE)
90 #endif
91 #ifndef FPGA_INIT_STATE
92 # define FPGA_INIT_STATE (in_be32((void *)GPIO0_IR) & FPGA_INIT)
93 #endif
94
95
96 static int fpga_boot (const unsigned char *fpgadata, int size)
97 {
98         int i, index, len;
99         int count;
100         unsigned char b;
101
102 #ifdef CONFIG_SYS_FPGA_SPARTAN2
103         int j;
104 #else
105         int bit;
106 #endif
107
108         /* display infos on fpgaimage */
109         index = 15;
110         for (i = 0; i < 4; i++) {
111                 len = fpgadata[index];
112                 DBG ("FPGA: %s\n", &(fpgadata[index + 1]));
113                 index += len + 3;
114         }
115
116 #ifdef CONFIG_SYS_FPGA_SPARTAN2
117         /* search for preamble 0xFFFFFFFF */
118         while (1) {
119                 if ((fpgadata[index] == 0xff) && (fpgadata[index + 1] == 0xff)
120                     && (fpgadata[index + 2] == 0xff)
121                     && (fpgadata[index + 3] == 0xff))
122                         break;  /* preamble found */
123                 else
124                         index++;
125         }
126 #else
127         /* search for preamble 0xFF2X */
128         for (index = 0; index < size - 1; index++) {
129                 if ((fpgadata[index] == 0xff)
130                     && ((fpgadata[index + 1] & 0xf0) == 0x30))
131                         break;
132         }
133         index += 2;
134 #endif
135
136         DBG ("FPGA: configdata starts at position 0x%x\n", index);
137         DBG ("FPGA: length of fpga-data %d\n", size - index);
138
139         /*
140          * Setup port pins for fpga programming
141          */
142 #ifndef CONFIG_M5249
143         out_be32 ((void *)GPIO0_ODR, 0x00000000); /* no open drain pins */
144         /* setup for output */
145         out_be32 ((void *)GPIO0_TCR,
146                   in_be32 ((void *)GPIO0_TCR) |
147                   FPGA_PRG | FPGA_CLK | FPGA_DATA);
148 #endif
149         SET_FPGA (FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);      /* set pins to high */
150
151         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
152         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
153
154         /*
155          * Init fpga by asserting and deasserting PROGRAM*
156          */
157         SET_FPGA (FPGA_PRG_LOW | FPGA_CLK_HIGH | FPGA_DATA_HIGH);       /* set prog active */
158
159         /* Wait for FPGA init line low */
160         count = 0;
161         while (FPGA_INIT_STATE) {
162                 udelay (1000);  /* wait 1ms */
163                 /* Check for timeout - 100us max, so use 3ms */
164                 if (count++ > 3) {
165                         DBG ("FPGA: Booting failed!\n");
166                         return ERROR_FPGA_PRG_INIT_LOW;
167                 }
168         }
169
170         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
171         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
172
173         /* deassert PROGRAM* */
174         SET_FPGA (FPGA_PRG_HIGH | FPGA_CLK_HIGH | FPGA_DATA_HIGH);      /* set prog inactive */
175
176         /* Wait for FPGA end of init period .  */
177         count = 0;
178         while (!(FPGA_INIT_STATE)) {
179                 udelay (1000);  /* wait 1ms */
180                 /* Check for timeout */
181                 if (count++ > 3) {
182                         DBG ("FPGA: Booting failed!\n");
183                         return ERROR_FPGA_PRG_INIT_HIGH;
184                 }
185         }
186
187         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
188         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
189
190         DBG ("write configuration data into fpga\n");
191         /* write configuration-data into fpga... */
192
193 #ifdef CONFIG_SYS_FPGA_SPARTAN2
194         /*
195          * Load uncompressed image into fpga
196          */
197         for (i = index; i < size; i++) {
198                 b = fpgadata[i];
199                 for (j = 0; j < 8; j++) {
200                         if ((b & 0x80) == 0x80) {
201                                 FPGA_WRITE_1;
202                         } else {
203                                 FPGA_WRITE_0;
204                         }
205                         b <<= 1;
206                 }
207         }
208 #else
209         /* send 0xff 0x20 */
210         FPGA_WRITE_1;
211         FPGA_WRITE_1;
212         FPGA_WRITE_1;
213         FPGA_WRITE_1;
214         FPGA_WRITE_1;
215         FPGA_WRITE_1;
216         FPGA_WRITE_1;
217         FPGA_WRITE_1;
218         FPGA_WRITE_0;
219         FPGA_WRITE_0;
220         FPGA_WRITE_1;
221         FPGA_WRITE_0;
222         FPGA_WRITE_0;
223         FPGA_WRITE_0;
224         FPGA_WRITE_0;
225         FPGA_WRITE_0;
226
227         /*
228          ** Bit_DeCompression
229          **   Code 1           .. maxOnes     : n                 '1's followed by '0'
230          **        maxOnes + 1 .. maxOnes + 1 : n - 1             '1's no '0'
231          **        maxOnes + 2 .. 254         : n - (maxOnes + 2) '0's followed by '1'
232          **        255                        :                   '1'
233          */
234
235         for (i = index; i < size; i++) {
236                 b = fpgadata[i];
237                 if ((b >= 1) && (b <= MAX_ONES)) {
238                         for (bit = 0; bit < b; bit++) {
239                                 FPGA_WRITE_1;
240                         }
241                         FPGA_WRITE_0;
242                 } else if (b == (MAX_ONES + 1)) {
243                         for (bit = 1; bit < b; bit++) {
244                                 FPGA_WRITE_1;
245                         }
246                 } else if ((b >= (MAX_ONES + 2)) && (b <= 254)) {
247                         for (bit = 0; bit < (b - (MAX_ONES + 2)); bit++) {
248                                 FPGA_WRITE_0;
249                         }
250                         FPGA_WRITE_1;
251                 } else if (b == 255) {
252                         FPGA_WRITE_1;
253                 }
254         }
255 #endif
256
257         DBG ("%s, ", (FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE");
258         DBG ("%s\n", (FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT");
259
260         /*
261          * Check if fpga's DONE signal - correctly booted ?
262          */
263
264         /* Wait for FPGA end of programming period .  */
265         count = 0;
266         while (!(FPGA_DONE_STATE)) {
267                 udelay (1000);  /* wait 1ms */
268                 /* Check for timeout */
269                 if (count++ > 3) {
270                         DBG ("FPGA: Booting failed!\n");
271                         return ERROR_FPGA_PRG_DONE;
272                 }
273         }
274
275         DBG ("FPGA: Booting successful!\n");
276         return 0;
277 }