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