1 /* 2 * This program is distributed in the hope that it will be useful, 3 * but WITHOUT ANY WARRANTY; without even the implied warranty of 4 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 5 * GNU General Public License for more details. 6 * 7 * You should have received a copy of the GNU General Public License 8 * along with this program; if not, write to the Free Software 9 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 10 */ 11 12 #include <common.h> 13 #include <console.h> 14 #include <bootretry.h> 15 #include <cli.h> 16 #include <command.h> 17 #include <console.h> 18 19 #include <inttypes.h> 20 #include <mapmem.h> 21 #include <asm/io.h> 22 #include <linux/compiler.h> 23 24 DECLARE_GLOBAL_DATA_PTR; 25 26 #define DRAM_BASE 0x80000000 27 #define TIMEOUT_DRAM 5000000 28 29 #ifdef CONFIG_ASPEED_AST2600 30 #define BLK_SIZE_MB 64 31 #define N_BLK 32 32 #define MCR74_BLK_OFFSET 26 33 #define MCR74_LEN_OFFSET 4 34 #define MCR74_BLK_LEN_MASK GENMASK(30, 4) 35 #else 36 #define BLK_SIZE_MB 16 37 #define N_BLK 64 38 #define MCR74_BLK_OFFSET 24 39 #define MCR74_LEN_OFFSET 4 40 #define MCR74_BLK_LEN_MASK GENMASK(29, 4) 41 #endif 42 #define BLK_SIZE (BLK_SIZE_MB * 1024 * 1024) 43 #define N_16B_IN_BLK (BLK_SIZE / 16) 44 45 /* ------------------------------------------------------------------------- */ 46 int MMCTestBurst(unsigned int datagen) 47 { 48 unsigned int data; 49 unsigned int timeout = 0; 50 51 writel(0x00000000, 0x1E6E0070); 52 writel((0x000000C1 | (datagen << 3)), 0x1E6E0070); 53 54 do { 55 data = readl(0x1E6E0070) & 0x3000; 56 57 if( data & 0x2000 ) 58 return(0); 59 60 if( ++timeout > TIMEOUT_DRAM ) { 61 printf("Timeout!!\n"); 62 writel(0x00000000, 0x1E6E0070); 63 return(0); 64 } 65 } while (!data); 66 67 writel(0x00000000, 0x1E6E0070); 68 69 return(1); 70 } 71 72 /* ------------------------------------------------------------------------- */ 73 int MMCTestSingle(unsigned int datagen) 74 { 75 unsigned int data; 76 unsigned int timeout = 0; 77 78 writel(0x00000000, 0x1E6E0070); 79 writel((0x00000085 | (datagen << 3)), 0x1E6E0070); 80 81 do { 82 data = readl(0x1E6E0070) & 0x3000; 83 84 if( data & 0x2000 ) 85 return(0); 86 87 if( ++timeout > TIMEOUT_DRAM ){ 88 printf("Timeout!!\n"); 89 writel(0x00000000, 0x1E6E0070); 90 91 return(0); 92 } 93 } while ( !data ); 94 95 writel(0x00000000, 0x1E6E0070); 96 97 return(1); 98 } 99 100 /* ------------------------------------------------------------------------- */ 101 int MMCTest(void) 102 { 103 unsigned int pattern; 104 105 pattern = rand(); 106 writel(pattern, 0x1E6E007C); 107 printf("Pattern = %08X : ",pattern); 108 109 if(!MMCTestBurst(0)) return(0); 110 if(!MMCTestBurst(1)) return(0); 111 if(!MMCTestBurst(2)) return(0); 112 if(!MMCTestBurst(3)) return(0); 113 if(!MMCTestBurst(4)) return(0); 114 if(!MMCTestBurst(5)) return(0); 115 if(!MMCTestBurst(6)) return(0); 116 if(!MMCTestBurst(7)) return(0); 117 if(!MMCTestSingle(0)) return(0); 118 if(!MMCTestSingle(1)) return(0); 119 if(!MMCTestSingle(2)) return(0); 120 if(!MMCTestSingle(3)) return(0); 121 if(!MMCTestSingle(4)) return(0); 122 if(!MMCTestSingle(5)) return(0); 123 if(!MMCTestSingle(6)) return(0); 124 if(!MMCTestSingle(7)) return(0); 125 126 return(1); 127 } 128 129 /* ------------------------------------------------------------------------- */ 130 static void print_usage(void) 131 { 132 printf("\nASPEED DRAM BIST\n\n"); 133 printf("Usage: dramtest <count> <block> <length>\n\n"); 134 printf("count: how many iterations to run (mandatory, in decimal)\n"); 135 printf(" 0: infinite loop.\n"); 136 printf("block: index of the address block to test " 137 "(optional, in decimal, default: 0)\n"); 138 printf(" 0: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 0, DRAM_BASE + BLK_SIZE * 1); 139 printf(" 1: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 1, DRAM_BASE + BLK_SIZE * 2); 140 printf(" 2: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 2, DRAM_BASE + BLK_SIZE * 3); 141 printf(" n: [80000000 + n*%dMB, 80000000 + (n+1)*%dMB)\n", BLK_SIZE_MB, BLK_SIZE_MB); 142 printf(" where n = [0, %d]\n", N_BLK - 1); 143 printf("length: size to test (optional, in hex, default: 0x10000)\n"); 144 printf(" 0x0: test the whole memory block %dMB\n", BLK_SIZE_MB); 145 printf(" 0x1: test the first 16 Bytes of the memory block\n"); 146 printf(" 0x2: test the first 2*16 Bytes of the memory block\n"); 147 printf(" n : test the first n*16 Bytes of the memory block\n"); 148 printf(" where n = [0x00000001, 0x%08x]\n", N_16B_IN_BLK - 1); 149 printf("\n\n"); 150 } 151 152 static int 153 do_ast_dramtest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 154 { 155 u32 PassCnt = 0; 156 unsigned long Testcounter = 0; 157 unsigned long block = 0; 158 unsigned long length = 0x10000; 159 int ret; 160 161 if (argc < 2) { 162 ret = 0; 163 goto cmd_err; 164 } 165 166 ret = CMD_RET_USAGE; 167 switch (argc) { 168 case 4: 169 if (strict_strtoul(argv[3], 16, &length) < 0) 170 goto cmd_err; 171 case 3: 172 if (strict_strtoul(argv[2], 10, &block) < 0) 173 goto cmd_err; 174 case 2: 175 if (strict_strtoul(argv[1], 10, &Testcounter) < 0) 176 goto cmd_err; 177 break; 178 } 179 180 printf("Test range: 0x%08lx - 0x%08lx\n", DRAM_BASE + (block << MCR74_BLK_OFFSET), 181 DRAM_BASE + (block << MCR74_BLK_OFFSET) + (length << 4) + 15); 182 183 ret = 1; 184 writel(0xFC600309, 0x1E6E0000); 185 while ((Testcounter > PassCnt) || (Testcounter == 0)) { 186 clrsetbits_le32(0x1E6E0074, MCR74_BLK_LEN_MASK, 187 (block << MCR74_BLK_OFFSET) | (length << MCR74_LEN_OFFSET)); 188 189 if (!MMCTest()) { 190 printf("FAIL %d/%ld (fail DQ 0x%08x)\n", PassCnt, 191 Testcounter, readl(0x1E6E0078)); 192 ret = 0; 193 break; 194 } else { 195 PassCnt++; 196 printf("Pass %d/%ld\n", PassCnt, Testcounter); 197 } 198 } 199 200 return (ret); 201 202 cmd_err: 203 print_usage(); 204 return (ret); 205 } 206 207 U_BOOT_CMD( 208 dramtest, 5, 0, do_ast_dramtest, 209 "ASPEED DRAM BIST", 210 "" 211 ); 212