]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - post/board/lwmon5/fpga.c
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[karo-tx-uboot.git] / post / board / lwmon5 / fpga.c
1 /*
2  * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com
3  *
4  * Developed for DENX Software Engineering GmbH
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 #include <common.h>
25
26 /* This test performs testing of FPGA SCRATCH register,
27  * gets FPGA version and run get_ram_size() on FPGA memory
28  */
29
30 #include <post.h>
31 #include <watchdog.h>
32 #include <asm/io.h>
33
34 DECLARE_GLOBAL_DATA_PTR;
35
36 #define FPGA_SCRATCH_REG        0xC4000050
37 #define FPGA_VERSION_REG        0xC4000040
38 #define FPGA_RAM_START          0xC4200000
39 #define FPGA_RAM_END            0xC4203FFF
40 #define FPGA_STAT               0xC400000C
41 #define FPGA_BUFFER             0x00800000
42 #define FPGA_RAM_SIZE           (FPGA_RAM_END - FPGA_RAM_START + 1)
43
44 #if CONFIG_POST & CONFIG_SYS_POST_BSPEC3
45
46 const static unsigned long pattern[] = {
47         0xffffffff,
48         0xaaaaaaaa,
49         0xcccccccc,
50         0xf0f0f0f0,
51         0xff00ff00,
52         0xffff0000,
53         0x0000ffff,
54         0x00ff00ff,
55         0x0f0f0f0f,
56         0x33333333,
57         0x55555555,
58         0x00000000,
59 };
60
61 const static unsigned long otherpattern = 0x01234567;
62
63 static int one_scratch_test(uint value)
64 {
65         uint read_value;
66         int ret = 0;
67
68         out_be32((void *)FPGA_SCRATCH_REG, value);
69         /* read other location (protect against data lines capacity) */
70         ret = in_be16((void *)FPGA_VERSION_REG);
71         /* verify test pattern */
72         read_value = in_be32((void *)FPGA_SCRATCH_REG);
73         if (read_value != value) {
74                 post_log("FPGA SCRATCH test failed write %08X, read %08X\n",
75                          value, read_value);
76                 ret = -1;
77         }
78
79         return ret;
80 }
81
82 static int fpga_post_test1(ulong *start, ulong size, ulong val)
83 {
84         int ret = 0;
85         ulong i = 0;
86         ulong *mem = start;
87         ulong readback;
88
89         for (i = 0; i < size / sizeof(ulong); i++) {
90                 mem[i] = val;
91                 if (i % 1024 == 0)
92                         WATCHDOG_RESET();
93         }
94
95         for (i = 0; i < size / sizeof(ulong); i++) {
96                 readback = mem[i];
97                 if (readback != val) {
98                         post_log("FPGA Memory error at %08x, "
99                                  "wrote %08x, read %08x !\n",
100                                  mem + i, val, readback);
101                         ret = -1;
102                         break;
103                 }
104                 if (i % 1024 == 0)
105                         WATCHDOG_RESET();
106         }
107         return ret;
108 }
109
110 static int fpga_post_test2(ulong *start, ulong size)
111 {
112         int ret = 0;
113         ulong i = 0;
114         ulong *mem = start;
115         ulong readback;
116
117         for (i = 0; i < size / sizeof(ulong); i++) {
118                 mem[i] = 1 << (i % 32);
119                 if (i % 1024 == 0)
120                         WATCHDOG_RESET();
121         }
122
123         for (i = 0; i < size / sizeof(ulong); i++) {
124                 readback = mem[i];
125                 if (readback != 1 << (i % 32)) {
126                         post_log("FPGA Memory error at %08x, "
127                                  "wrote %08x, read %08x !\n",
128                                  mem + i, 1 << (i % 32), readback);
129                         ret = -1;
130                         break;
131                 }
132                 if (i % 1024 == 0)
133                         WATCHDOG_RESET();
134         }
135
136         return ret;
137 }
138
139 static int fpga_post_test3(ulong *start, ulong size)
140 {
141         int ret = 0;
142         ulong i = 0;
143         ulong *mem = start;
144         ulong readback;
145
146         for (i = 0; i < size / sizeof(ulong); i++) {
147                 mem[i] = i;
148                 if (i % 1024 == 0)
149                         WATCHDOG_RESET();
150         }
151
152         for (i = 0; i < size / sizeof(ulong); i++) {
153                 readback = mem[i];
154                 if (readback != i) {
155                         post_log("FPGA Memory error at %08x, "
156                                  "wrote %08x, read %08x !\n",
157                                  mem + i, i, readback);
158                         ret = -1;
159                         break;
160                 }
161                 if (i % 1024 == 0)
162                         WATCHDOG_RESET();
163         }
164
165         return ret;
166 }
167
168 static int fpga_post_test4(ulong *start, ulong size)
169 {
170         int ret = 0;
171         ulong i = 0;
172         ulong *mem = start;
173         ulong readback;
174
175         for (i = 0; i < size / sizeof(ulong); i++) {
176                 mem[i] = ~i;
177                 if (i % 1024 == 0)
178                         WATCHDOG_RESET();
179         }
180
181         for (i = 0; i < size / sizeof(ulong); i++) {
182                 readback = mem[i];
183                 if (readback != ~i) {
184                         post_log("FPGA Memory error at %08x, "
185                                  "wrote %08x, read %08x !\n",
186                                  mem + i, ~i, readback);
187                         ret = -1;
188                         break;
189                 }
190                 if (i % 1024 == 0)
191                         WATCHDOG_RESET();
192         }
193
194         return ret;
195 }
196
197 /* FPGA Memory-pattern-test */
198 static int fpga_mem_test(void)
199 {
200         int ret = 0;
201         ulong* start = (ulong *)FPGA_RAM_START;
202         ulong  size  = FPGA_RAM_SIZE;
203
204         if (ret == 0)
205                 ret = fpga_post_test1(start, size, 0x00000000);
206
207         if (ret == 0)
208                 ret = fpga_post_test1(start, size, 0xffffffff);
209
210         if (ret == 0)
211                 ret = fpga_post_test1(start, size, 0x55555555);
212
213         if (ret == 0)
214                 ret = fpga_post_test1(start, size, 0xaaaaaaaa);
215
216         WATCHDOG_RESET();
217
218         if (ret == 0)
219                 ret = fpga_post_test2(start, size);
220
221         if (ret == 0)
222                 ret = fpga_post_test3(start, size);
223
224         if (ret == 0)
225                 ret = fpga_post_test4(start, size);
226
227         return ret;
228 }
229
230
231
232 /* Verify FPGA addresslines */
233 static int fpga_post_addrline(ulong *address, ulong *base, ulong size)
234 {
235         unsigned long *target;
236         unsigned long *end;
237         unsigned long readback;
238         unsigned long xor;
239         int ret = 0;
240
241         end = (ulong *)((ulong)base + size);
242         xor = 0;
243
244         for (xor = sizeof(ulong); xor > 0; xor <<= 1) {
245                 target = (ulong*)((ulong)address ^ xor);
246                 if ((target >= base) && (target < end)) {
247                         *address = ~*target;
248                         readback = *target;
249
250                         if (readback == *address) {
251                                 post_log("Memory (address line) error at %08x"
252                                          "XOR value %08x !\n",
253                                          address, target, xor);
254                                 ret = -1;
255                                 break;
256                         }
257                 }
258         }
259
260         return ret;
261 }
262
263 /* Verify FPGA addresslines */
264 static int fpga_post_dataline(ulong *address)
265 {
266         unsigned long temp32 = 0;
267         int i = 0;
268         int ret = 0;
269
270         for (i = 0; i < ARRAY_SIZE(pattern); i++) {
271                 *address = pattern[i];
272                 /*
273                  * Put a different pattern on the data lines: otherwise they
274                  * may float long enough to read back what we wrote.
275                  */
276                 *(address + 1) = otherpattern;
277                 temp32 = *address;
278
279                 if (temp32 != pattern[i]){
280                         post_log("Memory (date line) error at %08x, "
281                                  "wrote %08x, read %08x !\n",
282                                  address, pattern[i], temp32);
283                         ret = 1;
284                 }
285         }
286
287         return ret;
288 }
289
290 /* Verify FPGA, get version & memory size */
291 int fpga_post_test(int flags)
292 {
293         uint   old_value;
294         uint   version;
295         uint   read_value;
296         int    ret = 0;
297
298         post_log("\n");
299         old_value = in_be32((void *)FPGA_SCRATCH_REG);
300
301         if (one_scratch_test(0x55555555))
302                 ret = 1;
303         if (one_scratch_test(0xAAAAAAAA))
304                 ret = 1;
305
306         out_be32((void *)FPGA_SCRATCH_REG, old_value);
307
308         version = in_be32((void *)FPGA_VERSION_REG);
309         post_log("FPGA version %u.%u\n",
310                  (version >> 8) & 0xFF, version & 0xFF);
311
312         /* Enable write to FPGA RAM */
313         out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) | 0x1000);
314
315         /* get RAM size */
316         read_value = get_ram_size((void *)CONFIG_SYS_FPGA_BASE_1, FPGA_RAM_SIZE);
317         post_log("FPGA RAM size %d bytes\n", read_value);
318         WATCHDOG_RESET();
319
320         /* copy fpga memory to DDR2 RAM*/
321         memcpy((void *)FPGA_BUFFER,(void *)FPGA_RAM_START, FPGA_RAM_SIZE);
322         WATCHDOG_RESET();
323
324         /* Test datalines */
325         if (fpga_post_dataline((ulong *)FPGA_RAM_START)) {
326                 ret = 1;
327                 goto out;
328         }
329         WATCHDOG_RESET();
330
331         /* Test addresslines */
332         if (fpga_post_addrline((ulong *)FPGA_RAM_START,
333                                (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) {
334                 ret = 1;
335                 goto out;
336         }
337         WATCHDOG_RESET();
338         if (fpga_post_addrline((ulong *)FPGA_RAM_END - sizeof(long),
339                                (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) {
340                 ret = 1;
341                 goto out;
342         }
343         WATCHDOG_RESET();
344
345         /* Memory Pattern Test */
346         if (fpga_mem_test()) {
347                 ret = 1;
348                 goto out;
349         }
350         WATCHDOG_RESET();
351
352         /* restore memory */
353         memcpy((void *)FPGA_RAM_START,(void *)FPGA_BUFFER, FPGA_RAM_SIZE);
354         WATCHDOG_RESET();
355
356 out:
357         /* Disable write to RAM */
358         out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) & 0xEFFF);
359         return ret;
360 }
361
362 #endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC3 */