1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Test commands				File: ui_memtest.c
5    *
6    *  Modified by :  Khin Zaw
7    *
8    *  a complete memory test
9    *
10    *  A simple memory test
11    *
12    *  Author:  Mitch Lichtenberg
13    *
14    *********************************************************************
15    *
16    *  Copyright 2000,2001,2002,2003
17    *  Broadcom Corporation. All rights reserved.
18    *
19    *  This software is furnished under license and may be used and
20    *  copied only in accordance with the following terms and
21    *  conditions.  Subject to these conditions, you may download,
22    *  copy, install, use, modify and distribute modified or unmodified
23    *  copies of this software in source and/or binary form.  No title
24    *  or ownership is transferred hereby.
25    *
26    *  1) Any source code used, modified or distributed must reproduce
27    *     and retain this copyright notice and list of conditions
28    *     as they appear in the source file.
29    *
30    *  2) No right is granted to use any trade name, trademark, or
31    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
32    *     name may not be used to endorse or promote products derived
33    *     from this software without the prior written permission of
34    *     Broadcom Corporation.
35    *
36    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48    *     THE POSSIBILITY OF SUCH DAMAGE.
49    ********************************************************************* */
50
51
52#include "cfe.h"
53#include "sbmips.h"
54
55#include "ui_command.h"
56
57#include "cfe_mem.h"
58#include "lib_hssubr.h"
59#include "exception.h"
60
61#ifdef _BIGSUR_
62#include "bcm1480_regs.h"
63#include "bcm1480_scd.h"
64#endif
65
66static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]);
67#ifndef BCM47XX
68static int ui_cmd_randmemtest(ui_cmdline_t *cmd,int argc,char *argv[]);
69#endif
70
71#ifndef _SB_MAKE64
72#define _SB_MAKE64(x) ((uint64_t)(x))
73#endif
74#ifndef _SB_MAKEMASK
75#define _SB_MAKEMASK(v,n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n))
76#endif
77#ifndef _SB_MAKEMASK1
78#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
79#endif
80
81
82int ui_init_memtestcmds(void);
83
84int ui_init_memtestcmds(void)
85{
86    cmd_addcmd("memorytest",
87	       ui_cmd_memorytest,
88	       NULL,
89	       "Tests all available memory",
90	       "",
91	       "-loop;Loop forever or until keypress|"
92	       "-stoponerror;Stop if error occurs while looping|"
93	       "-cca=*;Use specified cacheability attribute|"
94	       "-arena=*;Test only specified arena index");
95
96#ifndef BCM47XX
97    cmd_addcmd("randmemtest",
98	       ui_cmd_randmemtest,
99	       NULL,
100	       "Tests memory using random access pattern",
101	       "randmemtest [num_mb]",
102	       "-loop;Loop forever or until keypress|"
103	       "-stoponerror;Stop if error occurs while looping|"
104	       "-cca=*;Use specified cacheability attribute|"
105	       "-ignoreerror;Ignore errors, don't print anything|"
106	       "-arena=*;Test only specified arena index");
107#endif /* BCM47XX */
108    return 0;
109}
110
111
112/* extensive memory tests */
113
114static void inline uacwrite(volatile uint64_t *srcadr,hsaddr_t dstadr)
115{
116__asm __volatile ("ld $8, 0(%0) ; "
117		  "ld $9, 8(%0) ; "
118		  "ld $10, 16(%0) ; "
119		  "ld $11, 24(%0) ; "
120		  "sync ; "
121		  ".align 4 ; "
122		  "sd $8,  0(%1) ; "
123		  "sd $9,  8(%1) ; "
124		  "sd $10, 16(%1) ; "
125		  "sd $11, 24(%1) ; "
126		  "sync" :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11");
127}
128
129static void inline readline(hsaddr_t srcadr,volatile uint64_t *dstadr)
130{
131__asm __volatile ("ld $8, 0(%0) ; "
132		  "ld $9, 8(%0) ; "
133		  "ld $10, 16(%0) ; "
134		  "ld $11, 24(%0) ; "
135		  "sd $8,  0(%1) ; "
136		  "sd $9,  8(%1) ; "
137		  "sd $10, 16(%1) ; "
138		  "sd $11, 24(%1) ; "
139		   :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11");
140}
141
142
143#define TEST_DATA_LEN 4
144#define CACHE_LINE_LEN 32
145
146static int test_arena(hsaddr_t arena_start,hsaddr_t arena_size,int cca,int stoponerror);
147
148
149static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[])
150{
151    int arena;
152    int error;
153    int arena_type;
154    uint64_t arena_start, arena_size;
155    int forever;
156    int passcnt;
157    int stoponerr = 0;
158    hsaddr_t phys_addr;
159    hsaddr_t mem_base;
160    int cca = K_CALG_UNCACHED_ACCEL;
161    int arenanum = -1;
162    char *x;
163    int res;
164
165    forever = cmd_sw_isset(cmd,"-loop");
166    stoponerr = cmd_sw_isset(cmd,"-stoponerror");
167    if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x);
168    if (cmd_sw_value(cmd,"-arena",&x)) arenanum = atoi(x);
169
170    printf("Available memory arenas:\n");
171    arena = 0;
172    while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) {
173	phys_addr = arena_start;    /* actual physical address */
174#if CPUCFG_REGS64
175	mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */
176#else
177	mem_base = PHYS_TO_K1(phys_addr); /* virtual address */
178#endif
179	xprintf("phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size);
180	arena++;
181	}
182
183    passcnt = 0;
184    res = 0;
185
186    printf("\nTesting memory.\n");
187    do {
188
189	passcnt++;
190	if (forever) {
191	    if (console_status()) break;
192	    printf("***** Iteration %d *****\n",passcnt);
193	    }
194
195	arena = 0;
196	error = 0;
197
198	while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) {
199
200	    /*
201	     * See if we were asked to do just one part of memory.
202	     */
203
204	    if ((arenanum >= 0) && (arena != arenanum)) {
205		arena++;
206		continue;
207		}
208
209	    /*
210	     * If we enumerated the locore area, avoid it.
211	     */
212
213	    if (arena_start == 0) {
214		arena_start += CFE_LOCORE_GLOBAL_END;
215		arena_size -= CFE_LOCORE_GLOBAL_END;
216		}
217
218	    res = test_arena(arena_start,arena_size,cca,stoponerr);
219
220	    if (stoponerr && (res < 0)) {
221		forever = 0;
222		break;
223		}
224	    arena++;
225	    }
226
227	}  while (forever);
228
229    return res;
230}
231
232static int test_arena(hsaddr_t arena_start,hsaddr_t arena_size,int cca,int stoponerr)
233{
234
235    static volatile uint64_t test_data[TEST_DATA_LEN];
236    static volatile uint64_t check_data[TEST_DATA_LEN];
237    int exitLoop;
238    int error;
239    hsaddr_t phys_addr;
240    hsaddr_t offset;
241    hsaddr_t mem_base;
242    long i;
243    hsaddr_t dst_adr, cache_dst_adr;
244    long cda,tda;
245
246    phys_addr = arena_start;    /* actual physical address */
247#if CPUCFG_REGS64
248    mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */
249#else
250    mem_base = PHYS_TO_K1(phys_addr); /* virtual address */
251#endif
252
253    xprintf("\n");
254    xprintf("Testing: phys = %016llX, virt = %016llX, size = %016llX\n",
255	    phys_addr, mem_base, arena_size);
256
257int testno, patno ;
258
259#define NUMTESTNO 12
260
261typedef struct testinfo_s {
262	char *testname;
263	int num_patterns;
264	uint64_t test_pattern[64];
265} testinfo_t;
266
267const testinfo_t test_patterns[] = {
268		{"All Zeros",4,          {0,0,0,0}},
269		{"All Ones",4,           {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}} ,
270		{"Alternate Zeros/Ones",4,           {0ULL,0xFFFFFFFFFFFFFFFFULL,0ULL,0xFFFFFFFFFFFFFFFFULL}} ,
271		{"Checker Board",4,      {0xAAAAAAAAAAAAAAAAULL,0x5555555555555555ULL,0xAAAAAAAAAAAAAAAAULL,0x5555555555555555ULL}} ,
272		{"Walking 1 byte(8)",8,  {0x0101010101010101ULL,0x0202020202020202ULL,0x0404040404040404ULL,0x0808080808080808ULL,
273					  0x1010101010101010ULL,0x2020202020202020ULL,0x4040404040404040ULL,0x8080808080808080ULL}} ,
274		{"Walking 1 word(16)",16,{0x0001000100010001ULL,0x0002000200020002ULL,0x0004000400040004ULL,0x0008000800080008ULL,
275				          0x0010001000100010ULL,0x0020002000200020ULL,0x0040004000400040ULL,0x0080008000800080ULL,
276					  0x0100010001000100ULL,0x0200020002000200ULL,0x0400040004000400ULL,0x0800080008000800ULL,
277					  0x1000100010001000ULL,0x2000200020002000ULL,0x4000400040004000ULL,0x8000800080008000ULL}} ,
278		{"Walking 0 byte(8)",8,  {0xFEFEFEFEFEFEFEFEULL,0xFDFDFDFDFDFDFDFDULL,0xFBFBFBFBFBFBFBFBULL,0xF7F7F7F7F7F7F7F7ULL,
279				          0xEFEFEFEFEFEFEFEFULL,0xDFDFDFDFDFDFDFDFULL,0xBFBFBFBFBFBFBFBFULL,0x7F7F7F7F7F7F7F7FULL}} ,
280		{"Walking 0 word(16)",16,{0xFFFEFFFEFFFEFFFEULL,0xFFFDFFFDFFFDFFFDULL,0xFFFBFFFBFFFBFFFBULL,0xFFF7FFF7FFF7FFF7ULL,
281					  0xFFEFFFEFFFEFFFEFULL,0xFFDFFFDFFFDFFFDFULL,0xFFBFFFBFFFBFFFBFULL,0xFF7FFF7FFF7FFF7FULL,
282					  0xFEFFFEFFFEFFFEFFULL,0xFDFFFDFFFDFFFDFFULL,0xFBFFFBFFFBFFFBFFULL,0xF7FFF7FFF7FFF7FFULL,
283					  0xEFFFEFFFEFFFEFFFULL,0xDFFFDFFFDFFFDFFFULL,0xBFFFBFFFBFFFBFFFULL,0x7FFF7FFF7FFF7FFFULL}},
284		{"Walking ECC8 0 ",8,    {0x0000004000808082ULL,0x0000004000808084ULL,0x0000004000808090ULL,0x0000004000800001ULL,   // fe fd fb f7
285					  0x0000004000008001ULL,0x0000000000808001ULL,0x0000000000000080ULL,0x0000004000808081ULL}} ,// ef df bf 7f
286		{"Walking ECC8 1 ",8,    {0x0000004000808014ULL,0x0000004000808012ULL,0x0000004000808006ULL,0x0000004000800097ULL,   // 01 02 04 08
287				          0x0000004000008097ULL,0x0000000000808097ULL,0x0000000000000016ULL,0x0000004000808017ULL}} ,// 10 20 40 80
288	        {"Crosstalk 1",64,       {0x0001000100010001ULL,0xFFFFFFFFFFFFFFFFULL,0x0001000100010001ULL,0xFFFFFFFFFFFFFFFFULL,
289				          0x0002000200020002ULL,0xFFFFFFFFFFFFFFFFULL,0x0002000200020002ULL,0xFFFFFFFFFFFFFFFFULL,
290				          0x0004000400040004ULL,0xFFFFFFFFFFFFFFFFULL,0x0004000400040004ULL,0xFFFFFFFFFFFFFFFFULL,
291				          0x0008000800080008ULL,0xFFFFFFFFFFFFFFFFULL,0x0008000800080008ULL,0xFFFFFFFFFFFFFFFFULL,
292				          0x0010001000100010ULL,0xFFFFFFFFFFFFFFFFULL,0x0010001000100010ULL,0xFFFFFFFFFFFFFFFFULL,
293				          0x0020002000200020ULL,0xFFFFFFFFFFFFFFFFULL,0x0020002000200020ULL,0xFFFFFFFFFFFFFFFFULL,
294				          0x0040004000400040ULL,0xFFFFFFFFFFFFFFFFULL,0x0040004000400040ULL,0xFFFFFFFFFFFFFFFFULL,
295					  0x0080008000800080ULL,0xFFFFFFFFFFFFFFFFULL,0x0080008000800080ULL,0xFFFFFFFFFFFFFFFFULL,
296					  0x0100010001000100ULL,0xFFFFFFFFFFFFFFFFULL,0x0100010001000100ULL,0xFFFFFFFFFFFFFFFFULL,
297				          0x0200020002000200ULL,0xFFFFFFFFFFFFFFFFULL,0x0200020002000200ULL,0xFFFFFFFFFFFFFFFFULL,
298				          0x0400040004000400ULL,0xFFFFFFFFFFFFFFFFULL,0x0400040004000400ULL,0xFFFFFFFFFFFFFFFFULL,
299				          0x0800080008000800ULL,0xFFFFFFFFFFFFFFFFULL,0x0800080008000800ULL,0xFFFFFFFFFFFFFFFFULL,
300				          0x1000100010001000ULL,0xFFFFFFFFFFFFFFFFULL,0x1000100010001000ULL,0xFFFFFFFFFFFFFFFFULL,
301				          0x2000200020002000ULL,0xFFFFFFFFFFFFFFFFULL,0x2000200020002000ULL,0xFFFFFFFFFFFFFFFFULL,
302				          0x4000400040004000ULL,0xFFFFFFFFFFFFFFFFULL,0x4000400040004000ULL,0xFFFFFFFFFFFFFFFFULL,
303					  0x8000800080008000ULL,0xFFFFFFFFFFFFFFFFULL,0x8000800080008000ULL,0xFFFFFFFFFFFFFFFFULL }} ,
304		{"Crosstalk 0",64,       {0xFFFEFFFEFFFEFFFEULL,0,0xFFFEFFFEFFFEFFFEULL,0,
305					  0xFFFDFFFDFFFDFFFDULL,0,0xFFFDFFFDFFFDFFFDULL,0,
306					  0xFFFBFFFBFFFBFFFBULL,0,0xFFFBFFFBFFFBFFFBULL,0,
307					  0xFFF7FFF7FFF7FFF7ULL,0,0xFFF7FFF7FFF7FFF7ULL,0,
308					  0xFFEFFFEFFFEFFFEFULL,0,0xFFEFFFEFFFEFFFEFULL,0,
309					  0xFFDFFFDFFFDFFFDFULL,0,0xFFDFFFDFFFDFFFDFULL,0,
310					  0xFFBFFFBFFFBFFFBFULL,0,0xFFBFFFBFFFBFFFBFULL,0,
311					  0xFF7FFF7FFF7FFF7FULL,0,0xFF7FFF7FFF7FFF7FULL,0,
312					  0xFEFFFEFFFEFFFEFFULL,0,0xFEFFFEFFFEFFFEFFULL,0,
313					  0xFDFFFDFFFDFFFDFFULL,0,0xFDFFFDFFFDFFFDFFULL,0,
314					  0xFBFFFBFFFBFFFBFFULL,0,0xFBFFFBFFFBFFFBFFULL,0,
315					  0xF7FFF7FFF7FFF7FFULL,0,0xF7FFF7FFF7FFF7FFULL,0,
316					  0xEFFFEFFFEFFFEFFFULL,0,0xEFFFEFFFEFFFEFFFULL,0,
317					  0xDFFFDFFFDFFFDFFFULL,0,0xDFFFDFFFDFFFDFFFULL,0,
318					  0xBFFFBFFFBFFFBFFFULL,0,0xBFFFBFFFBFFFBFFFULL,0,
319					  0x7FFF7FFF7FFF7FFFULL,0,0x7FFF7FFF7FFF7FFFULL,0}}
320} ;
321// address test
322    xprintf("Address test :Writing: [address|5555][~][aaaa|address][~] ");
323    exitLoop = 0;
324
325    for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
326	dst_adr = (mem_base+offset);
327	test_data[0] = ((uint64_t)dst_adr<<32)|0x55555555;
328	test_data[1] = ~test_data[0];
329	test_data[2] = 0xaaaaaaaa00000000ULL|(dst_adr & 0xffffffff);
330	test_data[3] = ~test_data[2];
331	uacwrite(test_data, dst_adr);
332        if ((dst_adr>>28)&((dst_adr&0xfffffff)==0)) xprintf(".");
333	}
334
335    xprintf("Reading: ");
336
337    error = 0;
338    for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
339	dst_adr = (mem_base+offset);
340	test_data[0] = ((uint64_t)dst_adr<<32)|0x55555555;
341	test_data[1] = ~test_data[0];
342	test_data[2] = 0xaaaaaaaa00000000ULL|(dst_adr & 0xffffffff);
343	test_data[3] = ~test_data[2];
344	cache_dst_adr = (mem_base+offset);
345	readline(cache_dst_adr,check_data);
346        if ((dst_adr>>28)&((dst_adr&0xfffffff)==0)) xprintf(".");
347	for (i = 0; i < TEST_DATA_LEN; i++) {
348	    cda = check_data[i];
349	    tda = test_data[i];
350	    if (cda != tda) {
351		xprintf("mem[%016llX] %016llX != %016llX\n",
352			mem_base+offset+(i*8),cda,tda);
353		error++;
354		}
355	    }
356	if (error) break;
357    }
358    xprintf("Done!\n");
359
360    if (error) return -1;
361    // data test
362    for (testno = 0 ; testno < NUMTESTNO ; testno++ ) {
363
364    xprintf("Data Test %d : writing %s. ",testno,test_patterns[testno].testname);
365
366    patno = 0 ;
367    for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
368	dst_adr = (mem_base+offset);
369            test_data[0] = test_patterns[testno].test_pattern[patno];
370            test_data[1] = test_patterns[testno].test_pattern[patno+1];
371            test_data[2] = test_patterns[testno].test_pattern[patno+2];
372            test_data[3] = test_patterns[testno].test_pattern[patno+3];
373	    uacwrite(test_data, dst_adr);
374	    //if (testno==6) xprintf("W[%016llx]=%016llx,%016llx %016llx,%016llx\n",dst_adr,test_data[0],test_data[1],test_data[2],test_data[3]);
375  	    if (patno+4 < test_patterns[testno].num_patterns) patno+=4;
376	    else patno = 0 ;
377	    }
378
379
380    xprintf("Reading and checking :");
381
382    error = 0;
383    patno=0 ;
384    for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
385	dst_adr = (mem_base+offset);
386	cache_dst_adr = (mem_base+offset);
387            test_data[0] = test_patterns[testno].test_pattern[patno];
388            test_data[1] = test_patterns[testno].test_pattern[patno+1];
389            test_data[2] = test_patterns[testno].test_pattern[patno+2];
390            test_data[3] = test_patterns[testno].test_pattern[patno+3];
391	    //if (testno==6) xprintf("R[%016llx]=%016llx,%016llx %016llx,%016llx\n",dst_adr,test_data[0],test_data[1],test_data[2],test_data[3]);
392  	if(patno+4 < test_patterns[testno].num_patterns) patno+=4;
393	else patno = 0 ;
394
395	readline(cache_dst_adr,check_data);
396	for (i = 0; i < TEST_DATA_LEN; i++) {
397	    cda = check_data[i];
398	    tda = test_data[i];
399	    if (cda != tda) {
400		xprintf("mem[%016llX] %016llX != %016llX\n",
401			mem_base+offset+(i*8), cda, tda);
402		error++;
403		if (error > 25) return -1;
404	    }
405	if (error) break;
406	}
407    }
408    xprintf(" Done!\n");
409// end of patterns
410    }
411//
412    return error ? -1 : 0;
413}
414
415#define LFSR_M	22
416#define LFSR_TAP 21
417//#define LFSR_PERIOD 0x3fff80
418#define LFSR_PERIOD 0x3ffff
419
420static inline unsigned long nextval(unsigned long regval)
421{
422    unsigned long newbit;
423
424    newbit = (regval & 1) ^ ((regval & (1<<(LFSR_M - LFSR_TAP))) != 0);
425
426    regval = (regval >> 1) | (newbit << (LFSR_M-1));
427
428    return regval;
429}
430
431
432#ifndef BCM47XX
433#define START_PHYS 0x1000
434static int randmemtest(int num_mb,int high_mb,int cca,int stoponerr,int ignoreerr)
435{
436#if CPUCFG_REGS64
437    hsaddr_t membase = PHYS_TO_XKPHYS(cca,START_PHYS);
438#else
439    hsaddr_t membase = PHYS_TO_K1(START_PHYS); /* UNCACHED virtual address */
440#endif
441    unsigned long lfsr;
442    uint64_t idx;
443    uint64_t maxidx;
444    uint64_t highlfsr;
445    int error = 0;
446    register uint64_t pattern0,pattern1,pattern2,pattern3,x;
447
448    highlfsr = (high_mb << 15);
449    if (highlfsr == 0) highlfsr = 0x3fff80;
450
451    maxidx = (uint64_t) ((num_mb << 15)-1);
452
453    printf("Highest physaddr is %016llX\n",highlfsr<<5);
454    printf("Writing (memory base %016llX)\n",membase);
455    lfsr = (1<<LFSR_M)-1;
456    for (idx = 0; idx < maxidx; idx++) {
457	pattern0 = 0x5555555555555555ULL ^ (lfsr | (lfsr << LFSR_M)); pattern1 = ~pattern0;
458	pattern3 = 0xaaaaaaaaaaaaaaaaULL ^ (idx | (idx << LFSR_M)) ; pattern2 = ~pattern3;
459
460	if (lfsr < highlfsr) {
461	    __asm __volatile ( " .align 4 ; "
462			       " sd %0,0(%4) ; "
463			       " sd %1,8(%4) ; "
464			       " sd %2,16(%4) ; "
465			       " sd %3,24(%4) ; "
466			       : : "r"(pattern0),"r"(pattern1),"r"(pattern2),"r"(pattern3),
467			       "r"(membase+(hsaddr_t)(lfsr << 5)));
468	    }
469	lfsr = nextval(lfsr);
470	}
471
472    printf("Reading.\n");
473    lfsr = (1<<LFSR_M)-1;
474    for (idx = 0; idx < maxidx; idx++) {
475
476	if (lfsr < highlfsr) { /* stay within 128MB */
477	    hsaddr_t addr = (membase + (hsaddr_t)(lfsr<<5));
478	    __asm __volatile ( " ld %0,0(%4) ; "
479			       " ld %1,8(%4) ; "
480			       " ld %2,16(%4) ; "
481			       " ld %3,24(%4)"
482			       : "=r"(pattern0),"=r"(pattern1),"=r"(pattern2),"=r"(pattern3) : "r"(addr));
483
484	    if (!ignoreerr) {
485	    x = 0x5555555555555555ULL ^ (lfsr | (lfsr << LFSR_M));
486	    if (pattern0 != x) {
487		printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr,pattern0,x,pattern0^x);
488		error++;
489		if (console_status()) break;
490		}
491
492	    x = ~x;
493	    if (pattern1 != x) {
494		printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+8,pattern1,x,pattern1^x);
495		error++;
496		if (console_status()) break;
497		}
498
499	    x = 0xaaaaaaaaaaaaaaaaULL ^ (idx | (idx << LFSR_M));
500	    if (pattern3 != x) {
501		printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+24,pattern3,x,pattern3^x);
502		error++;
503		if (console_status()) break;
504		}
505
506	    x = ~x;
507	    if (pattern2 != x) {
508		printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+16,pattern2,x,pattern2^x);
509		error++;
510		if (console_status()) break;
511		}
512		}
513
514	    if (error && stoponerr) break;
515	    }
516	lfsr = nextval(lfsr);
517	}
518    return error;
519}
520
521static int ui_cmd_randmemtest(ui_cmdline_t *cmd,int argc,char *argv[])
522{
523    int stoponerr = 1;
524    int ignoreerr = 0;
525    char *x;
526    int cca = K_CALG_UNCACHED_ACCEL;
527    int forever;
528    int error = 0;
529    int res;
530    int num_mb = 128;
531    int high_mb = 128;
532
533    ignoreerr = cmd_sw_isset(cmd,"-ignoreerror");
534    stoponerr = cmd_sw_isset(cmd,"-stoponerror");
535    if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x);
536    forever = cmd_sw_isset(cmd,"-loop");
537
538    if ((x = cmd_getarg(cmd,0))) num_mb = atoi(x);
539    if (num_mb > 128) num_mb = 128;
540
541    if ((x = cmd_getarg(cmd,1))) high_mb = atoi(x);
542    if (high_mb > 128) high_mb = 128;
543
544    do {
545#ifdef _BIGSUR_
546	SBWRITECSR(A_BUS_L2_ERRORS,0);
547	SBWRITECSR(A_BUS_MEM_IO_ERRORS,0);
548#endif
549	res = randmemtest(num_mb,high_mb,cca,stoponerr,ignoreerr);
550	if (res != 0) error = -1;
551	if ((res != 0) && stoponerr) break;
552#ifdef _BIGSUR_
553	do {
554	    uint64_t l2reg,memreg;
555	    l2reg = SBREADCSR(A_BUS_L2_ERRORS);
556	    memreg = SBREADCSR(A_BUS_MEM_IO_ERRORS);
557	    printf("L2: CorrECC=%d BadECC=%d   Mem: CorrECC=%d BadECC=%d\n",
558		   (int)G_SCD_L2ECC_CORR_D(l2reg),(int)G_SCD_L2ECC_BAD_D(l2reg),
559		   (int)G_SCD_MEM_ECC_CORR(memreg),(int)G_SCD_MEM_ECC_BAD(memreg));
560	    } while (0);
561#endif
562	} while (forever && !console_status());
563
564    return error;
565}
566#endif /* !BCM47XX */
567
568