]>
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 attempts to verify board GDC. A scratch register tested, then |
11 | * simple memory test (get_ram_size()) run over GDC memory. | |
12 | */ | |
13 | ||
14 | #include <post.h> | |
f14ae418 | 15 | #include <watchdog.h> |
65b20dce | 16 | #include <asm/io.h> |
f14ae418 | 17 | #include <video.h> |
65b20dce YT |
18 | |
19 | DECLARE_GLOBAL_DATA_PTR; | |
20 | ||
f14ae418 SL |
21 | #define GDC_SCRATCH_REG 0xC1FF8044 |
22 | #define GDC_VERSION_REG 0xC1FF8084 | |
23 | #define GDC_HOST_BASE 0xC1FC0000 | |
24 | #define GDC_RAM_START 0xC0000000 | |
25 | #define GDC_RAM_END (GDC_HOST_BASE - 1) | |
26 | #define GDC_RAM_SIZE (GDC_RAM_END - GDC_RAM_START) | |
65b20dce | 27 | |
6d0f6bcf | 28 | #if CONFIG_POST & CONFIG_SYS_POST_BSPEC4 |
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, | |
41 | 0x55555555, | |
42 | 0x00000000 | |
43 | }; | |
44 | ||
45 | const static unsigned long otherpattern = 0x01234567; | |
46 | ||
47 | /* test write/read og a given LIME Register */ | |
65b20dce YT |
48 | static int gdc_test_reg_one(uint value) |
49 | { | |
65b20dce YT |
50 | uint read_value; |
51 | ||
52 | /* write test pattern */ | |
53 | out_be32((void *)GDC_SCRATCH_REG, value); | |
54 | /* read other location (protect against data lines capacity) */ | |
e607a15d | 55 | in_be32((void *)GDC_RAM_START); |
65b20dce YT |
56 | /* verify test pattern */ |
57 | read_value = in_be32((void *)GDC_SCRATCH_REG); | |
58 | if (read_value != value) { | |
59 | post_log("GDC SCRATCH test failed write %08X, read %08X\n", | |
f14ae418 | 60 | value, read_value); |
65b20dce YT |
61 | } |
62 | ||
3a5d1e7f | 63 | return (read_value != value); |
65b20dce YT |
64 | } |
65 | ||
f14ae418 SL |
66 | /* test with a given static 32 bit pattern in a given memory addressrange */ |
67 | static int gdc_post_test1(ulong *start, ulong size, ulong val) | |
68 | { | |
69 | int ret = 0; | |
70 | ulong i = 0; | |
71 | ulong *mem = start; | |
72 | ulong readback; | |
73 | ||
74 | for (i = 0; i < size / sizeof(ulong); i++) { | |
75 | mem[i] = val; | |
76 | if (i % 1024 == 0) | |
77 | WATCHDOG_RESET(); | |
78 | } | |
79 | ||
80 | for (i = 0; i < size / sizeof(ulong); i++) { | |
81 | readback = mem[i]; | |
82 | if (readback != val) { | |
83 | post_log("GDC Memory error at %08x, " | |
84 | "wrote %08x, read %08x !\n", | |
85 | mem + i, val, readback); | |
86 | ret = -1; | |
87 | break; | |
88 | } | |
89 | if (i % 1024 == 0) | |
90 | WATCHDOG_RESET(); | |
91 | } | |
92 | ||
93 | return ret; | |
94 | } | |
95 | ||
96 | /* test with dynamic 32 bit pattern in a given memory addressrange */ | |
97 | static int gdc_post_test2(ulong *start, ulong size) | |
98 | { | |
99 | int ret = 0; | |
100 | ulong i = 0; | |
101 | ulong *mem = start; | |
102 | ulong readback; | |
103 | ||
104 | for (i = 0; i < size / sizeof(ulong); i++) { | |
105 | mem[i] = 1 << (i % 32); | |
106 | if (i % 1024 == 0) | |
107 | WATCHDOG_RESET(); | |
108 | } | |
109 | ||
110 | for (i = 0; i < size / sizeof(ulong); i++) { | |
111 | readback = mem[i]; | |
112 | if (readback != 1 << (i % 32)) { | |
113 | post_log("GDC Memory error at %08x, " | |
114 | "wrote %08x, read %08x !\n", | |
115 | mem + i, 1 << (i % 32), readback); | |
116 | ret = -1; | |
117 | break; | |
118 | } | |
119 | if (i % 1024 == 0) | |
120 | WATCHDOG_RESET(); | |
121 | } | |
122 | ||
123 | return ret; | |
124 | } | |
125 | ||
126 | /* test with dynamic 32 bit pattern in a given memory addressrange */ | |
127 | static int gdc_post_test3(ulong *start, ulong size) | |
128 | { | |
129 | int ret = 0; | |
130 | ulong i = 0; | |
131 | ulong *mem = start; | |
132 | ulong readback; | |
133 | ||
134 | for (i = 0; i < size / sizeof(ulong); i++) { | |
135 | mem[i] = i; | |
136 | if (i % 1024 == 0) | |
137 | WATCHDOG_RESET(); | |
138 | } | |
139 | ||
140 | for (i = 0; i < size / sizeof(ulong); i++) { | |
141 | readback = mem[i]; | |
142 | if (readback != i) { | |
143 | post_log("GDC Memory error at %08x, " | |
144 | "wrote %08x, read %08x !\n", | |
145 | mem + i, i, readback); | |
146 | ret = -1; | |
147 | break; | |
148 | } | |
149 | if (i % 1024 == 0) | |
150 | WATCHDOG_RESET(); | |
151 | } | |
152 | ||
153 | return ret; | |
154 | } | |
155 | ||
156 | /* test with dynamic 32 bit pattern in a given memory addressrange */ | |
157 | static int gdc_post_test4(ulong *start, ulong size) | |
158 | { | |
159 | int ret = 0; | |
160 | ulong i = 0; | |
161 | ulong *mem = start; | |
162 | ulong readback; | |
163 | ||
164 | for (i = 0; i < size / sizeof(ulong); i++) { | |
165 | mem[i] = ~i; | |
166 | if (i % 1024 == 0) | |
167 | WATCHDOG_RESET(); | |
168 | } | |
169 | ||
170 | for (i = 0; i < size / sizeof(ulong); i++) { | |
171 | readback = mem[i]; | |
172 | if (readback != ~i) { | |
173 | post_log("GDC Memory error at %08x, " | |
174 | "wrote %08x, read %08x !\n", | |
175 | mem + i, ~i, readback); | |
176 | ret = -1; | |
177 | break; | |
178 | } | |
179 | if (i % 1024 == 0) | |
180 | WATCHDOG_RESET(); | |
181 | } | |
182 | ||
183 | return ret; | |
184 | } | |
185 | ||
186 | /* do some patterntests in a given addressrange */ | |
187 | int gdc_mem_test(ulong *start, ulong size) | |
188 | { | |
189 | int ret = 0; | |
190 | ||
191 | /* | |
192 | * check addressrange and do different static and dynamic | |
193 | * pattern tests with it. | |
194 | */ | |
195 | if (((void *)start) + size <= (void *)GDC_RAM_END) { | |
196 | if (ret == 0) | |
197 | ret = gdc_post_test1(start, size, 0x00000000); | |
198 | ||
199 | if (ret == 0) | |
200 | ret = gdc_post_test1(start, size, 0xffffffff); | |
201 | ||
202 | if (ret == 0) | |
203 | ret = gdc_post_test1(start, size, 0x55555555); | |
204 | ||
205 | if (ret == 0) | |
206 | ret = gdc_post_test1(start, size, 0xaaaaaaaa); | |
207 | ||
208 | if (ret == 0) | |
209 | ret = gdc_post_test2(start, size); | |
210 | ||
211 | if (ret == 0) | |
212 | ret = gdc_post_test3(start, size); | |
213 | ||
214 | if (ret == 0) | |
215 | ret = gdc_post_test4(start, size); | |
216 | } | |
217 | ||
218 | return ret; | |
219 | } | |
220 | ||
221 | /* test function of gdc memory addresslines*/ | |
222 | static int gdc_post_addrline(ulong *address, ulong *base, ulong size) | |
223 | { | |
224 | ulong *target; | |
225 | ulong *end; | |
226 | ulong readback = 0; | |
227 | ulong xor = 0; | |
228 | int ret = 0; | |
229 | ||
230 | end = (ulong *)((ulong)base + size); | |
231 | ||
232 | for (xor = sizeof(long); xor > 0; xor <<= 1) { | |
233 | target = (ulong *)((ulong)address ^ xor); | |
234 | if ((target >= base) && (target < end)) { | |
235 | *address = ~*target; | |
236 | readback = *target; | |
237 | } | |
238 | ||
239 | if (readback == *address) { | |
240 | post_log("GDC Memory (address line) error at %08x" | |
241 | "XOR value %08x !\n", | |
242 | address, target , xor); | |
243 | ret = -1; | |
244 | break; | |
245 | } | |
246 | } | |
247 | ||
248 | return ret; | |
249 | } | |
250 | ||
251 | static int gdc_post_dataline(ulong *address) | |
252 | { | |
253 | unsigned long temp32 = 0; | |
254 | int i = 0; | |
255 | int ret = 0; | |
256 | ||
257 | for (i = 0; i < ARRAY_SIZE(pattern); i++) { | |
258 | *address = pattern[i]; | |
259 | /* | |
260 | * Put a different pattern on the data lines: otherwise they | |
261 | * may float long enough to read back what we wrote. | |
262 | */ | |
263 | *(address + 1) = otherpattern; | |
264 | temp32 = *address; | |
265 | ||
266 | if (temp32 != pattern[i]){ | |
267 | post_log("GDC Memory (date line) error at %08x, " | |
268 | "wrote %08x, read %08x !\n", | |
269 | address, pattern[i], temp32); | |
270 | ret = 1; | |
271 | } | |
272 | } | |
273 | ||
274 | return ret; | |
275 | } | |
276 | ||
277 | /* Verify GDC, get memory size, verify GDC memory */ | |
65b20dce YT |
278 | int gdc_post_test(int flags) |
279 | { | |
f14ae418 SL |
280 | uint old_value; |
281 | int i = 0; | |
282 | int ret = 0; | |
65b20dce YT |
283 | |
284 | post_log("\n"); | |
285 | old_value = in_be32((void *)GDC_SCRATCH_REG); | |
286 | ||
3a5d1e7f YT |
287 | /* |
288 | * GPIOC2 register behaviour: the LIME graphics processor has a | |
289 | * maximum of 5 GPIO ports that can be used in this hardware | |
290 | * configuration. Thus only the bits for these 5 GPIOs can be | |
291 | * activated in the GPIOC2 register. All other bits will always be | |
292 | * read as zero. | |
293 | */ | |
294 | if (gdc_test_reg_one(0x00150015)) | |
65b20dce | 295 | ret = 1; |
3a5d1e7f | 296 | if (gdc_test_reg_one(0x000A000A)) |
65b20dce YT |
297 | ret = 1; |
298 | ||
299 | out_be32((void *)GDC_SCRATCH_REG, old_value); | |
300 | ||
301 | old_value = in_be32((void *)GDC_VERSION_REG); | |
302 | post_log("GDC chip version %u.%u, year %04X\n", | |
f14ae418 SL |
303 | (old_value >> 8) & 0xFF, old_value & 0xFF, |
304 | (old_value >> 16) & 0xFFFF); | |
65b20dce YT |
305 | |
306 | old_value = get_ram_size((void *)GDC_RAM_START, | |
f14ae418 SL |
307 | 0x02000000); |
308 | ||
309 | debug("GDC RAM size (ist): %d bytes\n", old_value); | |
310 | debug("GDC RAM size (soll): %d bytes\n", GDC_RAM_SIZE); | |
65b20dce YT |
311 | post_log("GDC RAM size: %d bytes\n", old_value); |
312 | ||
f14ae418 SL |
313 | /* Test SDRAM datalines */ |
314 | if (gdc_post_dataline((ulong *)GDC_RAM_START)) { | |
315 | ret = 1; | |
316 | goto out; | |
317 | } | |
318 | WATCHDOG_RESET(); | |
319 | ||
320 | /* Test SDRAM adresslines */ | |
321 | if (gdc_post_addrline((ulong *)GDC_RAM_START, | |
322 | (ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { | |
323 | ret = 1; | |
324 | goto out; | |
325 | } | |
326 | WATCHDOG_RESET(); | |
327 | if (gdc_post_addrline((ulong *)GDC_RAM_END - sizeof(long), | |
328 | (ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { | |
329 | ret = 1; | |
330 | goto out; | |
331 | } | |
332 | WATCHDOG_RESET(); | |
333 | ||
334 | /* memory pattern test */ | |
335 | debug("GDC Memory test (flags %8x:%8x)\n", flags, | |
336 | POST_SLOWTEST | POST_MANUAL); | |
337 | ||
338 | if (flags & POST_MANUAL) { | |
339 | debug("Full memory test\n"); | |
340 | if (gdc_mem_test((ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { | |
341 | ret = 1; | |
342 | goto out; | |
343 | } | |
344 | /* load splashscreen again */ | |
345 | } else { | |
346 | debug("smart memory test\n"); | |
347 | for (i = 0; i < (GDC_RAM_SIZE >> 20) && ret == 0; i++) { | |
348 | if (ret == 0) | |
349 | ret = gdc_mem_test((ulong *)(GDC_RAM_START + | |
350 | (i << 20)), | |
351 | 0x800); | |
352 | if (ret == 0) | |
353 | ret = gdc_mem_test((ulong *)(GDC_RAM_START + | |
354 | (i << 20) + 0xff800), | |
355 | 0x800); | |
356 | } | |
357 | } | |
358 | WATCHDOG_RESET(); | |
359 | ||
360 | out: | |
65b20dce YT |
361 | return ret; |
362 | } | |
6d0f6bcf | 363 | #endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC4 */ |