xref: /rk3399_rockchip-uboot/cmd/mem.c (revision 2760efa8adeffe2ec398cdc174dd8e53864a864c)
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 /*
9  * Memory Functions
10  *
11  * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
12  */
13 
14 #include <common.h>
15 #include <console.h>
16 #include <bootretry.h>
17 #include <cli.h>
18 #include <command.h>
19 #include <console.h>
20 #include <hash.h>
21 #include <inttypes.h>
22 #include <mapmem.h>
23 #include <watchdog.h>
24 #include <asm/io.h>
25 #include <linux/compiler.h>
26 
27 DECLARE_GLOBAL_DATA_PTR;
28 
29 #ifndef CONFIG_SYS_MEMTEST_SCRATCH
30 #define CONFIG_SYS_MEMTEST_SCRATCH 0
31 #endif
32 
33 static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
34 
35 /* Display values from last command.
36  * Memory modify remembered values are different from display memory.
37  */
38 static ulong	dp_last_addr, dp_last_size;
39 static ulong	dp_last_length = 0x40;
40 static ulong	mm_last_addr, mm_last_size;
41 
42 static	ulong	base_address = 0;
43 
44 /* Memory Display
45  *
46  * Syntax:
47  *	md{.b, .w, .l, .q} {addr} {len}
48  */
49 #define DISP_LINE_LEN	16
50 static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
51 {
52 	ulong	addr, length, bytes;
53 	const void *buf;
54 	int	size;
55 	int rc = 0;
56 
57 	/* We use the last specified parameters, unless new ones are
58 	 * entered.
59 	 */
60 	addr = dp_last_addr;
61 	size = dp_last_size;
62 	length = dp_last_length;
63 
64 	if (argc < 2)
65 		return CMD_RET_USAGE;
66 
67 	if ((flag & CMD_FLAG_REPEAT) == 0) {
68 		/* New command specified.  Check for a size specification.
69 		 * Defaults to long if no or incorrect specification.
70 		 */
71 		if ((size = cmd_get_data_size(argv[0], 4)) < 0)
72 			return 1;
73 
74 		/* Address is specified since argc > 1
75 		*/
76 		addr = simple_strtoul(argv[1], NULL, 16);
77 		addr += base_address;
78 
79 		/* If another parameter, it is the length to display.
80 		 * Length is the number of objects, not number of bytes.
81 		 */
82 		if (argc > 2)
83 			length = simple_strtoul(argv[2], NULL, 16);
84 	}
85 
86 	bytes = size * length;
87 	invalidate_dcache_range(addr, addr+bytes);
88 	buf = map_sysmem(addr, bytes);
89 
90 	/* Print the lines. */
91 	print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
92 	addr += bytes;
93 	unmap_sysmem(buf);
94 
95 	dp_last_addr = addr;
96 	dp_last_length = length;
97 	dp_last_size = size;
98 	return (rc);
99 }
100 
101 static int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
102 {
103 	return mod_mem (cmdtp, 1, flag, argc, argv);
104 }
105 static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
106 {
107 	return mod_mem (cmdtp, 0, flag, argc, argv);
108 }
109 
110 static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
111 {
112 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
113 	u64 writeval;
114 #else
115 	ulong writeval;
116 #endif
117 	ulong	addr, count;
118 	int	size;
119 	void *buf, *start;
120 	ulong bytes;
121 
122 	if ((argc < 3) || (argc > 4))
123 		return CMD_RET_USAGE;
124 
125 	/* Check for size specification.
126 	*/
127 	if ((size = cmd_get_data_size(argv[0], 4)) < 1)
128 		return 1;
129 
130 	/* Address is specified since argc > 1
131 	*/
132 	addr = simple_strtoul(argv[1], NULL, 16);
133 	addr += base_address;
134 
135 	/* Get the value to write.
136 	*/
137 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
138 	writeval = simple_strtoull(argv[2], NULL, 16);
139 #else
140 	writeval = simple_strtoul(argv[2], NULL, 16);
141 #endif
142 
143 	/* Count ? */
144 	if (argc == 4) {
145 		count = simple_strtoul(argv[3], NULL, 16);
146 	} else {
147 		count = 1;
148 	}
149 
150 	bytes = size * count;
151 	start = map_sysmem(addr, bytes);
152 	buf = start;
153 	while (count-- > 0) {
154 		if (size == 4)
155 			*((u32 *)buf) = (u32)writeval;
156 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
157 		else if (size == 8)
158 			*((u64 *)buf) = (u64)writeval;
159 #endif
160 		else if (size == 2)
161 			*((u16 *)buf) = (u16)writeval;
162 		else
163 			*((u8 *)buf) = (u8)writeval;
164 		buf += size;
165 	}
166 	unmap_sysmem(start);
167 	flush_dcache_range(addr, addr+bytes);
168 	return 0;
169 }
170 
171 #ifdef CONFIG_MX_CYCLIC
172 static int do_mem_mdc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
173 {
174 	int i;
175 	ulong count;
176 
177 	if (argc < 4)
178 		return CMD_RET_USAGE;
179 
180 	count = simple_strtoul(argv[3], NULL, 10);
181 
182 	for (;;) {
183 		do_mem_md (NULL, 0, 3, argv);
184 
185 		/* delay for <count> ms... */
186 		for (i=0; i<count; i++)
187 			udelay (1000);
188 
189 		/* check for ctrl-c to abort... */
190 		if (ctrlc()) {
191 			puts("Abort\n");
192 			return 0;
193 		}
194 	}
195 
196 	return 0;
197 }
198 
199 static int do_mem_mwc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
200 {
201 	int i;
202 	ulong count;
203 
204 	if (argc < 4)
205 		return CMD_RET_USAGE;
206 
207 	count = simple_strtoul(argv[3], NULL, 10);
208 
209 	for (;;) {
210 		do_mem_mw (NULL, 0, 3, argv);
211 
212 		/* delay for <count> ms... */
213 		for (i=0; i<count; i++)
214 			udelay (1000);
215 
216 		/* check for ctrl-c to abort... */
217 		if (ctrlc()) {
218 			puts("Abort\n");
219 			return 0;
220 		}
221 	}
222 
223 	return 0;
224 }
225 #endif /* CONFIG_MX_CYCLIC */
226 
227 static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
228 {
229 	ulong	addr1, addr2, count, ngood, bytes;
230 	int	size;
231 	int     rcode = 0;
232 	const char *type;
233 	const void *buf1, *buf2, *base;
234 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
235 	u64 word1, word2;
236 #else
237 	ulong word1, word2;
238 #endif
239 
240 	if (argc != 4)
241 		return CMD_RET_USAGE;
242 
243 	/* Check for size specification.
244 	*/
245 	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
246 		return 1;
247 	type = size == 8 ? "double word" :
248 	       size == 4 ? "word" :
249 	       size == 2 ? "halfword" : "byte";
250 
251 	addr1 = simple_strtoul(argv[1], NULL, 16);
252 	addr1 += base_address;
253 
254 	addr2 = simple_strtoul(argv[2], NULL, 16);
255 	addr2 += base_address;
256 
257 	count = simple_strtoul(argv[3], NULL, 16);
258 
259 	bytes = size * count;
260 	base = buf1 = map_sysmem(addr1, bytes);
261 	buf2 = map_sysmem(addr2, bytes);
262 	for (ngood = 0; ngood < count; ++ngood) {
263 		if (size == 4) {
264 			word1 = *(u32 *)buf1;
265 			word2 = *(u32 *)buf2;
266 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
267 		} else if (size == 8) {
268 			word1 = *(u64 *)buf1;
269 			word2 = *(u64 *)buf2;
270 #endif
271 		} else if (size == 2) {
272 			word1 = *(u16 *)buf1;
273 			word2 = *(u16 *)buf2;
274 		} else {
275 			word1 = *(u8 *)buf1;
276 			word2 = *(u8 *)buf2;
277 		}
278 		if (word1 != word2) {
279 			ulong offset = buf1 - base;
280 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
281 			printf("%s at 0x%p (%#0*"PRIx64") != %s at 0x%p (%#0*"
282 			       PRIx64 ")\n",
283 			       type, (void *)(addr1 + offset), size, word1,
284 			       type, (void *)(addr2 + offset), size, word2);
285 #else
286 			printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
287 				type, (ulong)(addr1 + offset), size, word1,
288 				type, (ulong)(addr2 + offset), size, word2);
289 #endif
290 			rcode = 1;
291 			break;
292 		}
293 
294 		buf1 += size;
295 		buf2 += size;
296 
297 		/* reset watchdog from time to time */
298 		if ((ngood % (64 << 10)) == 0)
299 			WATCHDOG_RESET();
300 	}
301 	unmap_sysmem(buf1);
302 	unmap_sysmem(buf2);
303 
304 	printf("Total of %ld %s(s) were the same\n", ngood, type);
305 	return rcode;
306 }
307 
308 static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
309 {
310 	ulong	addr, dest, count;
311 	int	size;
312 
313 	if (argc != 4)
314 		return CMD_RET_USAGE;
315 
316 	/* Check for size specification.
317 	*/
318 	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
319 		return 1;
320 
321 	addr = simple_strtoul(argv[1], NULL, 16);
322 	addr += base_address;
323 
324 	dest = simple_strtoul(argv[2], NULL, 16);
325 	dest += base_address;
326 
327 	count = simple_strtoul(argv[3], NULL, 16);
328 
329 	if (count == 0) {
330 		puts ("Zero length ???\n");
331 		return 1;
332 	}
333 
334 #ifdef CONFIG_MTD_NOR_FLASH
335 	/* check if we are copying to Flash */
336 	if (addr2info(dest) != NULL) {
337 		int rc;
338 
339 		puts ("Copy to Flash... ");
340 
341 		rc = flash_write ((char *)addr, dest, count*size);
342 		if (rc != 0) {
343 			flash_perror (rc);
344 			return (1);
345 		}
346 		puts ("done\n");
347 		return 0;
348 	}
349 #endif
350 
351 	memcpy((void *)dest, (void *)addr, count * size);
352 
353 	return 0;
354 }
355 
356 static int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
357 		       char * const argv[])
358 {
359 	if (argc > 1) {
360 		/* Set new base address.
361 		*/
362 		base_address = simple_strtoul(argv[1], NULL, 16);
363 	}
364 	/* Print the current base address.
365 	*/
366 	printf("Base Address: 0x%08lx\n", base_address);
367 	return 0;
368 }
369 
370 static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
371 		       char * const argv[])
372 {
373 	ulong	addr, length, i, bytes;
374 	int	size;
375 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
376 	volatile u64 *llp;
377 #endif
378 	volatile u32 *longp;
379 	volatile u16 *shortp;
380 	volatile u8 *cp;
381 	const void *buf;
382 
383 	if (argc < 3)
384 		return CMD_RET_USAGE;
385 
386 	/*
387 	 * Check for a size specification.
388 	 * Defaults to long if no or incorrect specification.
389 	 */
390 	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
391 		return 1;
392 
393 	/* Address is always specified.
394 	*/
395 	addr = simple_strtoul(argv[1], NULL, 16);
396 
397 	/* Length is the number of objects, not number of bytes.
398 	*/
399 	length = simple_strtoul(argv[2], NULL, 16);
400 
401 	bytes = size * length;
402 	buf = map_sysmem(addr, bytes);
403 
404 	/* We want to optimize the loops to run as fast as possible.
405 	 * If we have only one object, just run infinite loops.
406 	 */
407 	if (length == 1) {
408 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
409 		if (size == 8) {
410 			llp = (u64 *)buf;
411 			for (;;)
412 				i = *llp;
413 		}
414 #endif
415 		if (size == 4) {
416 			longp = (u32 *)buf;
417 			for (;;)
418 				i = *longp;
419 		}
420 		if (size == 2) {
421 			shortp = (u16 *)buf;
422 			for (;;)
423 				i = *shortp;
424 		}
425 		cp = (u8 *)buf;
426 		for (;;)
427 			i = *cp;
428 	}
429 
430 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
431 	if (size == 8) {
432 		for (;;) {
433 			llp = (u64 *)buf;
434 			i = length;
435 			while (i-- > 0)
436 				*llp++;
437 		}
438 	}
439 #endif
440 	if (size == 4) {
441 		for (;;) {
442 			longp = (u32 *)buf;
443 			i = length;
444 			while (i-- > 0)
445 				*longp++;
446 		}
447 	}
448 	if (size == 2) {
449 		for (;;) {
450 			shortp = (u16 *)buf;
451 			i = length;
452 			while (i-- > 0)
453 				*shortp++;
454 		}
455 	}
456 	for (;;) {
457 		cp = (u8 *)buf;
458 		i = length;
459 		while (i-- > 0)
460 			*cp++;
461 	}
462 	unmap_sysmem(buf);
463 
464 	return 0;
465 }
466 
467 #ifdef CONFIG_LOOPW
468 static int do_mem_loopw(cmd_tbl_t *cmdtp, int flag, int argc,
469 			char * const argv[])
470 {
471 	ulong	addr, length, i, bytes;
472 	int	size;
473 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
474 	volatile u64 *llp;
475 	u64 data;
476 #else
477 	ulong	data;
478 #endif
479 	volatile u32 *longp;
480 	volatile u16 *shortp;
481 	volatile u8 *cp;
482 	void *buf;
483 
484 	if (argc < 4)
485 		return CMD_RET_USAGE;
486 
487 	/*
488 	 * Check for a size specification.
489 	 * Defaults to long if no or incorrect specification.
490 	 */
491 	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
492 		return 1;
493 
494 	/* Address is always specified.
495 	*/
496 	addr = simple_strtoul(argv[1], NULL, 16);
497 
498 	/* Length is the number of objects, not number of bytes.
499 	*/
500 	length = simple_strtoul(argv[2], NULL, 16);
501 
502 	/* data to write */
503 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
504 	data = simple_strtoull(argv[3], NULL, 16);
505 #else
506 	data = simple_strtoul(argv[3], NULL, 16);
507 #endif
508 
509 	bytes = size * length;
510 	buf = map_sysmem(addr, bytes);
511 
512 	/* We want to optimize the loops to run as fast as possible.
513 	 * If we have only one object, just run infinite loops.
514 	 */
515 	if (length == 1) {
516 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
517 		if (size == 8) {
518 			llp = (u64 *)buf;
519 			for (;;)
520 				*llp = data;
521 		}
522 #endif
523 		if (size == 4) {
524 			longp = (u32 *)buf;
525 			for (;;)
526 				*longp = data;
527 		}
528 		if (size == 2) {
529 			shortp = (u16 *)buf;
530 			for (;;)
531 				*shortp = data;
532 		}
533 		cp = (u8 *)buf;
534 		for (;;)
535 			*cp = data;
536 	}
537 
538 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
539 	if (size == 8) {
540 		for (;;) {
541 			llp = (u64 *)buf;
542 			i = length;
543 			while (i-- > 0)
544 				*llp++ = data;
545 		}
546 	}
547 #endif
548 	if (size == 4) {
549 		for (;;) {
550 			longp = (u32 *)buf;
551 			i = length;
552 			while (i-- > 0)
553 				*longp++ = data;
554 		}
555 	}
556 	if (size == 2) {
557 		for (;;) {
558 			shortp = (u16 *)buf;
559 			i = length;
560 			while (i-- > 0)
561 				*shortp++ = data;
562 		}
563 	}
564 	for (;;) {
565 		cp = (u8 *)buf;
566 		i = length;
567 		while (i-- > 0)
568 			*cp++ = data;
569 	}
570 }
571 #endif /* CONFIG_LOOPW */
572 
573 #ifdef CONFIG_CMD_MEMTEST
574 static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr,
575 			  vu_long *dummy)
576 {
577 	vu_long *addr;
578 	ulong errs = 0;
579 	ulong val, readback;
580 	int j;
581 	vu_long offset;
582 	vu_long test_offset;
583 	vu_long pattern;
584 	vu_long temp;
585 	vu_long anti_pattern;
586 	vu_long num_words;
587 	static const ulong bitpattern[] = {
588 		0x00000001,	/* single bit */
589 		0x00000003,	/* two adjacent bits */
590 		0x00000007,	/* three adjacent bits */
591 		0x0000000F,	/* four adjacent bits */
592 		0x00000005,	/* two non-adjacent bits */
593 		0x00000015,	/* three non-adjacent bits */
594 		0x00000055,	/* four non-adjacent bits */
595 		0xaaaaaaaa,	/* alternating 1/0 */
596 	};
597 
598 	num_words = (end_addr - start_addr) / sizeof(vu_long);
599 
600 	/*
601 	 * Data line test: write a pattern to the first
602 	 * location, write the 1's complement to a 'parking'
603 	 * address (changes the state of the data bus so a
604 	 * floating bus doesn't give a false OK), and then
605 	 * read the value back. Note that we read it back
606 	 * into a variable because the next time we read it,
607 	 * it might be right (been there, tough to explain to
608 	 * the quality guys why it prints a failure when the
609 	 * "is" and "should be" are obviously the same in the
610 	 * error message).
611 	 *
612 	 * Rather than exhaustively testing, we test some
613 	 * patterns by shifting '1' bits through a field of
614 	 * '0's and '0' bits through a field of '1's (i.e.
615 	 * pattern and ~pattern).
616 	 */
617 	addr = buf;
618 	for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
619 		val = bitpattern[j];
620 		for (; val != 0; val <<= 1) {
621 			*addr = val;
622 			*dummy  = ~val; /* clear the test data off the bus */
623 			readback = *addr;
624 			if (readback != val) {
625 				printf("FAILURE (data line): "
626 					"expected %08lx, actual %08lx\n",
627 						val, readback);
628 				errs++;
629 				if (ctrlc())
630 					return -1;
631 			}
632 			*addr  = ~val;
633 			*dummy  = val;
634 			readback = *addr;
635 			if (readback != ~val) {
636 				printf("FAILURE (data line): "
637 					"Is %08lx, should be %08lx\n",
638 						readback, ~val);
639 				errs++;
640 				if (ctrlc())
641 					return -1;
642 			}
643 		}
644 	}
645 
646 	/*
647 	 * Based on code whose Original Author and Copyright
648 	 * information follows: Copyright (c) 1998 by Michael
649 	 * Barr. This software is placed into the public
650 	 * domain and may be used for any purpose. However,
651 	 * this notice must not be changed or removed and no
652 	 * warranty is either expressed or implied by its
653 	 * publication or distribution.
654 	 */
655 
656 	/*
657 	* Address line test
658 
659 	 * Description: Test the address bus wiring in a
660 	 *              memory region by performing a walking
661 	 *              1's test on the relevant bits of the
662 	 *              address and checking for aliasing.
663 	 *              This test will find single-bit
664 	 *              address failures such as stuck-high,
665 	 *              stuck-low, and shorted pins. The base
666 	 *              address and size of the region are
667 	 *              selected by the caller.
668 
669 	 * Notes:	For best results, the selected base
670 	 *              address should have enough LSB 0's to
671 	 *              guarantee single address bit changes.
672 	 *              For example, to test a 64-Kbyte
673 	 *              region, select a base address on a
674 	 *              64-Kbyte boundary. Also, select the
675 	 *              region size as a power-of-two if at
676 	 *              all possible.
677 	 *
678 	 * Returns:     0 if the test succeeds, 1 if the test fails.
679 	 */
680 	pattern = (vu_long) 0xaaaaaaaa;
681 	anti_pattern = (vu_long) 0x55555555;
682 
683 	debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words);
684 	/*
685 	 * Write the default pattern at each of the
686 	 * power-of-two offsets.
687 	 */
688 	for (offset = 1; offset < num_words; offset <<= 1)
689 		addr[offset] = pattern;
690 
691 	/*
692 	 * Check for address bits stuck high.
693 	 */
694 	test_offset = 0;
695 	addr[test_offset] = anti_pattern;
696 
697 	for (offset = 1; offset < num_words; offset <<= 1) {
698 		temp = addr[offset];
699 		if (temp != pattern) {
700 			printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
701 				" expected 0x%.8lx, actual 0x%.8lx\n",
702 				start_addr + offset*sizeof(vu_long),
703 				pattern, temp);
704 			errs++;
705 			if (ctrlc())
706 				return -1;
707 		}
708 	}
709 	addr[test_offset] = pattern;
710 	WATCHDOG_RESET();
711 
712 	/*
713 	 * Check for addr bits stuck low or shorted.
714 	 */
715 	for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
716 		addr[test_offset] = anti_pattern;
717 
718 		for (offset = 1; offset < num_words; offset <<= 1) {
719 			temp = addr[offset];
720 			if ((temp != pattern) && (offset != test_offset)) {
721 				printf("\nFAILURE: Address bit stuck low or"
722 					" shorted @ 0x%.8lx: expected 0x%.8lx,"
723 					" actual 0x%.8lx\n",
724 					start_addr + offset*sizeof(vu_long),
725 					pattern, temp);
726 				errs++;
727 				if (ctrlc())
728 					return -1;
729 			}
730 		}
731 		addr[test_offset] = pattern;
732 	}
733 
734 	/*
735 	 * Description: Test the integrity of a physical
736 	 *		memory device by performing an
737 	 *		increment/decrement test over the
738 	 *		entire region. In the process every
739 	 *		storage bit in the device is tested
740 	 *		as a zero and a one. The base address
741 	 *		and the size of the region are
742 	 *		selected by the caller.
743 	 *
744 	 * Returns:     0 if the test succeeds, 1 if the test fails.
745 	 */
746 	num_words++;
747 
748 	/*
749 	 * Fill memory with a known pattern.
750 	 */
751 	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
752 		WATCHDOG_RESET();
753 		addr[offset] = pattern;
754 	}
755 
756 	/*
757 	 * Check each location and invert it for the second pass.
758 	 */
759 	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
760 		WATCHDOG_RESET();
761 		temp = addr[offset];
762 		if (temp != pattern) {
763 			printf("\nFAILURE (read/write) @ 0x%.8lx:"
764 				" expected 0x%.8lx, actual 0x%.8lx)\n",
765 				start_addr + offset*sizeof(vu_long),
766 				pattern, temp);
767 			errs++;
768 			if (ctrlc())
769 				return -1;
770 		}
771 
772 		anti_pattern = ~pattern;
773 		addr[offset] = anti_pattern;
774 	}
775 
776 	/*
777 	 * Check each location for the inverted pattern and zero it.
778 	 */
779 	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
780 		WATCHDOG_RESET();
781 		anti_pattern = ~pattern;
782 		temp = addr[offset];
783 		if (temp != anti_pattern) {
784 			printf("\nFAILURE (read/write): @ 0x%.8lx:"
785 				" expected 0x%.8lx, actual 0x%.8lx)\n",
786 				start_addr + offset*sizeof(vu_long),
787 				anti_pattern, temp);
788 			errs++;
789 			if (ctrlc())
790 				return -1;
791 		}
792 		addr[offset] = 0;
793 	}
794 
795 	return errs;
796 }
797 
798 static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr,
799 			    vu_long pattern, int iteration)
800 {
801 	vu_long *end;
802 	vu_long *addr;
803 	ulong errs = 0;
804 	ulong incr, length;
805 	ulong val, readback;
806 
807 	/* Alternate the pattern */
808 	incr = 1;
809 	if (iteration & 1) {
810 		incr = -incr;
811 		/*
812 		 * Flip the pattern each time to make lots of zeros and
813 		 * then, the next time, lots of ones.  We decrement
814 		 * the "negative" patterns and increment the "positive"
815 		 * patterns to preserve this feature.
816 		 */
817 		if (pattern & 0x80000000)
818 			pattern = -pattern;	/* complement & increment */
819 		else
820 			pattern = ~pattern;
821 	}
822 	length = (end_addr - start_addr) / sizeof(ulong);
823 	end = buf + length;
824 	printf("\rPattern %08lX  Writing..."
825 		"%12s"
826 		"\b\b\b\b\b\b\b\b\b\b",
827 		pattern, "");
828 
829 	for (addr = buf, val = pattern; addr < end; addr++) {
830 		WATCHDOG_RESET();
831 		*addr = val;
832 		val += incr;
833 	}
834 
835 	puts("Reading...");
836 
837 	for (addr = buf, val = pattern; addr < end; addr++) {
838 		WATCHDOG_RESET();
839 		readback = *addr;
840 		if (readback != val) {
841 			ulong offset = addr - buf;
842 
843 			printf("\nMem error @ 0x%08X: "
844 				"found %08lX, expected %08lX\n",
845 				(uint)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
846 				readback, val);
847 			errs++;
848 			if (ctrlc())
849 				return -1;
850 		}
851 		val += incr;
852 	}
853 
854 	return errs;
855 }
856 
857 /*
858  * Perform a memory test. A more complete alternative test can be
859  * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
860  * interrupted by ctrl-c or by a failure of one of the sub-tests.
861  */
862 static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
863 			char * const argv[])
864 {
865 	ulong start, end;
866 	vu_long *buf, *dummy;
867 	ulong iteration_limit = 0;
868 	int ret;
869 	ulong errs = 0;	/* number of errors, or -1 if interrupted */
870 	ulong pattern = 0;
871 	int iteration;
872 #if defined(CONFIG_SYS_ALT_MEMTEST)
873 	const int alt_test = 1;
874 #else
875 	const int alt_test = 0;
876 #endif
877 
878 	start = CONFIG_SYS_MEMTEST_START;
879 	end = CONFIG_SYS_MEMTEST_END;
880 
881 	if (argc > 1)
882 		if (strict_strtoul(argv[1], 16, &start) < 0)
883 			return CMD_RET_USAGE;
884 
885 	if (argc > 2)
886 		if (strict_strtoul(argv[2], 16, &end) < 0)
887 			return CMD_RET_USAGE;
888 
889 	if (argc > 3)
890 		if (strict_strtoul(argv[3], 16, &pattern) < 0)
891 			return CMD_RET_USAGE;
892 
893 	if (argc > 4)
894 		if (strict_strtoul(argv[4], 16, &iteration_limit) < 0)
895 			return CMD_RET_USAGE;
896 
897 	if (end < start) {
898 		printf("Refusing to do empty test\n");
899 		return -1;
900 	}
901 
902 	printf("Testing %08lx ... %08lx:\n", start, end);
903 	debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
904 	      start, end);
905 
906 	buf = map_sysmem(start, end - start);
907 	dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
908 	for (iteration = 0;
909 			!iteration_limit || iteration < iteration_limit;
910 			iteration++) {
911 		if (ctrlc()) {
912 			errs = -1UL;
913 			break;
914 		}
915 
916 		printf("Iteration: %6d\r", iteration + 1);
917 		debug("\n");
918 		if (alt_test) {
919 			errs = mem_test_alt(buf, start, end, dummy);
920 		} else {
921 			errs = mem_test_quick(buf, start, end, pattern,
922 					      iteration);
923 		}
924 		if (errs == -1UL)
925 			break;
926 	}
927 
928 	/*
929 	 * Work-around for eldk-4.2 which gives this warning if we try to
930 	 * case in the unmap_sysmem() call:
931 	 * warning: initialization discards qualifiers from pointer target type
932 	 */
933 	{
934 		void *vbuf = (void *)buf;
935 		void *vdummy = (void *)dummy;
936 
937 		unmap_sysmem(vbuf);
938 		unmap_sysmem(vdummy);
939 	}
940 
941 	if (errs == -1UL) {
942 		/* Memory test was aborted - write a newline to finish off */
943 		putc('\n');
944 		ret = 1;
945 	} else {
946 		printf("Tested %d iteration(s) with %lu errors.\n",
947 			iteration, errs);
948 		ret = errs != 0;
949 	}
950 
951 	return ret;
952 }
953 #endif	/* CONFIG_CMD_MEMTEST */
954 
955 /* Modify memory.
956  *
957  * Syntax:
958  *	mm{.b, .w, .l, .q} {addr}
959  *	nm{.b, .w, .l, .q} {addr}
960  */
961 static int
962 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
963 {
964 	ulong	addr;
965 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
966 	u64 i;
967 #else
968 	ulong i;
969 #endif
970 	int	nbytes, size;
971 	void *ptr = NULL;
972 
973 	if (argc != 2)
974 		return CMD_RET_USAGE;
975 
976 	bootretry_reset_cmd_timeout();	/* got a good command to get here */
977 	/* We use the last specified parameters, unless new ones are
978 	 * entered.
979 	 */
980 	addr = mm_last_addr;
981 	size = mm_last_size;
982 
983 	if ((flag & CMD_FLAG_REPEAT) == 0) {
984 		/* New command specified.  Check for a size specification.
985 		 * Defaults to long if no or incorrect specification.
986 		 */
987 		if ((size = cmd_get_data_size(argv[0], 4)) < 0)
988 			return 1;
989 
990 		/* Address is specified since argc > 1
991 		*/
992 		addr = simple_strtoul(argv[1], NULL, 16);
993 		addr += base_address;
994 	}
995 
996 	/* Print the address, followed by value.  Then accept input for
997 	 * the next value.  A non-converted value exits.
998 	 */
999 	do {
1000 		ptr = map_sysmem(addr, size);
1001 		printf("%08lx:", addr);
1002 		if (size == 4)
1003 			printf(" %08x", *((u32 *)ptr));
1004 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1005 		else if (size == 8)
1006 			printf(" %016" PRIx64, *((u64 *)ptr));
1007 #endif
1008 		else if (size == 2)
1009 			printf(" %04x", *((u16 *)ptr));
1010 		else
1011 			printf(" %02x", *((u8 *)ptr));
1012 
1013 		nbytes = cli_readline(" ? ");
1014 		if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
1015 			/* <CR> pressed as only input, don't modify current
1016 			 * location and move to next. "-" pressed will go back.
1017 			 */
1018 			if (incrflag)
1019 				addr += nbytes ? -size : size;
1020 			nbytes = 1;
1021 			/* good enough to not time out */
1022 			bootretry_reset_cmd_timeout();
1023 		}
1024 #ifdef CONFIG_BOOT_RETRY_TIME
1025 		else if (nbytes == -2) {
1026 			break;	/* timed out, exit the command	*/
1027 		}
1028 #endif
1029 		else {
1030 			char *endp;
1031 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1032 			i = simple_strtoull(console_buffer, &endp, 16);
1033 #else
1034 			i = simple_strtoul(console_buffer, &endp, 16);
1035 #endif
1036 			nbytes = endp - console_buffer;
1037 			if (nbytes) {
1038 				/* good enough to not time out
1039 				 */
1040 				bootretry_reset_cmd_timeout();
1041 				if (size == 4)
1042 					*((u32 *)ptr) = i;
1043 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1044 				else if (size == 8)
1045 					*((u64 *)ptr) = i;
1046 #endif
1047 				else if (size == 2)
1048 					*((u16 *)ptr) = i;
1049 				else
1050 					*((u8 *)ptr) = i;
1051 				if (incrflag)
1052 					addr += size;
1053 			}
1054 		}
1055 	} while (nbytes);
1056 	if (ptr)
1057 		unmap_sysmem(ptr);
1058 
1059 	mm_last_addr = addr;
1060 	mm_last_size = size;
1061 	return 0;
1062 }
1063 
1064 #ifdef CONFIG_CMD_CRC32
1065 
1066 static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1067 {
1068 	int flags = 0;
1069 	int ac;
1070 	char * const *av;
1071 
1072 	if (argc < 3)
1073 		return CMD_RET_USAGE;
1074 
1075 	av = argv + 1;
1076 	ac = argc - 1;
1077 #ifdef CONFIG_CRC32_VERIFY
1078 	if (strcmp(*av, "-v") == 0) {
1079 		flags |= HASH_FLAG_VERIFY | HASH_FLAG_ENV;
1080 		av++;
1081 		ac--;
1082 	}
1083 #endif
1084 
1085 	return hash_command("crc32", flags, cmdtp, flag, ac, av);
1086 }
1087 
1088 #endif
1089 
1090 /**************************************************/
1091 U_BOOT_CMD(
1092 	md,	3,	1,	do_mem_md,
1093 	"memory display",
1094 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1095 	"[.b, .w, .l, .q] address [# of objects]"
1096 #else
1097 	"[.b, .w, .l] address [# of objects]"
1098 #endif
1099 );
1100 
1101 
1102 U_BOOT_CMD(
1103 	mm,	2,	1,	do_mem_mm,
1104 	"memory modify (auto-incrementing address)",
1105 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1106 	"[.b, .w, .l, .q] address"
1107 #else
1108 	"[.b, .w, .l] address"
1109 #endif
1110 );
1111 
1112 
1113 U_BOOT_CMD(
1114 	nm,	2,	1,	do_mem_nm,
1115 	"memory modify (constant address)",
1116 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1117 	"[.b, .w, .l, .q] address"
1118 #else
1119 	"[.b, .w, .l] address"
1120 #endif
1121 );
1122 
1123 U_BOOT_CMD(
1124 	mw,	4,	1,	do_mem_mw,
1125 	"memory write (fill)",
1126 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1127 	"[.b, .w, .l, .q] address value [count]"
1128 #else
1129 	"[.b, .w, .l] address value [count]"
1130 #endif
1131 );
1132 
1133 U_BOOT_CMD(
1134 	cp,	4,	1,	do_mem_cp,
1135 	"memory copy",
1136 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1137 	"[.b, .w, .l, .q] source target count"
1138 #else
1139 	"[.b, .w, .l] source target count"
1140 #endif
1141 );
1142 
1143 U_BOOT_CMD(
1144 	cmp,	4,	1,	do_mem_cmp,
1145 	"memory compare",
1146 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1147 	"[.b, .w, .l, .q] addr1 addr2 count"
1148 #else
1149 	"[.b, .w, .l] addr1 addr2 count"
1150 #endif
1151 );
1152 
1153 #ifdef CONFIG_CMD_CRC32
1154 
1155 #ifndef CONFIG_CRC32_VERIFY
1156 
1157 U_BOOT_CMD(
1158 	crc32,	4,	1,	do_mem_crc,
1159 	"checksum calculation",
1160 	"address count [addr]\n    - compute CRC32 checksum [save at addr]"
1161 );
1162 
1163 #else	/* CONFIG_CRC32_VERIFY */
1164 
1165 U_BOOT_CMD(
1166 	crc32,	5,	1,	do_mem_crc,
1167 	"checksum calculation",
1168 	"address count [addr]\n    - compute CRC32 checksum [save at addr]\n"
1169 	"-v address count crc\n    - verify crc of memory area"
1170 );
1171 
1172 #endif	/* CONFIG_CRC32_VERIFY */
1173 
1174 #endif
1175 
1176 #ifdef CONFIG_CMD_MEMINFO
1177 __weak void board_show_dram(phys_size_t size)
1178 {
1179 	puts("DRAM:  ");
1180 	print_size(size, "\n");
1181 }
1182 
1183 static int do_mem_info(cmd_tbl_t *cmdtp, int flag, int argc,
1184 		       char * const argv[])
1185 {
1186 	board_show_dram(gd->ram_size);
1187 
1188 	return 0;
1189 }
1190 #endif
1191 
1192 U_BOOT_CMD(
1193 	base,	2,	1,	do_mem_base,
1194 	"print or set address offset",
1195 	"\n    - print address offset for memory commands\n"
1196 	"base off\n    - set address offset for memory commands to 'off'"
1197 );
1198 
1199 U_BOOT_CMD(
1200 	loop,	3,	1,	do_mem_loop,
1201 	"infinite loop on address range",
1202 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1203 	"[.b, .w, .l, .q] address number_of_objects"
1204 #else
1205 	"[.b, .w, .l] address number_of_objects"
1206 #endif
1207 );
1208 
1209 #ifdef CONFIG_LOOPW
1210 U_BOOT_CMD(
1211 	loopw,	4,	1,	do_mem_loopw,
1212 	"infinite write loop on address range",
1213 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1214 	"[.b, .w, .l, .q] address number_of_objects data_to_write"
1215 #else
1216 	"[.b, .w, .l] address number_of_objects data_to_write"
1217 #endif
1218 );
1219 #endif /* CONFIG_LOOPW */
1220 
1221 #ifdef CONFIG_CMD_MEMTEST
1222 U_BOOT_CMD(
1223 	mtest,	5,	1,	do_mem_mtest,
1224 	"simple RAM read/write test",
1225 	"[start [end [pattern [iterations]]]]"
1226 );
1227 #endif	/* CONFIG_CMD_MEMTEST */
1228 
1229 #ifdef CONFIG_MX_CYCLIC
1230 U_BOOT_CMD(
1231 	mdc,	4,	1,	do_mem_mdc,
1232 	"memory display cyclic",
1233 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1234 	"[.b, .w, .l, .q] address count delay(ms)"
1235 #else
1236 	"[.b, .w, .l] address count delay(ms)"
1237 #endif
1238 );
1239 
1240 U_BOOT_CMD(
1241 	mwc,	4,	1,	do_mem_mwc,
1242 	"memory write cyclic",
1243 #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
1244 	"[.b, .w, .l, .q] address value delay(ms)"
1245 #else
1246 	"[.b, .w, .l] address value delay(ms)"
1247 #endif
1248 );
1249 #endif /* CONFIG_MX_CYCLIC */
1250 
1251 #ifdef CONFIG_CMD_MEMINFO
1252 U_BOOT_CMD(
1253 	meminfo,	3,	1,	do_mem_info,
1254 	"display memory information",
1255 	""
1256 );
1257 #endif
1258