board/w7o/fpga.c: make (mostly) checkpatch clean
[platform/kernel/u-boot.git] / board / w7o / fpga.c
1 /*
2  * (C) Copyright 2001
3  * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
4  *  and
5  * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25 #include <config.h>
26 #include <common.h>
27 #include "w7o.h"
28 #include <asm/processor.h>
29 #include "errors.h"
30
31 static void
32 fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr)
33 {
34         unsigned long i;
35         volatile unsigned long val;
36         volatile unsigned short *dest = daddr;  /* volatile-bypass optimizer */
37
38         for (i = 0; i < len; i++, src++) {
39                 val = *src;
40                 *dest = (unsigned short) ((val & 0xff000000L) >> 16);
41                 *dest = (unsigned short) ((val & 0x00ff0000L) >> 8);
42                 *dest = (unsigned short) (val & 0x0000ff00L);
43                 *dest = (unsigned short) ((val & 0x000000ffL) << 8);
44         }
45
46         /* Terminate programming with 4 C clocks */
47         dest = daddr;
48         val = *(unsigned short *) dest;
49         val = *(unsigned short *) dest;
50         val = *(unsigned short *) dest;
51         val = *(unsigned short *) dest;
52
53 }
54
55
56 int
57 fpgaDownload(unsigned char *saddr, unsigned long size, unsigned short *daddr)
58 {
59         int i;                  /* index, intr disable flag */
60         int start;              /* timer */
61         unsigned long greg, grego;      /* GPIO & output register */
62         unsigned long length;   /* image size in words */
63         unsigned long *source;  /* image source addr */
64         unsigned short *dest;   /* destination FPGA addr */
65         volatile unsigned short *ndest; /* temp dest FPGA addr */
66         volatile unsigned short val;    /* temp val */
67         unsigned long cnfg = GPIO_XCV_CNFG;     /* FPGA CNFG */
68         unsigned long eirq = GPIO_XCV_IRQ;
69         int retval = -1;        /* Function return value */
70
71         /* Setup some basic values */
72         length = (size / 4) + 1;        /* size in words, rounding UP
73                                            is OK */
74         source = (unsigned long *) saddr;
75         dest = (unsigned short *) daddr;
76
77         /* Get DCR output register */
78         grego = in32(PPC405GP_GPIO0_OR);
79
80         /* Reset FPGA */
81         grego &= ~GPIO_XCV_PROG;        /* PROG line low */
82         out32(PPC405GP_GPIO0_OR, grego);
83
84         /* Setup timeout timer */
85         start = get_timer(0);
86
87         /* Wait for FPGA init line to go low */
88         while (in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT) {
89                 /* Check for timeout - 100us max, so use 3ms */
90                 if (get_timer(start) > 3) {
91                         printf("     failed to start init.\n");
92                         log_warn(ERR_XINIT0);   /* Don't halt */
93
94                         /* Reset line stays low */
95                         goto done;      /* I like gotos... */
96                 }
97         }
98
99         /* Unreset FPGA */
100         grego |= GPIO_XCV_PROG; /* PROG line high */
101         out32(PPC405GP_GPIO0_OR, grego);
102
103         /* Wait for FPGA end of init period = init line go hi  */
104         while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT)) {
105
106                 /* Check for timeout */
107                 if (get_timer(start) > 3) {
108                         printf("     failed to exit init.\n");
109                         log_warn(ERR_XINIT1);
110
111                         /* Reset FPGA */
112                         grego &= ~GPIO_XCV_PROG;        /* PROG line low */
113                         out32(PPC405GP_GPIO0_OR, grego);
114
115                         goto done;
116                 }
117         }
118
119         /* Now program FPGA ... */
120         ndest = dest;
121         for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
122                 /* Toggle IRQ/GPIO */
123                 greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
124                 greg |= eirq;   /* toggle irq/gpio */
125                 mtdcr(CPC0_CR0, greg);  /*  ... just do it */
126
127                 /* turn on open drain for CNFG */
128                 greg = in32(PPC405GP_GPIO0_ODR); /* get open drain register */
129                 greg |= cnfg;   /* CNFG open drain */
130                 out32(PPC405GP_GPIO0_ODR, greg); /*  .. just do it */
131
132                 /* Turn output enable on for CNFG */
133                 greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
134                 greg |= cnfg;   /* CNFG tristate inactive */
135                 out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
136
137                 /* Setup FPGA for programming */
138                 grego &= ~cnfg; /* CONFIG line low */
139                 out32(PPC405GP_GPIO0_OR, grego);
140
141                 /*
142                  * Program the FPGA
143                  */
144                 printf("\n       destination: 0x%lx ", (unsigned long) ndest);
145
146                 fpga_img_write(source, length, (unsigned short *) ndest);
147
148                 /* Done programming */
149                 grego |= cnfg;  /* CONFIG line high */
150                 out32(PPC405GP_GPIO0_OR, grego);
151
152                 /* Turn output enable OFF for CNFG */
153                 greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
154                 greg &= ~cnfg;  /* CNFG tristate inactive */
155                 out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
156
157                 /* Toggle IRQ/GPIO */
158                 greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
159                 greg &= ~eirq;  /* toggle irq/gpio */
160                 mtdcr(CPC0_CR0, greg);  /*  ... just do it */
161
162                 /* XXX - Next FPGA addr */
163                 ndest = (unsigned short *) ((char *) ndest + 0x00100000L);
164                 cnfg >>= 1;     /* XXX - Next  */
165                 eirq >>= 1;
166         }
167
168         /* Terminate programming with 4 C clocks */
169         ndest = dest;
170         for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
171                 val = *ndest;
172                 val = *ndest;
173                 val = *ndest;
174                 val = *ndest;
175                 ndest = (unsigned short *) ((char *) ndest + 0x00100000L);
176         }
177
178         /* Setup timer */
179         start = get_timer(0);
180
181         /* Wait for FPGA end of programming period = Test DONE low  */
182         while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_DONE)) {
183
184                 /* Check for timeout */
185                 if (get_timer(start) > 3) {
186                         printf("     done failed to come high.\n");
187                         log_warn(ERR_XDONE1);
188
189                         /* Reset FPGA */
190                         grego &= ~GPIO_XCV_PROG;        /* PROG line low */
191                         out32(PPC405GP_GPIO0_OR, grego);
192
193                         goto done;
194                 }
195         }
196
197         printf("\n       FPGA load succeeded\n");
198         retval = 0;             /* Program OK */
199
200 done:
201         return retval;
202 }
203
204 /* FPGA image is stored in flash */
205 extern flash_info_t flash_info[];
206
207 int init_fpga(void)
208 {
209         unsigned int i, j, ptr; /* General purpose */
210         unsigned char bufchar;  /* General purpose character */
211         unsigned char *buf;     /* Start of image pointer */
212         unsigned long len;      /* Length of image */
213         unsigned char *fn_buf;  /* Start of filename string */
214         unsigned int fn_len;    /* Length of filename string */
215         unsigned char *xcv_buf; /* Pointer to start of image */
216         unsigned long xcv_len;  /* Length of image */
217         unsigned long crc;      /* 30bit crc in image */
218         unsigned long calc_crc; /* Calc'd 30bit crc */
219         int retval = -1;
220
221         /* Tell the world what we are doing */
222         printf("FPGA:  ");
223
224         /*
225          * Get address of first sector where the FPGA
226          * image is stored.
227          */
228         buf = (unsigned char *) flash_info[1].start[0];
229
230         /*
231          * Get the stored image's CRC & length.
232          */
233         crc = *(unsigned long *) (buf + 4);     /* CRC is first long word */
234         len = *(unsigned long *) (buf + 8);     /* Image len is next long */
235
236         /* Pedantic */
237         if ((len < 0x133A4) || (len > 0x80000))
238                 goto bad_image;
239
240         /*
241          * Get the file name pointer and length.
242          * filename length is next short
243          */
244         fn_len = (*(unsigned short *) (buf + 12) & 0xff);
245         fn_buf = buf + 14;
246
247         /*
248          * Get the FPGA image pointer and length length.
249          */
250         xcv_buf = fn_buf + fn_len;      /* pointer to fpga image */
251         xcv_len = len - 14 - fn_len;    /* fpga image length */
252
253         /* Check for uninitialized FLASH */
254         if ((strncmp((char *) buf, "w7o", 3) != 0) || (len > 0x0007ffffL)
255             || (len == 0))
256                 goto bad_image;
257
258         /*
259          * Calculate and Check the image's CRC.
260          */
261         calc_crc = crc32(0, xcv_buf, xcv_len);
262         if (crc != calc_crc) {
263                 printf("\nfailed - bad CRC\n");
264                 goto done;
265         }
266
267         /* Output the file name */
268         printf("file name  : ");
269         for (i = 0; i < fn_len; i++) {
270                 bufchar = fn_buf[+i];
271                 if (bufchar < ' ' || bufchar > '~')
272                         bufchar = '.';
273                 putc(bufchar);
274         }
275
276         /*
277          * find rest of display data
278          */
279         ptr = 15;               /* Offset to ncd filename
280                                    length in fpga image */
281         j = xcv_buf[ptr];       /* Get len of ncd filename */
282         if (j > 32)
283                 goto bad_image;
284         ptr = ptr + j + 3;      /* skip ncd filename string +
285                                    3 bytes more bytes */
286
287         /*
288          * output target device string
289          */
290         j = xcv_buf[ptr++] - 1; /* len of targ str less term */
291         if (j > 32)
292                 goto bad_image;
293         printf("\n       target     : ");
294         for (i = 0; i < j; i++) {
295                 bufchar = (xcv_buf[ptr++]);
296                 if (bufchar < ' ' || bufchar > '~')
297                         bufchar = '.';
298                 putc(bufchar);
299         }
300
301         /*
302          * output compilation date string and time string
303          */
304         ptr += 3;               /* skip 2 bytes */
305         printf("\n       synth time : ");
306         j = (xcv_buf[ptr++] - 1);       /* len of date str less term */
307         if (j > 32)
308                 goto bad_image;
309         for (i = 0; i < j; i++) {
310                 bufchar = (xcv_buf[ptr++]);
311                 if (bufchar < ' ' || bufchar > '~')
312                         bufchar = '.';
313                 putc(bufchar);
314         }
315
316         ptr += 3;               /* Skip 2 bytes */
317         printf(" - ");
318         j = (xcv_buf[ptr++] - 1);       /* slen = targ dev str len */
319         if (j > 32)
320                 goto bad_image;
321         for (i = 0; i < j; i++) {
322                 bufchar = (xcv_buf[ptr++]);
323                 if (bufchar < ' ' || bufchar > '~')
324                         bufchar = '.';
325                 putc(bufchar);
326         }
327
328         /*
329          * output crc and length strings
330          */
331         printf("\n       len & crc  : 0x%lx  0x%lx", len, crc);
332
333         /*
334          * Program the FPGA.
335          */
336         retval = fpgaDownload((unsigned char *) xcv_buf, xcv_len,
337                               (unsigned short *) 0xfd000000L);
338         return retval;
339
340 bad_image:
341         printf("\n       BAD FPGA image format @ %lx\n",
342                flash_info[1].start[0]);
343         log_warn(ERR_XIMAGE);
344 done:
345         return retval;
346 }
347
348 void test_fpga(unsigned short *daddr)
349 {
350         int i;
351         volatile unsigned short *ndest = daddr;
352
353         for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
354 #if defined(CONFIG_W7OLMG)
355                 ndest[0x7e] = 0x55aa;
356                 if (ndest[0x7e] != 0x55aa)
357                         log_warn(ERR_XRW1 + i);
358                 ndest[0x7e] = 0xaa55;
359                 if (ndest[0x7e] != 0xaa55)
360                         log_warn(ERR_XRW1 + i);
361                 ndest[0x7e] = 0xc318;
362                 if (ndest[0x7e] != 0xc318)
363                         log_warn(ERR_XRW1 + i);
364
365 #elif defined(CONFIG_W7OLMC)
366                 ndest[0x800] = 0x55aa;
367                 ndest[0x801] = 0xaa55;
368                 ndest[0x802] = 0xc318;
369                 ndest[0x4800] = 0x55aa;
370                 ndest[0x4801] = 0xaa55;
371                 ndest[0x4802] = 0xc318;
372                 if ((ndest[0x800] != 0x55aa) ||
373                     (ndest[0x801] != 0xaa55) || (ndest[0x802] != 0xc318))
374                         log_warn(ERR_XRW1 + (2 * i)); /* Auto gen error code */
375                 if ((ndest[0x4800] != 0x55aa) ||
376                     (ndest[0x4801] != 0xaa55) || (ndest[0x4802] != 0xc318))
377                         log_warn(ERR_XRW2 + (2 * i)); /* Auto gen error code */
378
379 #else
380 #error "Unknown W7O board configuration"
381 #endif
382         }
383
384         printf("       FPGA ready\n");
385         return;
386 }