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