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 static int MMCTestBurst(u32 datagen) 46 { 47 u32 data; 48 int timeout = 0; 49 50 writel(0x00000000, 0x1e6e0070); 51 writel((0x000000c1 | (datagen << 3)), 0x1e6e0070); 52 53 do { 54 data = readl(0x1e6e0070) & 0x3000; 55 56 if (data & 0x2000) 57 return 0; 58 59 if (++timeout > TIMEOUT_DRAM) { 60 printf("Timeout!!\n"); 61 writel(0x00000000, 0x1e6e0070); 62 return 0; 63 } 64 } while (!data); 65 66 writel(0x00000000, 0x1e6e0070); 67 68 return 1; 69 } 70 71 static int MMCTestSingle(u32 datagen) 72 { 73 u32 data; 74 int timeout = 0; 75 76 writel(0x00000000, 0x1e6e0070); 77 writel((0x00000085 | (datagen << 3)), 0x1e6e0070); 78 79 do { 80 data = readl(0x1e6e0070) & 0x3000; 81 82 if (data & 0x2000) 83 return 0; 84 85 if (++timeout > TIMEOUT_DRAM) { 86 printf("Timeout!!\n"); 87 writel(0x00000000, 0x1e6e0070); 88 89 return 0; 90 } 91 } while (!data); 92 93 writel(0x00000000, 0x1e6e0070); 94 95 return 1; 96 } 97 98 static int MMCTest(void) 99 { 100 unsigned int pattern; 101 102 pattern = rand(); 103 writel(pattern, 0x1e6e007c); 104 printf("Pattern = %08X : ", pattern); 105 106 if(!MMCTestBurst(0)) return(0); 107 if(!MMCTestBurst(1)) return(0); 108 if(!MMCTestBurst(2)) return(0); 109 if(!MMCTestBurst(3)) return(0); 110 if(!MMCTestBurst(4)) return(0); 111 if(!MMCTestBurst(5)) return(0); 112 if(!MMCTestBurst(6)) return(0); 113 if(!MMCTestBurst(7)) return(0); 114 if(!MMCTestSingle(0)) return(0); 115 if(!MMCTestSingle(1)) return(0); 116 if(!MMCTestSingle(2)) return(0); 117 if(!MMCTestSingle(3)) return(0); 118 if(!MMCTestSingle(4)) return(0); 119 if(!MMCTestSingle(5)) return(0); 120 if(!MMCTestSingle(6)) return(0); 121 if(!MMCTestSingle(7)) return(0); 122 123 return 1; 124 } 125 126 static void print_usage(void) 127 { 128 printf("\nASPEED DRAM BIST\n\n"); 129 printf("Usage: dramtest <count> <block> <length>\n\n"); 130 printf("count: how many iterations to run (mandatory, in decimal)\n"); 131 printf(" 0: infinite loop.\n"); 132 printf("block: index of the address block to test " 133 "(optional, in decimal, default: 0)\n"); 134 printf(" 0: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 0, DRAM_BASE + BLK_SIZE * 1); 135 printf(" 1: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 1, DRAM_BASE + BLK_SIZE * 2); 136 printf(" 2: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 2, DRAM_BASE + BLK_SIZE * 3); 137 printf(" n: [80000000 + n*%dMB, 80000000 + (n+1)*%dMB)\n", BLK_SIZE_MB, BLK_SIZE_MB); 138 printf(" where n = [0, %d]\n", N_BLK - 1); 139 printf("length: size to test (optional, in hex, default: 0x10000)\n"); 140 printf(" 0x0: test the whole memory block %dMB\n", BLK_SIZE_MB); 141 printf(" 0x1: test the first 16 Bytes of the memory block\n"); 142 printf(" 0x2: test the first 2*16 Bytes of the memory block\n"); 143 printf(" n : test the first n*16 Bytes of the memory block\n"); 144 printf(" where n = [0x00000001, 0x%08x]\n", N_16B_IN_BLK); 145 printf("\n\n"); 146 } 147 148 static int do_ast_dramtest(cmd_tbl_t *cmdtp, int flag, int argc, 149 char *const argv[]) 150 { 151 u32 PassCnt = 0; 152 unsigned long Testcounter = 0; 153 unsigned long block = 0; 154 unsigned long length = 0x10000; 155 int ret; 156 157 if (argc < 2) { 158 ret = 0; 159 goto cmd_err; 160 } 161 162 ret = CMD_RET_USAGE; 163 switch (argc) { 164 case 4: 165 if (strict_strtoul(argv[3], 16, &length) < 0) 166 goto cmd_err; 167 case 3: 168 if (strict_strtoul(argv[2], 10, &block) < 0) 169 goto cmd_err; 170 case 2: 171 if (strict_strtoul(argv[1], 10, &Testcounter) < 0) 172 goto cmd_err; 173 break; 174 } 175 176 if (length == 0) 177 length = N_16B_IN_BLK; 178 179 printf("Test range: 0x%08lx - 0x%08lx\n", DRAM_BASE + (block << MCR74_BLK_OFFSET), 180 DRAM_BASE | (block << MCR74_BLK_OFFSET) | ((length - 1) << MCR74_LEN_OFFSET) | 0xf); 181 182 ret = 1; 183 writel(0xfc600309, 0x1e6e0000); 184 while ((Testcounter > PassCnt) || (Testcounter == 0)) { 185 clrsetbits_le32(0x1e6e0074, MCR74_BLK_LEN_MASK, 186 (block << MCR74_BLK_OFFSET) | ((length - 1) << MCR74_LEN_OFFSET)); 187 188 if (!MMCTest()) { 189 printf("FAIL %d/%ld (fail DQ 0x%08x)\n", PassCnt, Testcounter, 190 readl(0x1e6e0078)); 191 ret = 0; 192 break; 193 } else { 194 PassCnt++; 195 printf("Pass %d/%ld\n", PassCnt, Testcounter); 196 } 197 } 198 199 return ret; 200 201 cmd_err: 202 print_usage(); 203 return ret; 204 } 205 206 U_BOOT_CMD( 207 dramtest, 5, 0, do_ast_dramtest, 208 "ASPEED DRAM BIST", 209 "" 210 ); 211