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