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