xref: /rk3399_rockchip-uboot/post/drivers/memory.c (revision 9c02defc29b57945b600714cf61ddfd02b02fb14)
1ad5bb451SWolfgang Denk /*
2ad5bb451SWolfgang Denk  * (C) Copyright 2002
3ad5bb451SWolfgang Denk  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4ad5bb451SWolfgang Denk  *
5ad5bb451SWolfgang Denk  * See file CREDITS for list of people who contributed to this
6ad5bb451SWolfgang Denk  * project.
7ad5bb451SWolfgang Denk  *
8ad5bb451SWolfgang Denk  * This program is free software; you can redistribute it and/or
9ad5bb451SWolfgang Denk  * modify it under the terms of the GNU General Public License as
10ad5bb451SWolfgang Denk  * published by the Free Software Foundation; either version 2 of
11ad5bb451SWolfgang Denk  * the License, or (at your option) any later version.
12ad5bb451SWolfgang Denk  *
13ad5bb451SWolfgang Denk  * This program is distributed in the hope that it will be useful,
14ad5bb451SWolfgang Denk  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15ad5bb451SWolfgang Denk  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16ad5bb451SWolfgang Denk  * GNU General Public License for more details.
17ad5bb451SWolfgang Denk  *
18ad5bb451SWolfgang Denk  * You should have received a copy of the GNU General Public License
19ad5bb451SWolfgang Denk  * along with this program; if not, write to the Free Software
20ad5bb451SWolfgang Denk  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21ad5bb451SWolfgang Denk  * MA 02111-1307 USA
22ad5bb451SWolfgang Denk  */
23ad5bb451SWolfgang Denk 
24ad5bb451SWolfgang Denk #include <common.h>
25ad5bb451SWolfgang Denk 
26ad5bb451SWolfgang Denk /* Memory test
27ad5bb451SWolfgang Denk  *
28ad5bb451SWolfgang Denk  * General observations:
29ad5bb451SWolfgang Denk  * o The recommended test sequence is to test the data lines: if they are
30ad5bb451SWolfgang Denk  *   broken, nothing else will work properly.  Then test the address
31ad5bb451SWolfgang Denk  *   lines.  Finally, test the cells in the memory now that the test
32ad5bb451SWolfgang Denk  *   program knows that the address and data lines work properly.
33ad5bb451SWolfgang Denk  *   This sequence also helps isolate and identify what is faulty.
34ad5bb451SWolfgang Denk  *
35ad5bb451SWolfgang Denk  * o For the address line test, it is a good idea to use the base
36ad5bb451SWolfgang Denk  *   address of the lowest memory location, which causes a '1' bit to
37ad5bb451SWolfgang Denk  *   walk through a field of zeros on the address lines and the highest
38ad5bb451SWolfgang Denk  *   memory location, which causes a '0' bit to walk through a field of
39ad5bb451SWolfgang Denk  *   '1's on the address line.
40ad5bb451SWolfgang Denk  *
41ad5bb451SWolfgang Denk  * o Floating buses can fool memory tests if the test routine writes
42ad5bb451SWolfgang Denk  *   a value and then reads it back immediately.  The problem is, the
43ad5bb451SWolfgang Denk  *   write will charge the residual capacitance on the data bus so the
44ad5bb451SWolfgang Denk  *   bus retains its state briefely.  When the test program reads the
45ad5bb451SWolfgang Denk  *   value back immediately, the capacitance of the bus can allow it
46ad5bb451SWolfgang Denk  *   to read back what was written, even though the memory circuitry
47ad5bb451SWolfgang Denk  *   is broken.  To avoid this, the test program should write a test
48ad5bb451SWolfgang Denk  *   pattern to the target location, write a different pattern elsewhere
49ad5bb451SWolfgang Denk  *   to charge the residual capacitance in a differnt manner, then read
50ad5bb451SWolfgang Denk  *   the target location back.
51ad5bb451SWolfgang Denk  *
52ad5bb451SWolfgang Denk  * o Always read the target location EXACTLY ONCE and save it in a local
53ad5bb451SWolfgang Denk  *   variable.  The problem with reading the target location more than
54ad5bb451SWolfgang Denk  *   once is that the second and subsequent reads may work properly,
55ad5bb451SWolfgang Denk  *   resulting in a failed test that tells the poor technician that
56ad5bb451SWolfgang Denk  *   "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
57ad5bb451SWolfgang Denk  *   doesn't help him one bit and causes puzzled phone calls.  Been there,
58ad5bb451SWolfgang Denk  *   done that.
59ad5bb451SWolfgang Denk  *
60ad5bb451SWolfgang Denk  * Data line test:
61ad5bb451SWolfgang Denk  * ---------------
62ad5bb451SWolfgang Denk  * This tests data lines for shorts and opens by forcing adjacent data
63ad5bb451SWolfgang Denk  * to opposite states. Because the data lines could be routed in an
64ad5bb451SWolfgang Denk  * arbitrary manner the must ensure test patterns ensure that every case
65ad5bb451SWolfgang Denk  * is tested. By using the following series of binary patterns every
66ad5bb451SWolfgang Denk  * combination of adjacent bits is test regardless of routing.
67ad5bb451SWolfgang Denk  *
68ad5bb451SWolfgang Denk  *     ...101010101010101010101010
69ad5bb451SWolfgang Denk  *     ...110011001100110011001100
70ad5bb451SWolfgang Denk  *     ...111100001111000011110000
71ad5bb451SWolfgang Denk  *     ...111111110000000011111111
72ad5bb451SWolfgang Denk  *
73ad5bb451SWolfgang Denk  * Carrying this out, gives us six hex patterns as follows:
74ad5bb451SWolfgang Denk  *
75ad5bb451SWolfgang Denk  *     0xaaaaaaaaaaaaaaaa
76ad5bb451SWolfgang Denk  *     0xcccccccccccccccc
77ad5bb451SWolfgang Denk  *     0xf0f0f0f0f0f0f0f0
78ad5bb451SWolfgang Denk  *     0xff00ff00ff00ff00
79ad5bb451SWolfgang Denk  *     0xffff0000ffff0000
80ad5bb451SWolfgang Denk  *     0xffffffff00000000
81ad5bb451SWolfgang Denk  *
82ad5bb451SWolfgang Denk  * To test for short and opens to other signals on our boards, we
83ad5bb451SWolfgang Denk  * simply test with the 1's complemnt of the paterns as well, resulting
84ad5bb451SWolfgang Denk  * in twelve patterns total.
85ad5bb451SWolfgang Denk  *
86ad5bb451SWolfgang Denk  * After writing a test pattern. a special pattern 0x0123456789ABCDEF is
87ad5bb451SWolfgang Denk  * written to a different address in case the data lines are floating.
88ad5bb451SWolfgang Denk  * Thus, if a byte lane fails, you will see part of the special
89ad5bb451SWolfgang Denk  * pattern in that byte lane when the test runs.  For example, if the
90ad5bb451SWolfgang Denk  * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
91ad5bb451SWolfgang Denk  * (for the 'a' test pattern).
92ad5bb451SWolfgang Denk  *
93ad5bb451SWolfgang Denk  * Address line test:
94ad5bb451SWolfgang Denk  * ------------------
95ad5bb451SWolfgang Denk  *  This function performs a test to verify that all the address lines
96ad5bb451SWolfgang Denk  *  hooked up to the RAM work properly.  If there is an address line
97ad5bb451SWolfgang Denk  *  fault, it usually shows up as two different locations in the address
98ad5bb451SWolfgang Denk  *  map (related by the faulty address line) mapping to one physical
99ad5bb451SWolfgang Denk  *  memory storage location.  The artifact that shows up is writing to
100ad5bb451SWolfgang Denk  *  the first location "changes" the second location.
101ad5bb451SWolfgang Denk  *
102ad5bb451SWolfgang Denk  * To test all address lines, we start with the given base address and
103ad5bb451SWolfgang Denk  * xor the address with a '1' bit to flip one address line.  For each
104ad5bb451SWolfgang Denk  * test, we shift the '1' bit left to test the next address line.
105ad5bb451SWolfgang Denk  *
106ad5bb451SWolfgang Denk  * In the actual code, we start with address sizeof(ulong) since our
107ad5bb451SWolfgang Denk  * test pattern we use is a ulong and thus, if we tried to test lower
108ad5bb451SWolfgang Denk  * order address bits, it wouldn't work because our pattern would
109ad5bb451SWolfgang Denk  * overwrite itself.
110ad5bb451SWolfgang Denk  *
111ad5bb451SWolfgang Denk  * Example for a 4 bit address space with the base at 0000:
112ad5bb451SWolfgang Denk  *   0000 <- base
113ad5bb451SWolfgang Denk  *   0001 <- test 1
114ad5bb451SWolfgang Denk  *   0010 <- test 2
115ad5bb451SWolfgang Denk  *   0100 <- test 3
116ad5bb451SWolfgang Denk  *   1000 <- test 4
117ad5bb451SWolfgang Denk  * Example for a 4 bit address space with the base at 0010:
118ad5bb451SWolfgang Denk  *   0010 <- base
119ad5bb451SWolfgang Denk  *   0011 <- test 1
120ad5bb451SWolfgang Denk  *   0000 <- (below the base address, skipped)
121ad5bb451SWolfgang Denk  *   0110 <- test 2
122ad5bb451SWolfgang Denk  *   1010 <- test 3
123ad5bb451SWolfgang Denk  *
124ad5bb451SWolfgang Denk  * The test locations are successively tested to make sure that they are
125ad5bb451SWolfgang Denk  * not "mirrored" onto the base address due to a faulty address line.
126ad5bb451SWolfgang Denk  * Note that the base and each test location are related by one address
127ad5bb451SWolfgang Denk  * line flipped.  Note that the base address need not be all zeros.
128ad5bb451SWolfgang Denk  *
129ad5bb451SWolfgang Denk  * Memory tests 1-4:
130ad5bb451SWolfgang Denk  * -----------------
131ad5bb451SWolfgang Denk  * These tests verify RAM using sequential writes and reads
132ad5bb451SWolfgang Denk  * to/from RAM. There are several test cases that use different patterns to
133ad5bb451SWolfgang Denk  * verify RAM. Each test case fills a region of RAM with one pattern and
134ad5bb451SWolfgang Denk  * then reads the region back and compares its contents with the pattern.
135ad5bb451SWolfgang Denk  * The following patterns are used:
136ad5bb451SWolfgang Denk  *
137ad5bb451SWolfgang Denk  *  1a) zero pattern (0x00000000)
138ad5bb451SWolfgang Denk  *  1b) negative pattern (0xffffffff)
139ad5bb451SWolfgang Denk  *  1c) checkerboard pattern (0x55555555)
140ad5bb451SWolfgang Denk  *  1d) checkerboard pattern (0xaaaaaaaa)
141ad5bb451SWolfgang Denk  *  2)  bit-flip pattern ((1 << (offset % 32))
142ad5bb451SWolfgang Denk  *  3)  address pattern (offset)
143ad5bb451SWolfgang Denk  *  4)  address pattern (~offset)
144ad5bb451SWolfgang Denk  *
145ad5bb451SWolfgang Denk  * Being run in normal mode, the test verifies only small 4Kb
146ad5bb451SWolfgang Denk  * regions of RAM around each 1Mb boundary. For example, for 64Mb
147ad5bb451SWolfgang Denk  * RAM the following areas are verified: 0x00000000-0x00000800,
148ad5bb451SWolfgang Denk  * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
149ad5bb451SWolfgang Denk  * 0x04000000. If the test is run in slow-test mode, it verifies
150ad5bb451SWolfgang Denk  * the whole RAM.
151ad5bb451SWolfgang Denk  */
152ad5bb451SWolfgang Denk 
153ad5bb451SWolfgang Denk #ifdef CONFIG_POST
154ad5bb451SWolfgang Denk 
155ad5bb451SWolfgang Denk #include <post.h>
156ad5bb451SWolfgang Denk #include <watchdog.h>
157ad5bb451SWolfgang Denk 
158ad5bb451SWolfgang Denk #if CONFIG_POST & CFG_POST_MEMORY
159ad5bb451SWolfgang Denk 
160ad5bb451SWolfgang Denk DECLARE_GLOBAL_DATA_PTR;
161ad5bb451SWolfgang Denk 
162ad5bb451SWolfgang Denk /*
163ad5bb451SWolfgang Denk  * Define INJECT_*_ERRORS for testing error detection in the presence of
164ad5bb451SWolfgang Denk  * _good_ hardware.
165ad5bb451SWolfgang Denk  */
166ad5bb451SWolfgang Denk #undef  INJECT_DATA_ERRORS
167ad5bb451SWolfgang Denk #undef  INJECT_ADDRESS_ERRORS
168ad5bb451SWolfgang Denk 
169ad5bb451SWolfgang Denk #ifdef INJECT_DATA_ERRORS
170ad5bb451SWolfgang Denk #warning "Injecting data line errors for testing purposes"
171ad5bb451SWolfgang Denk #endif
172ad5bb451SWolfgang Denk 
173ad5bb451SWolfgang Denk #ifdef INJECT_ADDRESS_ERRORS
174ad5bb451SWolfgang Denk #warning "Injecting address line errors for testing purposes"
175ad5bb451SWolfgang Denk #endif
176ad5bb451SWolfgang Denk 
177ad5bb451SWolfgang Denk 
178ad5bb451SWolfgang Denk /*
179ad5bb451SWolfgang Denk  * This function performs a double word move from the data at
180ad5bb451SWolfgang Denk  * the source pointer to the location at the destination pointer.
181ad5bb451SWolfgang Denk  * This is helpful for testing memory on processors which have a 64 bit
182ad5bb451SWolfgang Denk  * wide data bus.
183ad5bb451SWolfgang Denk  *
184ad5bb451SWolfgang Denk  * On those PowerPC with FPU, use assembly and a floating point move:
185ad5bb451SWolfgang Denk  * this does a 64 bit move.
186ad5bb451SWolfgang Denk  *
187ad5bb451SWolfgang Denk  * For other processors, let the compiler generate the best code it can.
188ad5bb451SWolfgang Denk  */
189ad5bb451SWolfgang Denk static void move64(unsigned long long *src, unsigned long long *dest)
190ad5bb451SWolfgang Denk {
191ad5bb451SWolfgang Denk #if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X)
192ad5bb451SWolfgang Denk 	asm ("lfd  0, 0(3)\n\t" /* fpr0	  =  *scr	*/
193ad5bb451SWolfgang Denk 	 "stfd 0, 0(4)"		/* *dest  =  fpr0	*/
194ad5bb451SWolfgang Denk 	 : : : "fr0" );		/* Clobbers fr0		*/
195ad5bb451SWolfgang Denk     return;
196ad5bb451SWolfgang Denk #else
197ad5bb451SWolfgang Denk 	*dest = *src;
198ad5bb451SWolfgang Denk #endif
199ad5bb451SWolfgang Denk }
200ad5bb451SWolfgang Denk 
201ad5bb451SWolfgang Denk /*
202ad5bb451SWolfgang Denk  * This is 64 bit wide test patterns.  Note that they reside in ROM
203ad5bb451SWolfgang Denk  * (which presumably works) and the tests write them to RAM which may
204ad5bb451SWolfgang Denk  * not work.
205ad5bb451SWolfgang Denk  *
206ad5bb451SWolfgang Denk  * The "otherpattern" is written to drive the data bus to values other
207ad5bb451SWolfgang Denk  * than the test pattern.  This is for detecting floating bus lines.
208ad5bb451SWolfgang Denk  *
209ad5bb451SWolfgang Denk  */
210ad5bb451SWolfgang Denk const static unsigned long long pattern[] = {
211ad5bb451SWolfgang Denk 	0xaaaaaaaaaaaaaaaaULL,
212ad5bb451SWolfgang Denk 	0xccccccccccccccccULL,
213ad5bb451SWolfgang Denk 	0xf0f0f0f0f0f0f0f0ULL,
214ad5bb451SWolfgang Denk 	0xff00ff00ff00ff00ULL,
215ad5bb451SWolfgang Denk 	0xffff0000ffff0000ULL,
216ad5bb451SWolfgang Denk 	0xffffffff00000000ULL,
217ad5bb451SWolfgang Denk 	0x00000000ffffffffULL,
218ad5bb451SWolfgang Denk 	0x0000ffff0000ffffULL,
219ad5bb451SWolfgang Denk 	0x00ff00ff00ff00ffULL,
220ad5bb451SWolfgang Denk 	0x0f0f0f0f0f0f0f0fULL,
221ad5bb451SWolfgang Denk 	0x3333333333333333ULL,
222ad5bb451SWolfgang Denk 	0x5555555555555555ULL
223ad5bb451SWolfgang Denk };
224ad5bb451SWolfgang Denk const unsigned long long otherpattern = 0x0123456789abcdefULL;
225ad5bb451SWolfgang Denk 
226ad5bb451SWolfgang Denk 
227ad5bb451SWolfgang Denk static int memory_post_dataline(unsigned long long * pmem)
228ad5bb451SWolfgang Denk {
229ad5bb451SWolfgang Denk 	unsigned long long temp64 = 0;
230ad5bb451SWolfgang Denk 	int num_patterns = sizeof(pattern)/ sizeof(pattern[0]);
231ad5bb451SWolfgang Denk 	int i;
232ad5bb451SWolfgang Denk 	unsigned int hi, lo, pathi, patlo;
233ad5bb451SWolfgang Denk 	int ret = 0;
234ad5bb451SWolfgang Denk 
235ad5bb451SWolfgang Denk 	for ( i = 0; i < num_patterns; i++) {
236ad5bb451SWolfgang Denk 		move64((unsigned long long *)&(pattern[i]), pmem++);
237ad5bb451SWolfgang Denk 		/*
238ad5bb451SWolfgang Denk 		 * Put a different pattern on the data lines: otherwise they
239ad5bb451SWolfgang Denk 		 * may float long enough to read back what we wrote.
240ad5bb451SWolfgang Denk 		 */
241ad5bb451SWolfgang Denk 		move64((unsigned long long *)&otherpattern, pmem--);
242ad5bb451SWolfgang Denk 		move64(pmem, &temp64);
243ad5bb451SWolfgang Denk 
244ad5bb451SWolfgang Denk #ifdef INJECT_DATA_ERRORS
245ad5bb451SWolfgang Denk 		temp64 ^= 0x00008000;
246ad5bb451SWolfgang Denk #endif
247ad5bb451SWolfgang Denk 
248ad5bb451SWolfgang Denk 		if (temp64 != pattern[i]){
249ad5bb451SWolfgang Denk 			pathi = (pattern[i]>>32) & 0xffffffff;
250ad5bb451SWolfgang Denk 			patlo = pattern[i] & 0xffffffff;
251ad5bb451SWolfgang Denk 
252ad5bb451SWolfgang Denk 			hi = (temp64>>32) & 0xffffffff;
253ad5bb451SWolfgang Denk 			lo = temp64 & 0xffffffff;
254ad5bb451SWolfgang Denk 
255ad5bb451SWolfgang Denk 			post_log ("Memory (date line) error at %08x, "
256ad5bb451SWolfgang Denk 				  "wrote %08x%08x, read %08x%08x !\n",
257ad5bb451SWolfgang Denk 					  pmem, pathi, patlo, hi, lo);
258ad5bb451SWolfgang Denk 			ret = -1;
259ad5bb451SWolfgang Denk 		}
260ad5bb451SWolfgang Denk 	}
261ad5bb451SWolfgang Denk 	return ret;
262ad5bb451SWolfgang Denk }
263ad5bb451SWolfgang Denk 
264ad5bb451SWolfgang Denk static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
265ad5bb451SWolfgang Denk {
266ad5bb451SWolfgang Denk 	ulong *target;
267ad5bb451SWolfgang Denk 	ulong *end;
268ad5bb451SWolfgang Denk 	ulong readback;
269ad5bb451SWolfgang Denk 	ulong xor;
270ad5bb451SWolfgang Denk 	int   ret = 0;
271ad5bb451SWolfgang Denk 
272ad5bb451SWolfgang Denk 	end = (ulong *)((ulong)base + size);	/* pointer arith! */
273ad5bb451SWolfgang Denk 	xor = 0;
274ad5bb451SWolfgang Denk 	for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
275ad5bb451SWolfgang Denk 		target = (ulong *)((ulong)testaddr ^ xor);
276ad5bb451SWolfgang Denk 		if((target >= base) && (target < end)) {
277ad5bb451SWolfgang Denk 			*testaddr = ~*target;
278ad5bb451SWolfgang Denk 			readback  = *target;
279ad5bb451SWolfgang Denk 
280ad5bb451SWolfgang Denk #ifdef INJECT_ADDRESS_ERRORS
281ad5bb451SWolfgang Denk 			if(xor == 0x00008000) {
282ad5bb451SWolfgang Denk 				readback = *testaddr;
283ad5bb451SWolfgang Denk 			}
284ad5bb451SWolfgang Denk #endif
285ad5bb451SWolfgang Denk 			if(readback == *testaddr) {
286ad5bb451SWolfgang Denk 				post_log ("Memory (address line) error at %08x<->%08x, "
287ad5bb451SWolfgang Denk 				  	"XOR value %08x !\n",
288ad5bb451SWolfgang Denk 					testaddr, target, xor);
289ad5bb451SWolfgang Denk 				ret = -1;
290ad5bb451SWolfgang Denk 			}
291ad5bb451SWolfgang Denk 		}
292ad5bb451SWolfgang Denk 	}
293ad5bb451SWolfgang Denk 	return ret;
294ad5bb451SWolfgang Denk }
295ad5bb451SWolfgang Denk 
296ad5bb451SWolfgang Denk static int memory_post_test1 (unsigned long start,
297ad5bb451SWolfgang Denk 			      unsigned long size,
298ad5bb451SWolfgang Denk 			      unsigned long val)
299ad5bb451SWolfgang Denk {
300ad5bb451SWolfgang Denk 	unsigned long i;
301ad5bb451SWolfgang Denk 	ulong *mem = (ulong *) start;
302ad5bb451SWolfgang Denk 	ulong readback;
303ad5bb451SWolfgang Denk 	int ret = 0;
304ad5bb451SWolfgang Denk 
305ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong); i++) {
306ad5bb451SWolfgang Denk 		mem[i] = val;
307ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
308ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
309ad5bb451SWolfgang Denk 	}
310ad5bb451SWolfgang Denk 
311ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
312ad5bb451SWolfgang Denk 		readback = mem[i];
313ad5bb451SWolfgang Denk 		if (readback != val) {
314ad5bb451SWolfgang Denk 			post_log ("Memory error at %08x, "
315ad5bb451SWolfgang Denk 				  "wrote %08x, read %08x !\n",
316ad5bb451SWolfgang Denk 					  mem + i, val, readback);
317ad5bb451SWolfgang Denk 
318ad5bb451SWolfgang Denk 			ret = -1;
319ad5bb451SWolfgang Denk 			break;
320ad5bb451SWolfgang Denk 		}
321ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
322ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
323ad5bb451SWolfgang Denk 	}
324ad5bb451SWolfgang Denk 
325ad5bb451SWolfgang Denk 	return ret;
326ad5bb451SWolfgang Denk }
327ad5bb451SWolfgang Denk 
328ad5bb451SWolfgang Denk static int memory_post_test2 (unsigned long start, unsigned long size)
329ad5bb451SWolfgang Denk {
330ad5bb451SWolfgang Denk 	unsigned long i;
331ad5bb451SWolfgang Denk 	ulong *mem = (ulong *) start;
332ad5bb451SWolfgang Denk 	ulong readback;
333ad5bb451SWolfgang Denk 	int ret = 0;
334ad5bb451SWolfgang Denk 
335ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong); i++) {
336ad5bb451SWolfgang Denk 		mem[i] = 1 << (i % 32);
337ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
338ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
339ad5bb451SWolfgang Denk 	}
340ad5bb451SWolfgang Denk 
341ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
342ad5bb451SWolfgang Denk 		readback = mem[i];
343ad5bb451SWolfgang Denk 		if (readback != (1 << (i % 32))) {
344ad5bb451SWolfgang Denk 			post_log ("Memory error at %08x, "
345ad5bb451SWolfgang Denk 				  "wrote %08x, read %08x !\n",
346ad5bb451SWolfgang Denk 					  mem + i, 1 << (i % 32), readback);
347ad5bb451SWolfgang Denk 
348ad5bb451SWolfgang Denk 			ret = -1;
349ad5bb451SWolfgang Denk 			break;
350ad5bb451SWolfgang Denk 		}
351ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
352ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
353ad5bb451SWolfgang Denk 	}
354ad5bb451SWolfgang Denk 
355ad5bb451SWolfgang Denk 	return ret;
356ad5bb451SWolfgang Denk }
357ad5bb451SWolfgang Denk 
358ad5bb451SWolfgang Denk static int memory_post_test3 (unsigned long start, unsigned long size)
359ad5bb451SWolfgang Denk {
360ad5bb451SWolfgang Denk 	unsigned long i;
361ad5bb451SWolfgang Denk 	ulong *mem = (ulong *) start;
362ad5bb451SWolfgang Denk 	ulong readback;
363ad5bb451SWolfgang Denk 	int ret = 0;
364ad5bb451SWolfgang Denk 
365ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong); i++) {
366ad5bb451SWolfgang Denk 		mem[i] = i;
367ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
368ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
369ad5bb451SWolfgang Denk 	}
370ad5bb451SWolfgang Denk 
371ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
372ad5bb451SWolfgang Denk 		readback = mem[i];
373ad5bb451SWolfgang Denk 		if (readback != i) {
374ad5bb451SWolfgang Denk 			post_log ("Memory error at %08x, "
375ad5bb451SWolfgang Denk 				  "wrote %08x, read %08x !\n",
376ad5bb451SWolfgang Denk 					  mem + i, i, readback);
377ad5bb451SWolfgang Denk 
378ad5bb451SWolfgang Denk 			ret = -1;
379ad5bb451SWolfgang Denk 			break;
380ad5bb451SWolfgang Denk 		}
381ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
382ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
383ad5bb451SWolfgang Denk 	}
384ad5bb451SWolfgang Denk 
385ad5bb451SWolfgang Denk 	return ret;
386ad5bb451SWolfgang Denk }
387ad5bb451SWolfgang Denk 
388ad5bb451SWolfgang Denk static int memory_post_test4 (unsigned long start, unsigned long size)
389ad5bb451SWolfgang Denk {
390ad5bb451SWolfgang Denk 	unsigned long i;
391ad5bb451SWolfgang Denk 	ulong *mem = (ulong *) start;
392ad5bb451SWolfgang Denk 	ulong readback;
393ad5bb451SWolfgang Denk 	int ret = 0;
394ad5bb451SWolfgang Denk 
395ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong); i++) {
396ad5bb451SWolfgang Denk 		mem[i] = ~i;
397ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
398ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
399ad5bb451SWolfgang Denk 	}
400ad5bb451SWolfgang Denk 
401ad5bb451SWolfgang Denk 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
402ad5bb451SWolfgang Denk 		readback = mem[i];
403ad5bb451SWolfgang Denk 		if (readback != ~i) {
404ad5bb451SWolfgang Denk 			post_log ("Memory error at %08x, "
405ad5bb451SWolfgang Denk 				  "wrote %08x, read %08x !\n",
406ad5bb451SWolfgang Denk 					  mem + i, ~i, readback);
407ad5bb451SWolfgang Denk 
408ad5bb451SWolfgang Denk 			ret = -1;
409ad5bb451SWolfgang Denk 			break;
410ad5bb451SWolfgang Denk 		}
411ad5bb451SWolfgang Denk 		if (i % 1024 == 0)
412ad5bb451SWolfgang Denk 			WATCHDOG_RESET ();
413ad5bb451SWolfgang Denk 	}
414ad5bb451SWolfgang Denk 
415ad5bb451SWolfgang Denk 	return ret;
416ad5bb451SWolfgang Denk }
417ad5bb451SWolfgang Denk 
418ad5bb451SWolfgang Denk static int memory_post_tests (unsigned long start, unsigned long size)
419ad5bb451SWolfgang Denk {
420ad5bb451SWolfgang Denk 	int ret = 0;
421ad5bb451SWolfgang Denk 
422ad5bb451SWolfgang Denk 	if (ret == 0)
423ad5bb451SWolfgang Denk 		ret = memory_post_dataline ((unsigned long long *)start);
424ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
425ad5bb451SWolfgang Denk 	if (ret == 0)
426ad5bb451SWolfgang Denk 		ret = memory_post_addrline ((ulong *)start, (ulong *)start, size);
427ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
428ad5bb451SWolfgang Denk 	if (ret == 0)
429ad5bb451SWolfgang Denk 		ret = memory_post_addrline ((ulong *)(start + size - 8),
430ad5bb451SWolfgang Denk 					    (ulong *)start, size);
431ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
432ad5bb451SWolfgang Denk 	if (ret == 0)
433ad5bb451SWolfgang Denk 		ret = memory_post_test1 (start, size, 0x00000000);
434ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
435ad5bb451SWolfgang Denk 	if (ret == 0)
436ad5bb451SWolfgang Denk 		ret = memory_post_test1 (start, size, 0xffffffff);
437ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
438ad5bb451SWolfgang Denk 	if (ret == 0)
439ad5bb451SWolfgang Denk 		ret = memory_post_test1 (start, size, 0x55555555);
440ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
441ad5bb451SWolfgang Denk 	if (ret == 0)
442ad5bb451SWolfgang Denk 		ret = memory_post_test1 (start, size, 0xaaaaaaaa);
443ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
444ad5bb451SWolfgang Denk 	if (ret == 0)
445ad5bb451SWolfgang Denk 		ret = memory_post_test2 (start, size);
446ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
447ad5bb451SWolfgang Denk 	if (ret == 0)
448ad5bb451SWolfgang Denk 		ret = memory_post_test3 (start, size);
449ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
450ad5bb451SWolfgang Denk 	if (ret == 0)
451ad5bb451SWolfgang Denk 		ret = memory_post_test4 (start, size);
452ad5bb451SWolfgang Denk 	WATCHDOG_RESET ();
453ad5bb451SWolfgang Denk 
454ad5bb451SWolfgang Denk 	return ret;
455ad5bb451SWolfgang Denk }
456ad5bb451SWolfgang Denk 
457ad5bb451SWolfgang Denk int memory_post_test (int flags)
458ad5bb451SWolfgang Denk {
459ad5bb451SWolfgang Denk 	int ret = 0;
460ad5bb451SWolfgang Denk 	bd_t *bd = gd->bd;
461ad5bb451SWolfgang Denk 	unsigned long memsize = (bd->bi_memsize >= 256 << 20 ?
462ad5bb451SWolfgang Denk 				 256 << 20 : bd->bi_memsize) - (1 << 20);
463ad5bb451SWolfgang Denk 
464*9c02defcSYuri Tikhonov 	/* Limit area to be tested with the board info struct */
465*9c02defcSYuri Tikhonov 	if (CFG_SDRAM_BASE + memsize > (ulong)bd)
466*9c02defcSYuri Tikhonov 		memsize = (ulong)bd - CFG_SDRAM_BASE;
467ad5bb451SWolfgang Denk 
468ad5bb451SWolfgang Denk 	if (flags & POST_SLOWTEST) {
469ad5bb451SWolfgang Denk 		ret = memory_post_tests (CFG_SDRAM_BASE, memsize);
470ad5bb451SWolfgang Denk 	} else {			/* POST_NORMAL */
471ad5bb451SWolfgang Denk 
472ad5bb451SWolfgang Denk 		unsigned long i;
473ad5bb451SWolfgang Denk 
474ad5bb451SWolfgang Denk 		for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
475ad5bb451SWolfgang Denk 			if (ret == 0)
476ad5bb451SWolfgang Denk 				ret = memory_post_tests (i << 20, 0x800);
477ad5bb451SWolfgang Denk 			if (ret == 0)
478ad5bb451SWolfgang Denk 				ret = memory_post_tests ((i << 20) + 0xff800, 0x800);
479ad5bb451SWolfgang Denk 		}
480ad5bb451SWolfgang Denk 	}
481ad5bb451SWolfgang Denk 
482ad5bb451SWolfgang Denk 	return ret;
483ad5bb451SWolfgang Denk }
484ad5bb451SWolfgang Denk 
485ad5bb451SWolfgang Denk #endif /* CONFIG_POST & CFG_POST_MEMORY */
486ad5bb451SWolfgang Denk #endif /* CONFIG_POST */
487