memtester support in kernel
authoryangkai <yangkai@ubuntu-fs>
Wed, 23 Mar 2011 11:22:35 +0000 (19:22 +0800)
committeryangkai <yangkai@ubuntu-fs>
Wed, 23 Mar 2011 11:22:35 +0000 (19:22 +0800)
arch/arm/mach-rk29/Makefile
arch/arm/mach-rk29/ddr.c
arch/arm/mach-rk29/include/mach/memtester.h [new file with mode: 0755]
arch/arm/mach-rk29/memtester.c [new file with mode: 0755]
arch/arm/mach-rk29/pm.c
arch/arm/mach-rk29/tests.c [new file with mode: 0755]
arch/arm/mach-rk29/tests.h [new file with mode: 0755]

index 06ad98791727a1718d30a3d84315c38f286fb116..850b23200a258c1466cc07a1be32b01154e88399 100644 (file)
@@ -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
index 2653fb07e6c16dad612eda04f039c41821e31159..0e96f042e7eda31c18b4802293eade51bf98c6af 100755 (executable)
@@ -34,7 +34,7 @@
 
 #include <asm/io.h>
 
-#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 (executable)
index 0000000..098ad96
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Very simple (yet, for some reason, very effective) memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2007-2009 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * 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 (executable)
index 0000000..9e02f28
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * memtester version 4
+ *
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2007-2009 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Licensed under the terms of the GNU General Public License version 2 (only).
+ * See the file COPYING for details.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#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;
+}
index 84c5b9866fb424092162a87511281e5d793988d2..22b71fde4c38377b0f4672b5aec901f5e3f0159e 100755 (executable)
@@ -25,6 +25,7 @@
 #include <mach/sram.h>
 #include <mach/gpio.h>
 #include <mach/ddr.h>
+#include <mach/memtester.h>
 
 #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 (executable)
index 0000000..a2995d3
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2007-2009 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * 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 (executable)
index 0000000..46a5233
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Very simple yet very effective memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2007-2009 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * 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 <linux/kernel.h>
+#include <mach/rk29_iomap.h>
+
+#include <linux/random.h>
+
+//#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);
+