From 1497220f4feae9feae37fea23cd01ddabe8d2d49 Mon Sep 17 00:00:00 2001 From: yangkai Date: Wed, 23 Mar 2011 19:22:35 +0800 Subject: [PATCH] memtester support in kernel --- arch/arm/mach-rk29/Makefile | 1 + arch/arm/mach-rk29/ddr.c | 14 +- arch/arm/mach-rk29/include/mach/memtester.h | 19 + arch/arm/mach-rk29/memtester.c | 177 +++++++ arch/arm/mach-rk29/pm.c | 65 ++- arch/arm/mach-rk29/tests.c | 515 ++++++++++++++++++++ arch/arm/mach-rk29/tests.h | 195 ++++++++ 7 files changed, 974 insertions(+), 12 deletions(-) create mode 100755 arch/arm/mach-rk29/include/mach/memtester.h create mode 100755 arch/arm/mach-rk29/memtester.c create mode 100755 arch/arm/mach-rk29/tests.c create mode 100755 arch/arm/mach-rk29/tests.h diff --git a/arch/arm/mach-rk29/Makefile b/arch/arm/mach-rk29/Makefile index 06ad98791727..850b23200a25 100644 --- a/arch/arm/mach-rk29/Makefile +++ b/arch/arm/mach-rk29/Makefile @@ -1,4 +1,5 @@ obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o ddr.o sram.o memcpy_dma.o reset.o +obj-y += tests.o memtester.o obj-y += early_printk.o ifndef CONFIG_DEBUG_LL obj-y += ../kernel/debug.o diff --git a/arch/arm/mach-rk29/ddr.c b/arch/arm/mach-rk29/ddr.c index 2653fb07e6c1..0e96f042e7ed 100755 --- a/arch/arm/mach-rk29/ddr.c +++ b/arch/arm/mach-rk29/ddr.c @@ -34,7 +34,7 @@ #include -#define ddr_print(x...) printk( "ddr init: " x ) +#define ddr_print(x...) printk( "DDR DEBUG: " x ) // save_sp must be static global variable @@ -1006,7 +1006,7 @@ refresh: pDDR_Reg->CCR |= HOSTEN; //enable host port } -void __sramfunc ddr_change_freq(uint32_t nMHz) +uint32_t __sramfunc ddr_change_freq(uint32_t nMHz) { uint32_t ret; volatile u32 n; @@ -1057,6 +1057,7 @@ void __sramfunc ddr_change_freq(uint32_t nMHz) DDR_RESTORE_SP(save_sp); local_irq_restore(flags); + return ret; //ddr_print("%s exit\n", __func__); } void __sramfunc ddr_suspend(void) @@ -1213,7 +1214,7 @@ static int __init ddr_probe(void) if((mem_type == DDRII) || (mem_type == DDR3)) { - pDDR_Reg->ALPMR = LPPERIOD_POWER_DOWN(0xFF);// | AUTOPD; + pDDR_Reg->ALPMR = LPPERIOD_POWER_DOWN(0xFF) | AUTOPD; } else { @@ -1226,9 +1227,8 @@ static int __init ddr_probe(void) Hz = clk_get_rate(clk_get(NULL,"ddr")); MHz = Hz/1000000; - ddr_change_freq(MHz); - ddr_print("ddr pll freq=%dMHz\n", MHz); - - return 0; + value = ddr_change_freq(MHz); + ddr_print("init success!!! freq=%dMHz\n", value); + return 0; } core_initcall_sync(ddr_probe); diff --git a/arch/arm/mach-rk29/include/mach/memtester.h b/arch/arm/mach-rk29/include/mach/memtester.h new file mode 100755 index 000000000000..098ad9622c07 --- /dev/null +++ b/arch/arm/mach-rk29/include/mach/memtester.h @@ -0,0 +1,19 @@ +/* + * Very simple (yet, for some reason, very effective) memory tester. + * Originally by Simon Kirby + * Version 2 by Charles Cazabon + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2007-2009 Charles Cazabon + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the declarations for external variables from the main file. + * See other comments in that file. + * + */ + + +/* extern declarations. */ + +extern void memtester(void); \ No newline at end of file diff --git a/arch/arm/mach-rk29/memtester.c b/arch/arm/mach-rk29/memtester.c new file mode 100755 index 000000000000..9e02f284cedf --- /dev/null +++ b/arch/arm/mach-rk29/memtester.c @@ -0,0 +1,177 @@ +/* + * memtester version 4 + * + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby + * Version 2 by Charles Cazabon + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2007-2009 Charles Cazabon + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + */ + + +#include +#include + +#include "tests.h" + + +#define EXIT_FAIL_NONSTARTER 0x01 +#define EXIT_FAIL_ADDRESSLINES 0x02 +#define EXIT_FAIL_OTHERTEST 0x04 + +//#pragma arm section rwdata="DDR" +useful_data_t useful_data={(2*1024*1024), 133, 333}; +//#pragma arm section + +struct test tests[17] += { + #ifdef TEST_RANDOM + { "Random Value", test_random_value }, + #endif + #ifdef TEST_XOR + { "Compare XOR", test_xor_comparison }, + #endif + #ifdef TEST_SUB + { "Compare SUB", test_sub_comparison }, + #endif + #ifdef TEST_MUL + { "Compare MUL", test_mul_comparison }, + #endif + #ifdef TEST_DIV + { "Compare DIV",test_div_comparison }, + #endif + #ifdef TEST_OR + { "Compare OR", test_or_comparison }, + #endif + #ifdef TEST_AND + { "Compare AND", test_and_comparison }, + #endif + #ifdef TEST_SEQINC + { "Sequential Increment", test_seqinc_comparison }, + #endif + #ifdef TEST_SOLID_BIT + { "Solid Bits", test_solidbits_comparison }, + #endif + #ifdef TEST_BLOCK_SEQ + { "Block Sequential", test_blockseq_comparison }, + #endif + #ifdef TEST_CHECK_BOARD + { "Checkerboard", test_checkerboard_comparison }, + #endif + #ifdef TEST_BIT_SPREAD + { "Bit Spread", test_bitspread_comparison }, + #endif + #ifdef TEST_BIT_FLIP + { "Bit Flip", test_bitflip_comparison }, + #endif + #ifdef TEST_ONE + { "Walking Ones", test_walkbits1_comparison }, + #endif + #ifdef TEST_ZERO + { "Walking Zeroes", test_walkbits0_comparison }, + #endif + { NULL, NULL } +}; + +int exit_code = 0; + +int memtester(void) { + ul loops, loop, i; + size_t pagesize, wantraw, wantmb, wantbytes, wantbytes_orig, bufsize, + halflen, count; + ptrdiff_t pagesizemask; + void volatile *buf, *aligned; + ulv *bufa, *bufb; + int memshift; + ul cap; + + + + print("Copyright (C) 2009 Charles Cazabon.\n"); + print("Licensed under the GNU General Public License version 2 (only).\n"); + print("\n"); + pagesize = 1024; + pagesizemask = (ptrdiff_t) ~(pagesize - 1); + print("pagesizemask is 0x"); + print_Hex(pagesizemask); + print("\n"); + + if(useful_data.testCap == 0xFFFFFFFF) + { + cap = 0x800000 << (((pDDR_Reg->DCR >> 4) & 0x7) + + ((((pDDR_Reg->DCR >> 7) & 0x7)+1) >> ((pDDR_Reg->DCR >> 2) & 0x3)) + + ((pDDR_Reg->DCR >> 11) & 0x3)); + } + else if(useful_data.testCap == 0) + { + cap = (0x1 << 20); + } + else + { + cap = useful_data.testCap; + } + + wantraw = cap>>20; + memshift = 20; /* megabytes */ + + wantbytes_orig = wantbytes = ((size_t) wantraw << memshift); + wantmb = (wantbytes_orig >> 20); + + loops = 10; + + print("want "); + print_Dec((ull) wantmb); + print("MB ("); + print_Dec((ull) wantbytes); + print(" bytes)\n"); + buf = NULL; + + buf = (void volatile *) kmalloc(wantbytes, GFP_KERNEL); + // buf = (void volatile *)0x60000000; + bufsize = wantbytes; + aligned = buf; + + halflen = bufsize / 2; + count = halflen / sizeof(ul); + bufa = (ulv *) aligned; + bufb = (ulv *) ((size_t) aligned + halflen); + + for(loop=1; ((!loops) || loop <= loops); loop++) { + print("Loop "); + print_Dec(loop); + //if (loops) { + // print_Dec(loops); + //} + print(":\n"); + print(" Stuck Address: "); + if (!test_stuck_address(aligned, bufsize / sizeof(ul))) { + print("ok\n"); + } else { + exit_code |= EXIT_FAIL_ADDRESSLINES; + goto error; + } + for (i=0;;i++) { + if (!tests[i].name) break; + print(" "); + print(tests[i].name); + print(": "); + if (!tests[i].fp(bufa, bufb, count)) { + print("ok\n"); + } else { + exit_code |= EXIT_FAIL_OTHERTEST; + goto error; + } + } + print("\n"); + } + kfree((const void *)buf); + print("Done.\n"); + return 0; +error: + print("failed\n"); + return 1; +} diff --git a/arch/arm/mach-rk29/pm.c b/arch/arm/mach-rk29/pm.c index 84c5b9866fb4..22b71fde4c38 100755 --- a/arch/arm/mach-rk29/pm.c +++ b/arch/arm/mach-rk29/pm.c @@ -25,6 +25,7 @@ #include #include #include +#include #define cru_readl(offset) readl(RK29_CRU_BASE + offset) #define cru_writel(v, offset) do { writel(v, RK29_CRU_BASE + offset); readl(RK29_CRU_BASE + offset); } while (0) @@ -71,14 +72,60 @@ static void/* inline*/ __sramfunc printch(char byte) printch('\r'); } -static void inline printascii(const char *s) +static void __sramfunc printascii(const char *s) { while (*s) { - printch(*s); - s++; + if (*s == '\n') + { + printch('\r'); + } + printch(*s); + s++; + } +} +void print(const char *s) +{ + printascii(s); +} + +void __sramfunc print_Hex(unsigned int hex) +{ + int i = 8; + printch('0'); + printch('x'); + while (i--) { + unsigned char c = (hex & 0xF0000000) >> 28; + printch(c < 0xa ? c + '0' : c - 0xa + 'a'); + hex <<= 4; } } +void __sramfunc print_Dec (uint32_t n) +{ + if (n >= 10) + { + print_Dec(n / 10); + n %= 10; + } + printch((char)(n + '0')); +} + +void print_Dec_3(uint32_t value) +{ + if(value<10) + { + print(" "); + } + else if(value<100) + { + print(" "); + } + else + { + } + print_Dec(value); +} + static void /* inline*/ __sramfunc printhex(unsigned int hex) { int i = 8; @@ -209,7 +256,10 @@ void __sramfunc ddr_testmode(void) // printascii("self refresh success\n"); } } - + else if(ddr_debug == 3) + { + memtester(); + } } #else void __sramfunc ddr_testmode(void) @@ -220,7 +270,7 @@ static void __sramfunc rk29_sram_suspend(void) { u32 clksel0; - if(ddr_debug) + if((ddr_debug == 1)||(ddr_debug == 2)) ddr_testmode(); printch('5'); ddr_suspend(); @@ -285,6 +335,11 @@ static int rk29_pm_enter(suspend_state_t state) { u32 apll, cpll, gpll, mode, clksel0; u32 clkgate[4]; + + // memory teseter + if(ddr_debug == 3) + ddr_testmode(); + printch('0'); #ifdef CONFIG_RK29_PWM_REGULATOR diff --git a/arch/arm/mach-rk29/tests.c b/arch/arm/mach-rk29/tests.c new file mode 100755 index 000000000000..a2995d3c917e --- /dev/null +++ b/arch/arm/mach-rk29/tests.c @@ -0,0 +1,515 @@ +/* + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby + * Version 2 by Charles Cazabon + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2007-2009 Charles Cazabon + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the functions for the actual tests, called from the + * main routine in memtester.c. See other comments in that file. + * + */ + +#include "tests.h" + +char progress[] = "-\\|/"; +#define PROGRESSLEN 4 +#define PROGRESSOFTEN 2500 + +int compare_regions(ulv *bufa, ulv *bufb, size_t count) { + int r = 0; + size_t i; + ulv *p1 = bufa; + ulv *p2 = bufb; + int n=0; + + for (i = 0; i < count; i++, p1++, p2++) { + if (*p1 != *p2) { + { + print("FAILURE: 0x"); + print_Hex((ul) *p1); + print(" != 0x"); + print_Hex((ul) *p2); + print(" at offset 0x"); + print_Hex((ul) i); + print(".\n"); + } + /* printf("Skipping to next test..."); */ + r = -1; + n++; + if(n>10) + { + break; + } + } + } + return r; +} + +int compare_regions_reverse(ulv *bufa, ulv *bufb, size_t count) { + int r = 0; + size_t i; + ulv *p1 = bufa; + ulv *p2 = bufb; + int n=0; + + for (i = 0; i < count; i++, p1++, p2++) { + if (*p1 != ~(*p2)) { + { + print("FAILURE: 0x"); + print_Hex((ul) *p1); + print(" != 0x"); + print_Hex((ul) *p2); + print(" at offset 0x"); + print_Hex((ul) i); + print(".\n"); + } + /* printf("Skipping to next test..."); */ + r = -1; + n++; + if(n>10) + { + break; + } + } + } + return r; +} + +int test_stuck_address(ulv *bufa, size_t count) { + ulv *p1 = bufa; + unsigned int j; + size_t i; + + print(" "); + for (j = 0; j < 16; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + print("setting "); + print_Dec_3(j); + for (i = 0; i < count; i++) { + *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1); + *p1++; + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + p1 = (ulv *) bufa; + for (i = 0; i < count; i++, p1++) { + if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) { + { + print("FAILURE: possible bad address line at offset 0x"); + print_Hex((ul) i); + print(".\n"); + } + print("Skipping to next test...\n"); + return -1; + } + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +#ifdef TEST_RANDOM +int test_random_value(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + + for (i = 0; i < count; i++) { + *p1++ = *p2++ = rand_ul(); + if (!(i % PROGRESSOFTEN)) { + } + } + print("\b \b"); + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_XOR +int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ ^= q; + *p2++ ^= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_SUB +int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ -= q; + *p2++ -= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_MUL +int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ *= q; + *p2++ *= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_DIV +int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + if (!q) { + q++; + } + *p1++ /= q; + *p2++ /= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_OR +int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ |= q; + *p2++ |= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_AND +int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ &= q; + *p2++ &= q; + } + return compare_regions(bufa, bufb, count); +} +#endif + +#ifdef TEST_SEQINC +int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + ul value; + + for (i = 0; i < count; i++) { + value = (i+q); + *p1++ = value; + *p2++ = ~value; + //*p1++ = *p2++ = (i + q); + } + return compare_regions_reverse(bufa, bufb, count); +} +#endif + +#ifdef TEST_SOLID_BIT +int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + ul value; + + print(" "); + for (j = 0; j < 64; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? UL_ONEBITS : 0; + print("setting "); + print_Dec_3(j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + value = (i % 2) == 0 ? q : ~q; + *p1++ = value; + *p2++ = ~value; + //*p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_CHECK_BOARD +int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + ul value; + + print(" "); + for (j = 0; j < 64; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; + print("setting "); + print_Dec_3(j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + value = (i % 2) == 0 ? q : ~q; + *p1++ = value; + *p2++ = ~value; + //*p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_BLOCK_SEQ +int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + ul value; + + print(" "); + for (j = 0; j < 256; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + print("setting "); + print_Dec_3(j); + for (i = 0; i < count; i++) { + value = (ul) UL_BYTE(j); + *p1++ = value; + *p2++ = ~value; + //*p1++ = *p2++ = (ul) UL_BYTE(j); + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_ZERO +int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + ul value; + + print(" "); + for (j = 0; j < UL_LEN * 2; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + print("setting "); + print_Dec_3(j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + //*p1++ = *p2++ = 0x00000001 << j; + value = 0x00000001 << j; + *p1++ = value; + *p2++ = ~value; + } else { /* Walk it back down. */ + //*p1++ = *p2++ = 0x00000001 << (UL_LEN * 2 - j - 1); + value = 0x00000001 << (UL_LEN * 2 - j - 1); + *p1++ = value; + *p2++ = ~value; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_ONE +int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + ul value; + + print(" "); + for (j = 0; j < UL_LEN * 2; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + print("setting "); + print_Dec_3(j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + //*p1++ = *p2++ = UL_ONEBITS ^ (0x00000001 << j); + value = UL_ONEBITS ^ (0x00000001 << j); + *p1++ = value; + *p2++ = ~value; + } else { /* Walk it back down. */ + //*p1++ = *p2++ = UL_ONEBITS ^ (0x00000001 << (UL_LEN * 2 - j - 1)); + value = UL_ONEBITS ^ (0x00000001 << (UL_LEN * 2 - j - 1)); + *p1++ = value; + *p2++ = ~value; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_BIT_SPREAD +int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + ul value; + + print(" "); + for (j = 0; j < UL_LEN * 2; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + print("setting "); + print_Dec_3(j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + //*p1++ = *p2++ = (i % 2 == 0) + // ? (0x00000001 << j) | (0x00000001 << (j + 2)) + // : UL_ONEBITS ^ ((0x00000001 << j) + // | (0x00000001 << (j + 2))); + value = (i % 2 == 0) + ? (0x00000001 << j) | (0x00000001 << (j + 2)) + : UL_ONEBITS ^ ((0x00000001 << j) + | (0x00000001 << (j + 2))); + *p1++ = value; + *p2++ = ~value; + } else { /* Walk it back down. */ + //*p1++ = *p2++ = (i % 2 == 0) + // ? (0x00000001 << (UL_LEN * 2 - 1 - j)) | (0x00000001 << (UL_LEN * 2 + 1 - j)) + // : UL_ONEBITS ^ (0x00000001 << (UL_LEN * 2 - 1 - j) + // | (0x00000001 << (UL_LEN * 2 + 1 - j))); + value = (i % 2 == 0) + ? (0x00000001 << (UL_LEN * 2 - 1 - j)) | (0x00000001 << (UL_LEN * 2 + 1 - j)) + : UL_ONEBITS ^ (0x00000001 << (UL_LEN * 2 - 1 - j) + | (0x00000001 << (UL_LEN * 2 + 1 - j))); + *p1++ = value; + *p2++ = ~value; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif + +#ifdef TEST_BIT_FLIP +int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j, k; + ul q; + size_t i; + ul value; + + print(" "); + for (k = 0; k < UL_LEN; k++) { + q = 0x00000001 << k; + for (j = 0; j < 8; j++) { + print("\b\b\b\b\b\b\b\b\b\b\b"); + q = ~q; + print("setting "); + print_Dec_3(k * 8 + j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + //*p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + value = (i % 2) == 0 ? q : ~q; + *p1++ = value; + *p2++ = ~value; + } + print("\b\b\b\b\b\b\b\b\b\b\b"); + print("testing "); + print_Dec_3(k * 8 + j); + if (compare_regions_reverse(bufa, bufb, count)) { + return -1; + } + } + } + print("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} +#endif diff --git a/arch/arm/mach-rk29/tests.h b/arch/arm/mach-rk29/tests.h new file mode 100755 index 000000000000..46a523386388 --- /dev/null +++ b/arch/arm/mach-rk29/tests.h @@ -0,0 +1,195 @@ +/* + * Very simple yet very effective memory tester. + * Originally by Simon Kirby + * Version 2 by Charles Cazabon + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2007-2009 Charles Cazabon + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the declarations for the functions for the actual tests, + * called from the main routine in memtester.c. See other comments in that + * file. + * + */ + +#include +#include + +#include + +//#if (ULONG_MAX == 4294967295UL) +#if 1 + #define rand_ul() random32() + #define UL_ONEBITS 0xffffffff + #define UL_LEN 32 + #define CHECKERBOARD1 0x55555555 + #define CHECKERBOARD2 0xaaaaaaaa + #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24)) +#elif (ULONG_MAX == 18446744073709551615ULL) + #define rand64() (((ul) rand32()) << 32 | ((ul) rand32())) + #define rand_ul() rand64() + #define UL_ONEBITS 0xffffffffffffffffUL + #define UL_LEN 64 + #define CHECKERBOARD1 0x5555555555555555 + #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa + #define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56)) +#else + #error long on this platform is not 32 or 64 bits +#endif + +#define TEST_ALL + +#ifdef TEST_ALL // TEST_ALLµÄʱºòÕâЩ¶¼²»¶¯ +#define TEST_RANDOM +#define TEST_XOR +#define TEST_SUB +#define TEST_MUL +#define TEST_DIV +#define TEST_OR +#define TEST_AND +#define TEST_SEQINC +#define TEST_SOLID_BIT +#define TEST_BLOCK_SEQ +#define TEST_CHECK_BOARD +#define TEST_BIT_SPREAD +#define TEST_BIT_FLIP +#define TEST_ONE +#define TEST_ZERO +#else //ÕâЩÅäÖÃÓÃÓÚÔöɾ +//#define TEST_RANDOM +//#define TEST_XOR +//#define TEST_SUB +//#define TEST_MUL +//#define TEST_DIV +//#define TEST_OR +//#define TEST_AND +//#define TEST_SEQINC +//#define TEST_SOLID_BIT +//#define TEST_BLOCK_SEQ +//#define TEST_CHECK_BOARD +//#define TEST_BIT_SPREAD +#define TEST_BIT_FLIP +//#define TEST_ONE +//#define TEST_ZERO +#endif + + +typedef unsigned long ul; +typedef unsigned long long ull; +typedef unsigned long volatile ulv; +/* DDR Controller register struct */ +typedef volatile struct DDR_REG_Tag +{ + volatile unsigned int CCR; //Controller Configuration Register + volatile unsigned int DCR; //DRAM Configuration Register + volatile unsigned int IOCR; //IO Configuration Register + volatile unsigned int CSR; //Controller Status Register + volatile unsigned int DRR; //DRAM Refresh Register + volatile unsigned int TPR[3]; //SDRAM Timing Parameters Registers + volatile unsigned int DLLCR; //Global DLL Control Register + volatile unsigned int DLLCR09[10]; //DDR Control Register 0-9 + volatile unsigned int RSLR[4]; //Rank System Latency Register 0-3 + volatile unsigned int RDGR[4]; //Rank DQS Gating Register 0-3 + volatile unsigned int DQTR[9]; //DQ Timing Register 0-8 + volatile unsigned int DQSTR; //DQS Timing Register + volatile unsigned int DQSBTR; //DQS_b Timing Register + volatile unsigned int ODTCR; //ODT Configuration Register + volatile unsigned int DTR[2]; //Data Training Register 0-1 + volatile unsigned int DTAR; //Data Training Address Register + volatile unsigned int ZQCR[3]; //SDRAM ZQ Control Register and SDRAM ZQCS Control Register 0-2 + volatile unsigned int ZQSR; //SDRAM ZQ Status Register + volatile unsigned int TPR3; //SDRAM Timing Parameters Register 3 + volatile unsigned int ALPMR; //Automatic Low Power Mode Register + volatile unsigned int Reserved[0x7c-0x30]; + volatile unsigned int MR; //Mode Register + volatile unsigned int EMR; //Extended Mode Register + volatile unsigned int EMR2; //Extended Mode Register 2 + volatile unsigned int EMR3; //Extended Mode Register 3 + //Memory Management Unit Registers + volatile unsigned int HPCR[32]; //Host Port Configuration Register 0-31 + volatile unsigned int PQCR[8]; //Priority Queue Configuration Register 0-7 + volatile unsigned int MMGCR; //Memory Manager General Configuration Register +}DDR_REG_T, *pDDR_REG_T; + +typedef struct tagGPIO_IOMUX +{ + volatile unsigned int GPIOL_IOMUX; + volatile unsigned int GPIOH_IOMUX; +}GPIO_IOMUX_T; + +//GRF Registers +typedef volatile struct tagREG_FILE +{ + volatile unsigned int GRF_GPIO_DIR[6]; + volatile unsigned int GRF_GPIO_DO[6]; + volatile unsigned int GRF_GPIO_EN[6]; + GPIO_IOMUX_T GRF_GPIO_IOMUX[6]; + volatile unsigned int GRF_GPIO_PULL[7]; + volatile unsigned int GRF_UOC_CON[2]; + volatile unsigned int GRF_USB_CON; + volatile unsigned int GRF_CPU_CON[2]; + volatile unsigned int GRF_CPU_STATUS; + volatile unsigned int GRF_MEM_CON; + volatile unsigned int GRF_MEM_STATUS[3]; + volatile unsigned int GRF_SOC_CON[5]; + volatile unsigned int GRF_OS_REG[4]; +} REG_FILE, *pREG_FILE; + +//CRU Registers +typedef volatile struct tagCRU_REG +{ + volatile unsigned int CRU_APLL_CON; + volatile unsigned int CRU_DPLL_CON; + volatile unsigned int CRU_CPLL_CON; + volatile unsigned int CRU_PPLL_CON; + volatile unsigned int CRU_MODE_CON; + volatile unsigned int CRU_CLKSEL_CON[18]; + volatile unsigned int CRU_CLKGATE_CON[4]; + volatile unsigned int CRU_SOFTRST_CON[3]; +} CRU_REG, *pCRU_REG; + +#define pDDR_Reg ((pDDR_REG_T)RK29_DDRC_BASE) +#define pGRF_Reg ((pREG_FILE)RK29_GRF_BASE) +#define pSCU_Reg ((pCRU_REG)RK29_CRU_BASE) + +struct test +{ + char *name; + int (*fp)(ulv *bufa, ulv *bufb, size_t count); +}; + +typedef struct useful_data_tag +{ + unsigned int testCap; //²âÊÔµÄÈÝÁ¿ + unsigned int WriteFreq; + unsigned int ReadFreq; +}useful_data_t; +extern void printascii(const char *s); +extern void print_Dec(unsigned int n); +extern void print_Hex(unsigned int hex); +extern void print(const char *s); +extern void print_Dec_3(unsigned int value); + + +/* Function declaration. */ + +int test_stuck_address(unsigned long volatile *bufa, size_t count); +int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_simple_comparison(ulv *bufa, ulv *bufb, size_t count); + -- 2.34.1