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