#include /* Needed for KERN_INFO */ #include #include #include #include #include #include #include #include #include "diag_error.h" #include "memMarco.h" #include "memtest.h" #include "memsize.h" #include #include /*Memory Data Line diagnostic pattern*/ u64 gMemDLPattern[7] = { 0xAAAAAAAAAAAAAAAA, 0x5555555555555555, 0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000 }; /*Memory DWORD diagnostic pattern*/ u64 gMemDWPattern[6] = { 0xFFFFFFFFFFFFFFFF, //inverse: 0x00000000 //syndrome: 0x00 0xAAAAAAAAAAAAAAAA, //inverse: 0x55555555 //syndrome: 0x00 0xE1E1E1E1E1E1E1E1, //inverse: 0x1E1E1E1E //syndrome: 0xFF 0x3333333333333333, //inverse: 0xCCCCCCCC //syndrome: 0x99 0xFF00FF00FF00FF00, //inverse: 0x00FF00FF //syndrome: 0x00 0xBB44BB44BB44BB44 //inverse: 0x44BB44BB //syndrome: 0x66 }; void errorReport(mdc cmd, char *msg) { //comm_error(MODEL_ID, COMPONENT_ID, cmd.error_item, cmd.error_code, msg); commReportError(MEC_MEM, cmd.error_item, cmd.error_code, msg, 0, 0, 0, DG_FORMAT_NONE); //gDiagReportError = 1; //printk("[%04x-%04x-%02x-%04x] Error: %s \n",MODEL_ID, COMPONENT_ID, cmd.error_item, cmd.error_code, msg); } void marco_test(u64 startAddr) { u64 sizeTest=0; printk("before M_INIT_TEST_BASE %Ld \n", startAddr >> 20); M_INIT_TEST_BASE(startAddr); printk("after M_INIT_TEST_BASE %Ld \n", startAddr >> 20); M_INIT_TEST_REGION(startAddr, sizeTest); printk("after M_INIT_TEST_REGION %Ld size %Ld \n", startAddr >> 20, sizeTest >> 20); } /*** PROCEDURES ***/ /******************************************************************************* * PROCEDURE * * NAME: memDataLinesTest * SUMMARY: This procedure will test the data bus of the SDRAM * SCOPE: public * * DESCRIPTION: This test will write the data line pattern to memeory and read to verify * * RETURNS: * * NOTES: * */ void memDataLinesTest(u64 startAddr) { int idx; mdc cmd; printk("memDataLinesTest -> startAddr: 0x%Lx", startAddr); cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_DATALINES; for(idx=0 ;idx < ((sizeof(gMemDLPattern)/sizeof(u64))+1) ;idx++) { cmd.forward=1; if (idx==0) { cmd.verify_pattern=(u64) NULL; }else{ cmd.verify_pattern=gMemDLPattern[idx-1]; } if ( idx == (sizeof(gMemDLPattern)/sizeof(u64)) ) { cmd.write_pattern=(u64) NULL; }else{ cmd.write_pattern=gMemDLPattern[idx]; printk("Pattern no.%u = 0x%Lx\n",idx+1,gMemDLPattern[idx]); } if ( mem_region(cmd, 0, sizeof(int)) ) return; } } /******************************************************************************* * PROCEDURE * * NAME: memAddressLinesTest * SUMMARY: This procedure will test the address bus of the SDRAM * SCOPE: public * * DESCRIPTION: This test will write the address value to the order 2 address location and read to verify * * RETURNS: * * NOTES: * */ void memAddressLinesTest(u64 startAddr, u64 sizeTest) { u64 memsize; // The number of bits of the address line u64 addrOffset; // The offset to the testing address u64 AddrLineMask; int process_step=0; int show_process_step=0; mdc cmd; cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_ADDRESSLINES; M_INIT_TEST_BASE(startAddr); M_INIT_TEST_REGION(startAddr, sizeTest); memsize=memGetMemConfig(); AddrLineMask = (startAddr + sizeTest) - 1; printk("\n [START] memAddressLinesTestrocess: %d%% (write)\n\n", process_step); //for(addrOffset = 1; (startAddr + addrOffset) < memsize; addrOffset<<=1) for(addrOffset = 0; (startAddr + addrOffset) < memsize; addrOffset+=0x10000) { //printk("[memAddressLinesTest] (w) addrOffset 0x%lx \n",addrOffset); cmd.forward=1; cmd.verify_pattern= (u64) NULL; cmd.write_pattern=gMemDLPattern[0]; //mem_region(cmd, addrOffset, sizeof(int)); if ( mem_region(cmd, addrOffset, 0x400) ) return; while (process_step <= 50* ( (float) (addrOffset)/(memsize)) ){ if(process_step!=show_process_step){ printk("\n memAddressLinesTestrocess: %d%% (write)\n\n", process_step); show_process_step=process_step; } process_step+=5; } } //for(addrOffset = 1; (startAddr + addrOffset) < memsize; addrOffset<<=1) for(addrOffset = 0; (startAddr + addrOffset) < memsize; addrOffset+=0x10000) { //printk("[memAddressLinesTest] (v) addrOffset 0x%lx \n",addrOffset); cmd.forward=1; cmd.verify_pattern=gMemDLPattern[0]; cmd.write_pattern=(u64) NULL; //mem_region(cmd, addrOffset, sizeof(int)); if (mem_region(cmd, addrOffset, 0x400)) return; while (process_step <= 100* ( (float) (addrOffset)/(memsize)) ){ if(process_step!=show_process_step){ printk("\n memAddressLinesTestrocess: %d%% (verify)\n\n", process_step); show_process_step=process_step; } process_step+=5; } } } /******************************************************************************* * PROCEDURE * * NAME: memByteEnableTest * SUMMARY: This procedure will perform byte enable test on sdram * SCOPE: public * * DESCRIPTION: This test initialize two QWord memory space with the pre-defined pattern * and change the content byte by byte and verify the content of memory * * RETURNS: * * NOTES: * */ void memByteEnableTest(u64 startAddr) { int idx; u64* pRegionBase; u64* pRegionTest; u64 value; u64 value_mask; int process_step=0; int show_process_step=0; mdc cmd; cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_BYTEENABLE; M_INIT_TEST_BASE(startAddr); pRegionBase = (u64 *)ioremap(startAddr, (sizeof(gMemDWPattern)*2)); printk("[START] memByteEnableTest process \n"); for(idx=0; idx < (sizeof(gMemDWPattern)/sizeof(u64)); idx++) { pRegionTest=pRegionBase+idx; *pRegionTest=gMemDWPattern[idx]; value=*pRegionTest; pRegionTest=pRegionBase+sizeof(gMemDWPattern)+idx; *pRegionTest=0xFFFFFFFFFFFFFFFFull; value_mask=*pRegionTest; if ( (value & value_mask) != gMemDWPattern[idx] ){ //printk("\n[FAIL] memByteEnableTest \n"); errorReport(cmd, "memByteEnableTest failed"); return; }else{ printk("\nmemByteEnableTest pattern %Lx\n", gMemDWPattern[idx]); } while (process_step <= 100* ( (float) (idx+1)/((sizeof(gMemDWPattern)/sizeof(u64)))) ){ if(process_step!=show_process_step){ printk("\r memByteEnableTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } } printk("\n[END] memByteEnableTest process \n"); } /******************************************************************************* * PROCEDURE * * NAME: memMarchCTest * SUMMARY: This procedure will perform the MarchC test on sdram * SCOPE: public * * DESCRIPTION: This test will wrire and verify memory in reverse order * * RETURNS: * * NOTES: * */ void memMarchCTest(u64 startAddr, u64 sizeTest, int loopTest) { int idxLoop; mdc cmd; int process_step=0; int show_process_step=0; cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_MARCHC; M_INIT_TEST_BASE(startAddr); M_INIT_TEST_REGION(startAddr, sizeTest); printk(" startAddr %Lx, sizeTest %Lx \n", startAddr, sizeTest); for(idxLoop=0; idxLoop < loopTest; idxLoop++) { cmd.forward=1; cmd.verify_pattern=(u64) NULL; cmd.write_pattern=~gMemDWPattern[idxLoop]; if (mem_region(cmd, startAddr, sizeTest)) return; while (process_step <= 25* ( (float) (idxLoop+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memMarchCTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } //The 1st march will forward go through whole memory cmd.forward=1; cmd.verify_pattern=~gMemDWPattern[idxLoop]; cmd.write_pattern=gMemDWPattern[idxLoop]; if (mem_region(cmd, startAddr, sizeTest)) return; while (process_step <= 50* ( (float) (idxLoop+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memMarchCTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } //The 2nd march will forward go through whole memory cmd.forward=-1; cmd.verify_pattern=gMemDWPattern[idxLoop]; cmd.write_pattern=~gMemDWPattern[idxLoop]; if (mem_region(cmd, startAddr, sizeTest)) return; while (process_step <= 75* ( (float) (idxLoop+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memMarchCTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } // //The 3rd march will backward go through whole memory // cmd.forward=-1; // cmd.verify_pattern=~gMemDWPattern[idxLoop]; // cmd.write_pattern=gMemDWPattern[idxLoop]; // mem_region(cmd, startAddr, sizeTest); // // //The 4th march will backward go through whole memory // cmd.forward=-1; // cmd.verify_pattern=gMemDWPattern[idxLoop]; // cmd.write_pattern=~gMemDWPattern[idxLoop]; // mem_region(cmd, startAddr, sizeTest); //The 5th mach will forward go through whole memory to verify the last written pattern cmd.forward=-1; cmd.verify_pattern=~gMemDWPattern[idxLoop]; cmd.write_pattern=0; if (mem_region(cmd, startAddr, sizeTest)) return; while (process_step <= 100* ( (float) (idxLoop+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memMarchCTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } } printk("\n"); } /******************************************************************************* * PROCEDURE * * NAME: memWordPatternsTest * SUMMARY: This procedure will perform the Work patterns test on sdram * SCOPE: public * * DESCRIPTION: This test will write different pattern to memory and verify * * RETURNS: * * NOTES: * */ void memWordPatternsTest(u64 startAddr, u64 sizeTest, int loopTest) { int process_step=0; int show_process_step=0; int idx; mdc cmd; M_INIT_TEST_BASE(startAddr); M_INIT_TEST_REGION(startAddr, sizeTest); cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_EXTENDPATTERNS; if ( (loopTest > sizeof(gMemDWPattern)/sizeof(u64) ) | (loopTest == 0)) loopTest = sizeof(gMemDWPattern)/sizeof(u64); printk("\n"); for(idx=0 ; idx < (loopTest+1) ;idx++) { printk("\n\n ============ %d ============ \n\n",idx); cmd.forward=1; if (idx==0) { cmd.verify_pattern=(u64) NULL; }else{ cmd.verify_pattern=gMemDWPattern[idx-1]; } if ( idx == (loopTest+1) ) { cmd.write_pattern=(u64) NULL; }else{ cmd.write_pattern=gMemDWPattern[idx]; printk("\n\n Pattern no.%u = 0x%Lx \n\n",idx+1,gMemDWPattern[idx]); } //mem_region(cmd, startAddr, sizeTest); if (mem_region(cmd, startAddr, 1024)) return; if (loopTest >1) { while (process_step <= 100* ( (float) (idx+1)/(loopTest+1) ) ){ if(process_step!=show_process_step){ printk("\r memWordPatternsTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } } } printk("\n"); } /******************************************************************************* * PROCEDURE * * NAME: memPRandPatternsTest * SUMMARY: This procedure will perform the pseudo random test on sdram * SCOPE: public * * DESCRIPTION: This test will use the pattern generated by pseudo random generator and verify * * RETURNS: * * NOTES: * */ void memPRandPatternsTest(u64 startAddr, u64 sizeTest, int loopTest) { int process_step=0; int show_process_step=0; int idx; u64 val; mdc cmd; M_INIT_TEST_BASE(startAddr); M_INIT_TEST_REGION(startAddr, sizeTest); cmd=init_MemDiagCmd(); cmd.error_item=MEM_DIAG_ITEM_CODE_PSEUDORANDOMPATTERNS; printk("\n"); for(idx=0 ; idx < loopTest ;idx++) { get_random_bytes(&val, sizeof(val)); cmd.forward=1; cmd.verify_pattern=(u64) NULL; cmd.write_pattern=val; if(mem_region(cmd, startAddr, sizeTest)) return; if (loopTest >1) { while (process_step <= 50* ( (float) (idx+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memPRandPatternsTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } } cmd.forward=1; cmd.verify_pattern=val; cmd.write_pattern=(u64) NULL; if(mem_region(cmd, startAddr, sizeTest)) return; if (loopTest >1) { while (process_step <= 100* ( (float) (idx+1)/loopTest ) ){ if(process_step!=show_process_step){ printk("\r memPRandPatternsTest process: %d%%", process_step); show_process_step=process_step; } process_step+=5; } } } printk("\n"); }